Skip to content

Commit 4e0b68c

Browse files
committed
[OpenACC] Implement warning restrictions for 'firstprivate'
'firstprivate' can't be generated unless we have a copy constructor, so this patch implements the restriction as a warning, and prevents the item from being added to the AST.
1 parent dd0737b commit 4e0b68c

File tree

4 files changed

+109
-14
lines changed

4 files changed

+109
-14
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13531,7 +13531,8 @@ def err_acc_device_type_multiple_archs
1353113531
def warn_acc_var_referenced_lacks_op
1353213532
: Warning<"variable of type %0 referenced in OpenACC '%1' clause does not "
1353313533
"have a %enum_select<AccVarReferencedReason>{%DefCtor{default "
13534-
"constructor}|%Dtor{destructor}}2; reference has no effect">,
13534+
"constructor}|%CopyCtor{copy constructor}|%Dtor{destructor}}2; "
13535+
"reference has no effect">,
1353513536
InGroup<DiagGroup<"openacc-var-lacks-operation">>,
1353613537
DefaultError;
1353713538

clang/include/clang/Sema/SemaOpenACC.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,6 @@ class SemaOpenACC : public SemaBase {
176176

177177
void checkFor();
178178

179-
// void checkRangeFor(); ?? ERICH
180-
// const ValueDecl *checkInit();
181-
// void checkCond(const ValueDecl *Init);
182-
// void checkInc(const ValueDecl *Init);
183179
public:
184180
// Checking for non-instantiation version of a Range-for.
185181
ForStmtBeginChecker(SemaOpenACC &SemaRef, SourceLocation ForLoc,

clang/lib/Sema/SemaOpenACC.cpp

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -642,21 +642,13 @@ ExprResult CheckVarType(SemaOpenACC &S, OpenACCClauseKind CK, Expr *VarExpr,
642642
if (!InnerExpr || InnerExpr->isTypeDependent())
643643
return VarExpr;
644644

645-
const auto *RD = InnerExpr->getType()->getAsCXXRecordDecl();
645+
auto *RD = InnerExpr->getType()->getAsCXXRecordDecl();
646646

647647
// if this isn't a C++ record decl, we can create/copy/destroy this thing at
648648
// will without problem, so this is a success.
649649
if (!RD)
650650
return VarExpr;
651651

652-
// TODO: OpenACC:
653-
// Private must have default ctor + dtor in InnerExpr
654-
// FirstPrivate must have copyctor + dtor in InnerExpr
655-
// Reduction must have copyctor + dtor + operation in InnerExpr
656-
657-
// TODO OpenACC: It isn't clear what the requirements are for default
658-
// constructor/copy constructor are for First private and reduction, but
659-
// private requires a default constructor.
660652
if (CK == OpenACCClauseKind::Private) {
661653
bool HasNonDeletedDefaultCtor =
662654
llvm::find_if(RD->ctors(), [](const CXXConstructorDecl *CD) {
@@ -669,6 +661,26 @@ ExprResult CheckVarType(SemaOpenACC &S, OpenACCClauseKind CK, Expr *VarExpr,
669661
<< clang::diag::AccVarReferencedReason::DefCtor;
670662
return ExprError();
671663
}
664+
} else if (CK == OpenACCClauseKind::FirstPrivate) {
665+
if (!RD->hasSimpleCopyConstructor()) {
666+
Sema::SpecialMemberOverloadResult SMOR = S.SemaRef.LookupSpecialMember(
667+
RD, CXXSpecialMemberKind::CopyConstructor, /*ConstArg=*/true,
668+
/*VolatileArg=*/false, /*RValueThis=*/false, /*ConstThis=*/false,
669+
/*VolatileThis=*/false);
670+
671+
if (SMOR.getKind() != Sema::SpecialMemberOverloadResult::Success ||
672+
SMOR.getMethod()->isDeleted()) {
673+
S.Diag(InnerExpr->getBeginLoc(),
674+
clang::diag::warn_acc_var_referenced_lacks_op)
675+
<< InnerExpr->getType() << CK
676+
<< clang::diag::AccVarReferencedReason::CopyCtor;
677+
return ExprError();
678+
}
679+
}
680+
} else if (CK == OpenACCClauseKind::Reduction) {
681+
// TODO: OpenACC:
682+
// Reduction must have copyctor + dtor + operation in InnerExpr I think?
683+
// Need to confirm when implementing this part.
672684
}
673685

674686
// All 3 things need to make sure they have a dtor.

clang/test/SemaOpenACC/private_firstprivate_reduction_required_ops.cpp

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,17 @@ struct ImplicitDelDtor {
3535
DeletedDtor d;
3636
};
3737

38+
struct DeletedCopy {
39+
DeletedCopy(const DeletedCopy&) = delete;
40+
};
41+
42+
struct DefaultedCopy {
43+
DefaultedCopy(const DefaultedCopy&) = default;
44+
};
45+
struct UserCopy {
46+
UserCopy(const UserCopy&);
47+
};
48+
3849
void private_uses(ImplicitCtorDtor &CDT, ImplDeletedCtor &IDC,
3950
DefaultedCtor &DefC, ImpledCtor &IC, DeletedCtor &DelC,
4051
ImpledDtor &ID, DefaultedDtor &DefD, DeletedDtor &DelD,
@@ -101,3 +112,78 @@ void inst(ImplicitCtorDtor &CDT, ImplDeletedCtor &IDC,
101112
// expected-note@+1{{in instantiation}}
102113
private_templ(IDD);
103114
}
115+
116+
void firstprivate_uses(ImplicitCtorDtor &CDT, ImplDeletedCtor &IDC,
117+
DefaultedCtor &DefC, ImpledCtor &IC, DeletedCtor &DelC,
118+
ImpledDtor &ID, DefaultedDtor &DefD, DeletedDtor &DelD,
119+
ImplicitDelDtor &IDD, DeletedCopy &DelCopy,
120+
DefaultedCopy &DefCopy, UserCopy &UDCopy) {
121+
#pragma acc parallel firstprivate(CDT)
122+
;
123+
124+
#pragma acc parallel firstprivate(IDC)
125+
;
126+
127+
#pragma acc parallel firstprivate(DefC)
128+
;
129+
130+
#pragma acc parallel firstprivate(IC)
131+
;
132+
133+
#pragma acc parallel firstprivate(DelC)
134+
;
135+
136+
#pragma acc parallel firstprivate(ID)
137+
;
138+
139+
#pragma acc parallel firstprivate(DefD)
140+
;
141+
142+
// expected-error@+1{{variable of type 'DeletedDtor' referenced in OpenACC 'firstprivate' clause does not have a destructor; reference has no effect}}
143+
#pragma acc parallel firstprivate(DelD)
144+
;
145+
146+
// expected-error@+1{{variable of type 'ImplicitDelDtor' referenced in OpenACC 'firstprivate' clause does not have a copy constructor; reference has no effect}}
147+
#pragma acc parallel firstprivate(IDD)
148+
;
149+
150+
// expected-error@+1{{variable of type 'DeletedCopy' referenced in OpenACC 'firstprivate' clause does not have a copy constructor; reference has no effect}}
151+
#pragma acc parallel firstprivate(DelCopy)
152+
;
153+
#pragma acc parallel firstprivate(DefCopy)
154+
;
155+
#pragma acc parallel firstprivate(UDCopy)
156+
;
157+
}
158+
159+
template<typename T>
160+
void firstprivate_template(T& t) {
161+
#pragma acc parallel firstprivate(t) // #FIRSTPRIV
162+
;
163+
}
164+
165+
void firstprivate_inst(ImplicitCtorDtor &CDT, ImplDeletedCtor &IDC,
166+
DefaultedCtor &DefC, ImpledCtor &IC, DeletedCtor &DelC,
167+
ImpledDtor &ID, DefaultedDtor &DefD, DeletedDtor &DelD,
168+
ImplicitDelDtor &IDD, DeletedCopy &DelCopy,
169+
DefaultedCopy &DefCopy, UserCopy &UDCopy) {
170+
firstprivate_template(CDT);
171+
firstprivate_template(IDC);
172+
firstprivate_template(DefC);
173+
firstprivate_template(IC);
174+
firstprivate_template(DelC);
175+
firstprivate_template(ID);
176+
firstprivate_template(DefD);
177+
// expected-error@#FIRSTPRIV{{variable of type 'DeletedDtor' referenced in OpenACC 'firstprivate' clause does not have a destructor; reference has no effect}}
178+
// expected-note@+1{{in instantiation}}
179+
firstprivate_template(DelD);
180+
// expected-error@#FIRSTPRIV{{variable of type 'ImplicitDelDtor' referenced in OpenACC 'firstprivate' clause does not have a copy constructor; reference has no effect}}
181+
// expected-note@+1{{in instantiation}}
182+
firstprivate_template(IDD);
183+
// expected-error@#FIRSTPRIV{{variable of type 'DeletedCopy' referenced in OpenACC 'firstprivate' clause does not have a copy constructor; reference has no effect}}
184+
// expected-note@+1{{in instantiation}}
185+
firstprivate_template(DelCopy);
186+
firstprivate_template(DefCopy);
187+
firstprivate_template(UDCopy);
188+
}
189+

0 commit comments

Comments
 (0)