Author: abataev Date: Wed Mar 2 21:52:24 2016 New Revision: 262578 URL: http://llvm.org/viewvc/llvm-project?rev=262578&view=rev Log: [OPENMP 4.5] Initial support for data members in 'linear' clause.
OpenMP 4.5 allows to privatize data members of current class in member functions. Patch adds initial support for privatization of data members in 'linear' clause, no codegen support. Modified: cfe/trunk/include/clang/Basic/Attr.td cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp cfe/trunk/lib/Sema/SemaOpenMP.cpp cfe/trunk/test/OpenMP/for_ast_print.cpp cfe/trunk/test/OpenMP/for_linear_messages.cpp cfe/trunk/test/OpenMP/for_simd_linear_messages.cpp cfe/trunk/test/OpenMP/parallel_for_linear_messages.cpp cfe/trunk/test/OpenMP/parallel_for_simd_linear_messages.cpp cfe/trunk/test/OpenMP/target_parallel_for_linear_messages.cpp Modified: cfe/trunk/include/clang/Basic/Attr.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=262578&r1=262577&r2=262578&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/Attr.td (original) +++ cfe/trunk/include/clang/Basic/Attr.td Wed Mar 2 21:52:24 2016 @@ -2185,6 +2185,13 @@ def OMPThreadPrivateDecl : InheritableAt 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]>; Modified: cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp?rev=262578&r1=262577&r2=262578&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp (original) +++ cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp Wed Mar 2 21:52:24 2016 @@ -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); + } + } } } } Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=262578&r1=262577&r2=262578&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original) +++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Wed Mar 2 21:52:24 2016 @@ -1706,6 +1706,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMP 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 *buildCapture 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::ActOnOpenMPLastprivateC } 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::ActOnOpenMPReductionCla 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); } Modified: cfe/trunk/test/OpenMP/for_ast_print.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_ast_print.cpp?rev=262578&r1=262577&r2=262578&view=diff ============================================================================== --- cfe/trunk/test/OpenMP/for_ast_print.cpp (original) +++ cfe/trunk/test/OpenMP/for_ast_print.cpp Wed Mar 2 21:52:24 2016 @@ -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) { Modified: cfe/trunk/test/OpenMP/for_linear_messages.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_linear_messages.cpp?rev=262578&r1=262577&r2=262578&view=diff ============================================================================== --- cfe/trunk/test/OpenMP/for_linear_messages.cpp (original) +++ cfe/trunk/test/OpenMP/for_linear_messages.cpp Wed Mar 2 21:52:24 2016 @@ -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; } Modified: cfe/trunk/test/OpenMP/for_simd_linear_messages.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_simd_linear_messages.cpp?rev=262578&r1=262577&r2=262578&view=diff ============================================================================== --- cfe/trunk/test/OpenMP/for_simd_linear_messages.cpp (original) +++ cfe/trunk/test/OpenMP/for_simd_linear_messages.cpp Wed Mar 2 21:52:24 2016 @@ -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; } Modified: cfe/trunk/test/OpenMP/parallel_for_linear_messages.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_for_linear_messages.cpp?rev=262578&r1=262577&r2=262578&view=diff ============================================================================== --- cfe/trunk/test/OpenMP/parallel_for_linear_messages.cpp (original) +++ cfe/trunk/test/OpenMP/parallel_for_linear_messages.cpp Wed Mar 2 21:52:24 2016 @@ -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; } Modified: cfe/trunk/test/OpenMP/parallel_for_simd_linear_messages.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_for_simd_linear_messages.cpp?rev=262578&r1=262577&r2=262578&view=diff ============================================================================== --- cfe/trunk/test/OpenMP/parallel_for_simd_linear_messages.cpp (original) +++ cfe/trunk/test/OpenMP/parallel_for_simd_linear_messages.cpp Wed Mar 2 21:52:24 2016 @@ -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; } Modified: cfe/trunk/test/OpenMP/target_parallel_for_linear_messages.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/target_parallel_for_linear_messages.cpp?rev=262578&r1=262577&r2=262578&view=diff ============================================================================== --- cfe/trunk/test/OpenMP/target_parallel_for_linear_messages.cpp (original) +++ cfe/trunk/test/OpenMP/target_parallel_for_linear_messages.cpp Wed Mar 2 21:52:24 2016 @@ -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; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits