diff options
-rw-r--r-- | clang/include/clang/Basic/Attr.td | 7 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGStmtOpenMP.cpp | 12 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 115 | ||||
-rw-r--r-- | clang/test/OpenMP/for_ast_print.cpp | 24 | ||||
-rw-r--r-- | clang/test/OpenMP/for_linear_messages.cpp | 2 | ||||
-rw-r--r-- | clang/test/OpenMP/for_simd_linear_messages.cpp | 2 | ||||
-rw-r--r-- | clang/test/OpenMP/parallel_for_linear_messages.cpp | 2 | ||||
-rw-r--r-- | clang/test/OpenMP/parallel_for_simd_linear_messages.cpp | 2 | ||||
-rw-r--r-- | clang/test/OpenMP/target_parallel_for_linear_messages.cpp | 2 |
9 files changed, 92 insertions, 76 deletions
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index b77a5337192..983f5346797 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2185,6 +2185,13 @@ def OMPThreadPrivateDecl : InheritableAttr { let Documentation = [Undocumented]; } +def OMPCaptureNoInit : InheritableAttr { + // This attribute has no spellings as it is only ever created implicitly. + let Spellings = []; + let SemaHandler = 0; + let Documentation = [Undocumented]; +} + def InternalLinkage : InheritableAttr { let Spellings = [GNU<"internal_linkage">, CXX11<"clang", "internal_linkage">]; let Subjects = SubjectList<[Var, Function, CXXRecord]>; diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 90d6a829e14..ddceb1b559c 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -18,6 +18,7 @@ #include "TargetInfo.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtOpenMP.h" +#include "clang/AST/DeclOpenMP.h" using namespace clang; using namespace CodeGen; @@ -30,8 +31,15 @@ class OMPLexicalScope { for (const auto *C : S.clauses()) { if (auto *CPI = OMPClauseWithPreInit::get(C)) { if (auto *PreInit = cast_or_null<DeclStmt>(CPI->getPreInitStmt())) { - for (const auto *I : PreInit->decls()) - CGF.EmitVarDecl(cast<VarDecl>(*I)); + for (const auto *I : PreInit->decls()) { + if (!I->hasAttr<OMPCaptureNoInitAttr>()) + CGF.EmitVarDecl(cast<VarDecl>(*I)); + else { + CodeGenFunction::AutoVarEmission Emission = + CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); + CGF.EmitAutoVarCleanups(Emission); + } + } } } } diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 86ad66f4a62..50148b5187c 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -1706,6 +1706,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id, Expr *CaptureExpr, bool WithInit) { + assert(CaptureExpr); ASTContext &C = S.getASTContext(); Expr *Init = CaptureExpr->IgnoreImpCasts(); QualType Ty = Init->getType(); @@ -1723,12 +1724,11 @@ static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id, WithInit = true; } auto *CED = OMPCapturedExprDecl::Create(C, S.CurContext, Id, Ty); + if (!WithInit) + CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C, SourceRange())); S.CurContext->addHiddenDecl(CED); - if (WithInit) - S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false, - /*TypeMayContainAuto=*/true); - else - S.ActOnUninitializedDecl(CED, /*TypeMayContainAuto=*/true); + S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false, + /*TypeMayContainAuto=*/true); return CED; } @@ -7676,7 +7676,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, } if (TopDVar.CKind == OMPC_firstprivate || (!IsOpenMPCapturedDecl(D) && - !cast<OMPCapturedExprDecl>(Ref->getDecl())->getInit())) { + Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) { ExprResult RefRes = DefaultLvalueConversion(Ref); if (!RefRes.isUsable()) continue; @@ -8277,7 +8277,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause( buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false); if (!IsOpenMPCapturedDecl(D)) { ExprCaptures.push_back(Ref->getDecl()); - if (!cast<OMPCapturedExprDecl>(Ref->getDecl())->getInit()) { + if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) { ExprResult RefRes = DefaultLvalueConversion(Ref); if (!RefRes.isUsable()) continue; @@ -8340,115 +8340,96 @@ OMPClause *Sema::ActOnOpenMPLinearClause( } for (auto &RefExpr : VarList) { assert(RefExpr && "NULL expr in OpenMP linear clause."); - if (isa<DependentScopeDeclRefExpr>(RefExpr)) { + SourceLocation ELoc; + SourceRange ERange; + Expr *SimpleRefExpr = RefExpr; + auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange, + /*AllowArraySection=*/false); + if (Res.second) { // It will be analyzed later. Vars.push_back(RefExpr); Privates.push_back(nullptr); Inits.push_back(nullptr); - continue; } - - // OpenMP [2.14.3.7, linear clause] - // A list item that appears in a linear clause is subject to the private - // clause semantics described in Section 2.14.3.3 on page 159 except as - // noted. In addition, the value of the new list item on each iteration - // of the associated loop(s) corresponds to the value of the original - // list item before entering the construct plus the logical number of - // the iteration times linear-step. - - SourceLocation ELoc = RefExpr->getExprLoc(); - // OpenMP [2.1, C/C++] - // A list item is a variable name. - // OpenMP [2.14.3.3, Restrictions, p.1] - // A variable that is part of another variable (as an array or - // structure element) cannot appear in a private clause. - DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr); - if (!DE || !isa<VarDecl>(DE->getDecl())) { - Diag(ELoc, diag::err_omp_expected_var_name_member_expr) - << 0 << RefExpr->getSourceRange(); + ValueDecl *D = Res.first; + if (!D) continue; - } - VarDecl *VD = cast<VarDecl>(DE->getDecl()); + QualType Type = D->getType(); + auto *VD = dyn_cast<VarDecl>(D); // OpenMP [2.14.3.7, linear clause] // A list-item cannot appear in more than one linear clause. // A list-item that appears in a linear clause cannot appear in any // other data-sharing attribute clause. - DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false); + DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, false); if (DVar.RefExpr) { Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind) << getOpenMPClauseName(OMPC_linear); - ReportOriginalDSA(*this, DSAStack, VD, DVar); - continue; - } - - QualType QType = VD->getType(); - if (QType->isDependentType() || QType->isInstantiationDependentType()) { - // It will be analyzed later. - Vars.push_back(DE); - Privates.push_back(nullptr); - Inits.push_back(nullptr); + ReportOriginalDSA(*this, DSAStack, D, DVar); continue; } // A variable must not have an incomplete type or a reference type. - if (RequireCompleteType(ELoc, QType, - diag::err_omp_linear_incomplete_type)) { + if (RequireCompleteType(ELoc, Type, + diag::err_omp_linear_incomplete_type)) continue; - } if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) && - !QType->isReferenceType()) { + !Type->isReferenceType()) { Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference) - << QType << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind); + << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind); continue; } - QType = QType.getNonReferenceType(); + Type = Type.getNonReferenceType(); // A list item must not be const-qualified. - if (QType.isConstant(Context)) { + if (Type.isConstant(Context)) { Diag(ELoc, diag::err_omp_const_variable) << getOpenMPClauseName(OMPC_linear); bool IsDecl = + !VD || VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; - Diag(VD->getLocation(), + Diag(D->getLocation(), IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << VD; + << D; continue; } // A list item must be of integral or pointer type. - QType = QType.getUnqualifiedType().getCanonicalType(); - const Type *Ty = QType.getTypePtrOrNull(); + Type = Type.getUnqualifiedType().getCanonicalType(); + const auto *Ty = Type.getTypePtrOrNull(); if (!Ty || (!Ty->isDependentType() && !Ty->isIntegralType(Context) && !Ty->isPointerType())) { - Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << QType; + Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type; bool IsDecl = + !VD || VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; - Diag(VD->getLocation(), + Diag(D->getLocation(), IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << VD; + << D; continue; } // Build private copy of original var. - auto *Private = buildVarDecl(*this, ELoc, QType, VD->getName(), - VD->hasAttrs() ? &VD->getAttrs() : nullptr); - auto *PrivateRef = buildDeclRefExpr( - *this, Private, DE->getType().getUnqualifiedType(), DE->getExprLoc()); + auto *Private = buildVarDecl(*this, ELoc, Type, D->getName(), + D->hasAttrs() ? &D->getAttrs() : nullptr); + auto *PrivateRef = buildDeclRefExpr(*this, Private, Type, ELoc); // Build var to save initial value. - VarDecl *Init = buildVarDecl(*this, ELoc, QType, ".linear.start"); + VarDecl *Init = buildVarDecl(*this, ELoc, Type, ".linear.start"); Expr *InitExpr; + DeclRefExpr *Ref = nullptr; + if (!VD) + Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true); if (LinKind == OMPC_LINEAR_uval) - InitExpr = VD->getInit(); + InitExpr = VD ? VD->getInit() : SimpleRefExpr; else - InitExpr = DE; + InitExpr = VD ? SimpleRefExpr : Ref; AddInitializerToDecl(Init, DefaultLvalueConversion(InitExpr).get(), - /*DirectInit*/ false, /*TypeMayContainAuto*/ false); - auto InitRef = buildDeclRefExpr( - *this, Init, DE->getType().getUnqualifiedType(), DE->getExprLoc()); - DSAStack->addDSA(VD, DE, OMPC_linear); - Vars.push_back(DE); + /*DirectInit=*/false, /*TypeMayContainAuto=*/false); + auto InitRef = buildDeclRefExpr(*this, Init, Type, ELoc); + + DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref); + Vars.push_back(VD ? RefExpr->IgnoreParens() : Ref); Privates.push_back(PrivateRef); Inits.push_back(InitRef); } diff --git a/clang/test/OpenMP/for_ast_print.cpp b/clang/test/OpenMP/for_ast_print.cpp index 38dafc0125d..182b395c13c 100644 --- a/clang/test/OpenMP/for_ast_print.cpp +++ b/clang/test/OpenMP/for_ast_print.cpp @@ -19,16 +19,22 @@ template <typename T> class S7 : public T { protected: T a; - S7() : a(0) {} + T &b; + typename T::type c:12; + typename T::type &d; + S7() : a(0), b(a), c(0), d(a.a) {} public: - S7(typename T::type v) : a(v) { + S7(typename T::type v) : a(v), b(a), c(v), d(a.a) { #pragma omp for private(a) private(this->a) private(T::a) for (int k = 0; k < a.a; ++k) ++this->a.a; #pragma omp for lastprivate(a) lastprivate(this->a) lastprivate(T::a) for (int k = 0; k < a.a; ++k) ++this->a.a; +#pragma omp for linear(val(c)) + for (int k = 0; k < a.a; ++k) + ++this->a.a; } S7 &operator=(S7 &s) { #pragma omp for private(a) private(this->a) @@ -37,16 +43,22 @@ public: #pragma omp for lastprivate(a) lastprivate(this->a) for (int k = 0; k < s.a.a; ++k) ++s.a.a; +#pragma omp for linear(uval(this->b)) + for (int k = 0; k < s.a.a; ++k) + ++s.a.a; return *this; } }; // CHECK: #pragma omp for private(this->a) private(this->a) private(this->S::a) // CHECK: #pragma omp for lastprivate(this->a) lastprivate(this->a) lastprivate(this->S::a) +// CHECK: #pragma omp for linear(val(this->c)) // CHECK: #pragma omp for private(this->a) private(this->a) private(T::a) // CHECK: #pragma omp for lastprivate(this->a) lastprivate(this->a) lastprivate(T::a) +// CHECK: #pragma omp for linear(val(this->c)) // CHECK: #pragma omp for private(this->a) private(this->a) // CHECK: #pragma omp for lastprivate(this->a) lastprivate(this->a) +// CHECK: #pragma omp for linear(uval(this->b)) class S8 : public S7<S> { S8() {} @@ -59,6 +71,9 @@ public: #pragma omp for lastprivate(a) lastprivate(this->a) lastprivate(S7<S>::a) for (int k = 0; k < a.a; ++k) ++this->a.a; +#pragma omp for linear(ref(S7<S>::d)) + for (int k = 0; k < a.a; ++k) + ++this->a.a; } S8 &operator=(S8 &s) { #pragma omp for private(a) private(this->a) @@ -67,14 +82,19 @@ public: #pragma omp for lastprivate(a) lastprivate(this->a) for (int k = 0; k < s.a.a; ++k) ++s.a.a; +#pragma omp for linear(this->c) + for (int k = 0; k < s.a.a; ++k) + ++s.a.a; return *this; } }; // CHECK: #pragma omp for private(this->a) private(this->a) private(this->S7<S>::a) // CHECK: #pragma omp for lastprivate(this->a) lastprivate(this->a) lastprivate(this->S7<S>::a) +// CHECK: #pragma omp for linear(ref(this->S7<S>::d)) // CHECK: #pragma omp for private(this->a) private(this->a) // CHECK: #pragma omp for lastprivate(this->a) lastprivate(this->a) +// CHECK: #pragma omp for linear(this->c) template <class T, int N> T tmain(T argc) { diff --git a/clang/test/OpenMP/for_linear_messages.cpp b/clang/test/OpenMP/for_linear_messages.cpp index 39fb21ef7be..ab8934979ac 100644 --- a/clang/test/OpenMP/for_linear_messages.cpp +++ b/clang/test/OpenMP/for_linear_messages.cpp @@ -212,7 +212,7 @@ int main(int argc, char **argv) { #pragma omp for linear(i) ordered(1) // expected-error {{'linear' clause cannot be specified along with 'ordered' clause with a parameter}} for (int k = 0; k < argc; ++k) ++k; - foomain<int,char>(argc,argv); + foomain<int,char>(argc,argv); // expected-note {{n instantiation of function template specialization 'foomain<int, char>' requested here}} return 0; } diff --git a/clang/test/OpenMP/for_simd_linear_messages.cpp b/clang/test/OpenMP/for_simd_linear_messages.cpp index 44370a15664..3f93125a38a 100644 --- a/clang/test/OpenMP/for_simd_linear_messages.cpp +++ b/clang/test/OpenMP/for_simd_linear_messages.cpp @@ -208,7 +208,7 @@ int main(int argc, char **argv) { #pragma omp for simd linear(i) for (int k = 0; k < argc; ++k) ++k; - foomain<int,char>(argc,argv); + foomain<int,char>(argc,argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}} return 0; } diff --git a/clang/test/OpenMP/parallel_for_linear_messages.cpp b/clang/test/OpenMP/parallel_for_linear_messages.cpp index 7272aada92a..e5f5b61873c 100644 --- a/clang/test/OpenMP/parallel_for_linear_messages.cpp +++ b/clang/test/OpenMP/parallel_for_linear_messages.cpp @@ -263,7 +263,7 @@ int main(int argc, char **argv) { for (int k = 0; k < argc; ++k) ++k; - foomain<int, char>(argc, argv); + foomain<int, char>(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}} return 0; } diff --git a/clang/test/OpenMP/parallel_for_simd_linear_messages.cpp b/clang/test/OpenMP/parallel_for_simd_linear_messages.cpp index 858f53f4674..fc1895a3685 100644 --- a/clang/test/OpenMP/parallel_for_simd_linear_messages.cpp +++ b/clang/test/OpenMP/parallel_for_simd_linear_messages.cpp @@ -208,7 +208,7 @@ int main(int argc, char **argv) { #pragma omp parallel for simd linear(i) for (int k = 0; k < argc; ++k) ++k; - foomain<int,char>(argc,argv); + foomain<int,char>(argc,argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}} return 0; } diff --git a/clang/test/OpenMP/target_parallel_for_linear_messages.cpp b/clang/test/OpenMP/target_parallel_for_linear_messages.cpp index c1694c0c499..36e897d5946 100644 --- a/clang/test/OpenMP/target_parallel_for_linear_messages.cpp +++ b/clang/test/OpenMP/target_parallel_for_linear_messages.cpp @@ -263,7 +263,7 @@ int main(int argc, char **argv) { for (int k = 0; k < argc; ++k) ++k; - foomain<int, char>(argc, argv); + foomain<int, char>(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}} return 0; } |