From e4d269c8913b3fba9c91f6dad738a86d2640040b Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Tue, 19 May 2015 07:46:42 +0000 Subject: [PATCH] [OPENMP] Fixed analysis of function arguments and their data sharing attributes. Added proper analysis for types of function arguments. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@237670 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaOpenMP.cpp | 118 ++++++++++++-------- test/OpenMP/for_firstprivate_messages.cpp | 9 +- test/OpenMP/for_lastprivate_messages.cpp | 9 +- test/OpenMP/for_private_messages.cpp | 9 +- test/OpenMP/single_copyprivate_messages.cpp | 7 +- 5 files changed, 102 insertions(+), 50 deletions(-) diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index dd3ff37c37..9d45f8213c 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -505,11 +505,11 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) { } QualType Type = D->getType().getNonReferenceType().getCanonicalType(); - bool IsConstant = Type.isConstant(SemaRef.getASTContext()); - while (Type->isArrayType()) { - QualType ElemType = cast(Type.getTypePtr())->getElementType(); - Type = ElemType.getNonReferenceType().getCanonicalType(); + if (auto *PVD = dyn_cast(D)) { + Type = PVD->getOriginalType().getNonReferenceType().getCanonicalType(); } + bool IsConstant = Type.isConstant(SemaRef.getASTContext()); + Type = SemaRef.getASTContext().getBaseElementType(Type); // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced // in a Construct, C/C++, predetermined, p.6] // Variables with const qualified type having no mutable member are @@ -663,6 +663,10 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) { continue; } auto *VD = cast(cast(DE)->getDecl()); + QualType Type = VD->getType(); + if (auto *PVD = dyn_cast(VD)) { + Type = PVD->getOriginalType(); + } auto DVar = DSAStack->getTopDSA(VD, false); if (DVar.CKind == OMPC_lastprivate) { // Generate helper private variable and initialize it with the @@ -671,8 +675,8 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) { // variable is not added to IdResolver, so the code in the OpenMP // region uses original variable for proper diagnostics. auto *VDPrivate = - buildVarDecl(*this, DE->getExprLoc(), - VD->getType().getUnqualifiedType(), VD->getName()); + buildVarDecl(*this, DE->getExprLoc(), Type.getUnqualifiedType(), + VD->getName()); ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false); if (VDPrivate->isInvalidDecl()) continue; @@ -4756,6 +4760,9 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef VarList, VarDecl *VD = cast(D); QualType Type = VD->getType(); + if (auto *PVD = dyn_cast(VD)) { + Type = PVD->getOriginalType(); + } if (Type->isDependentType() || Type->isInstantiationDependentType()) { // It will be analyzed later. Vars.push_back(DE); @@ -4781,14 +4788,6 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef VarList, continue; } - // OpenMP [2.9.3.3, Restrictions, C/C++, p.1] - // A variable of class type (or array thereof) that appears in a private - // clause requires an accessible, unambiguous default constructor for the - // class type. - while (Type->isArrayType()) { - Type = cast(Type.getTypePtr())->getElementType(); - } - // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced // in a Construct] // Variables with the predetermined data-sharing attributes may not be @@ -4804,19 +4803,22 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef VarList, continue; } + // OpenMP [2.9.3.3, Restrictions, C/C++, p.1] + // A variable of class type (or array thereof) that appears in a private + // clause requires an accessible, unambiguous default constructor for the + // class type. // Generate helper private variable and initialize it with the default // value. The address of the original variable is replaced by the address of // the new private variable in CodeGen. This new variable is not added to // IdResolver, so the code in the OpenMP region uses original variable for // proper diagnostics. - auto VDPrivate = - buildVarDecl(*this, DE->getExprLoc(), - VD->getType().getUnqualifiedType(), VD->getName()); + Type = Type.getUnqualifiedType(); + auto VDPrivate = buildVarDecl(*this, DE->getExprLoc(), Type, VD->getName()); ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false); if (VDPrivate->isInvalidDecl()) continue; - auto VDPrivateRefExpr = - buildDeclRefExpr(*this, VDPrivate, DE->getType(), DE->getExprLoc()); + auto VDPrivateRefExpr = buildDeclRefExpr( + *this, VDPrivate, DE->getType().getUnqualifiedType(), DE->getExprLoc()); DSAStack->addDSA(VD, DE, OMPC_private); Vars.push_back(DE); @@ -4890,6 +4892,9 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef VarList, VarDecl *VD = cast(D); QualType Type = VD->getType(); + if (auto *PVD = dyn_cast(VD)) { + Type = PVD->getOriginalType(); + } if (Type->isDependentType() || Type->isInstantiationDependentType()) { // It will be analyzed later. Vars.push_back(DE); @@ -4927,14 +4932,12 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef VarList, // A variable of class type (or array thereof) that appears in a private // clause requires an accessible, unambiguous copy constructor for the // class type. - Type = Context.getBaseElementType(Type).getNonReferenceType(); + auto ElemType = Context.getBaseElementType(Type).getNonReferenceType(); // If an implicit firstprivate variable found it was checked already. if (!IsImplicitClause) { DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false); - Type = Type.getNonReferenceType().getCanonicalType(); - bool IsConstant = Type.isConstant(Context); - Type = Context.getBaseElementType(Type); + bool IsConstant = ElemType.isConstant(Context); // OpenMP [2.4.13, Data-sharing Attribute Clauses] // A list item that specifies a given variable may not appear in more // than one clause on the same directive, except that a variable may be @@ -5017,8 +5020,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef VarList, } } - auto VDPrivate = buildVarDecl( - *this, ELoc, VD->getType().getUnqualifiedType(), VD->getName()); + Type = Type.getUnqualifiedType(); + auto VDPrivate = buildVarDecl(*this, ELoc, Type, VD->getName()); // Generate helper private variable and initialize it with the value of the // original variable. The address of the original variable is replaced by // the address of the new private variable in the CodeGen. This new variable @@ -5027,13 +5030,14 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef VarList, Expr *VDInitRefExpr = nullptr; // For arrays generate initializer for single element and replace it by the // original array element in CodeGen. - if (DE->getType()->isArrayType()) { - auto VDInit = buildVarDecl(*this, DE->getExprLoc(), Type, VD->getName()); - VDInitRefExpr = buildDeclRefExpr(*this, VDInit, Type, ELoc); + if (Type->isArrayType()) { + auto VDInit = + buildVarDecl(*this, DE->getExprLoc(), ElemType, VD->getName()); + VDInitRefExpr = buildDeclRefExpr(*this, VDInit, ElemType, ELoc); auto Init = DefaultLvalueConversion(VDInitRefExpr).get(); - auto *VDInitTemp = - buildVarDecl(*this, DE->getLocStart(), Type.getUnqualifiedType(), - ".firstprivate.temp"); + ElemType = ElemType.getUnqualifiedType(); + auto *VDInitTemp = buildVarDecl(*this, DE->getLocStart(), ElemType, + ".firstprivate.temp"); InitializedEntity Entity = InitializedEntity::InitializeVariable(VDInitTemp); InitializationKind Kind = InitializationKind::CreateCopy(ELoc, ELoc); @@ -5047,7 +5051,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef VarList, } else { auto *VDInit = buildVarDecl(*this, DE->getLocStart(), Type, ".firstprivate.temp"); - VDInitRefExpr = buildDeclRefExpr(*this, VDInit, Type, DE->getExprLoc()); + VDInitRefExpr = + buildDeclRefExpr(*this, VDInit, DE->getType(), DE->getExprLoc()); AddInitializerToDecl(VDPrivate, DefaultLvalueConversion(VDInitRefExpr).get(), /*DirectInit=*/false, /*TypeMayContainAuto=*/false); @@ -5109,6 +5114,9 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef VarList, VarDecl *VD = cast(D); QualType Type = VD->getType(); + if (auto *PVD = dyn_cast(VD)) { + Type = PVD->getOriginalType(); + } if (Type->isDependentType() || Type->isInstantiationDependentType()) { // It will be analyzed later. Vars.push_back(DE); @@ -5243,6 +5251,9 @@ OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef VarList, VarDecl *VD = cast(D); QualType Type = VD->getType(); + if (auto *PVD = dyn_cast(VD)) { + Type = PVD->getOriginalType(); + } if (Type->isDependentType() || Type->isInstantiationDependentType()) { // It will be analyzed later. Vars.push_back(DE); @@ -5452,6 +5463,9 @@ OMPClause *Sema::ActOnOpenMPReductionClause( auto D = DE->getDecl(); auto VD = cast(D); auto Type = VD->getType(); + if (auto *PVD = dyn_cast(VD)) { + Type = PVD->getOriginalType(); + } // OpenMP [2.9.3.3, Restrictions, C/C++, p.3] // A variable that appears in a private clause must not have an incomplete // type or a reference type. @@ -5782,6 +5796,9 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef VarList, Expr *Step, } QualType QType = VD->getType(); + if (auto *PVD = dyn_cast(VD)) { + QType = PVD->getOriginalType(); + } if (QType->isDependentType() || QType->isInstantiationDependentType()) { // It will be analyzed later. Vars.push_back(DE); @@ -5832,11 +5849,11 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef VarList, Expr *Step, } // Build var to save initial value. - VarDecl *Init = buildVarDecl(*this, ELoc, DE->getType(), ".linear.start"); + VarDecl *Init = buildVarDecl(*this, ELoc, QType, ".linear.start"); AddInitializerToDecl(Init, DefaultLvalueConversion(DE).get(), /*DirectInit*/ false, /*TypeMayContainAuto*/ false); - auto InitRef = - buildDeclRefExpr(*this, Init, DE->getType(), DE->getExprLoc()); + auto InitRef = buildDeclRefExpr( + *this, Init, DE->getType().getUnqualifiedType(), DE->getExprLoc()); DSAStack->addDSA(VD, DE, OMPC_linear); Vars.push_back(DE); Inits.push_back(InitRef); @@ -5904,8 +5921,9 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, // Build privatized reference to the current linear var. auto DE = cast(RefExpr); auto PrivateRef = - buildDeclRefExpr(SemaRef, cast(DE->getDecl()), DE->getType(), - DE->getExprLoc(), /*RefersToCapture=*/true); + buildDeclRefExpr(SemaRef, cast(DE->getDecl()), + DE->getType().getUnqualifiedType(), DE->getExprLoc(), + /*RefersToCapture=*/true); // Build update: Var = InitExpr + IV * Step ExprResult Update = @@ -5960,10 +5978,11 @@ OMPClause *Sema::ActOnOpenMPAlignedClause( // OpenMP [2.8.1, simd construct, Restrictions] // The type of list items appearing in the aligned clause must be // array, pointer, reference to array, or reference to pointer. - QualType QType = DE->getType() - .getNonReferenceType() - .getUnqualifiedType() - .getCanonicalType(); + QualType QType = VD->getType(); + if (auto *PVD = dyn_cast(VD)) { + QType = PVD->getOriginalType(); + } + QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType(); const Type *Ty = QType.getTypePtrOrNull(); if (!Ty || (!Ty->isDependentType() && !Ty->isArrayType() && !Ty->isPointerType())) { @@ -6042,6 +6061,9 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef VarList, VarDecl *VD = cast(D); QualType Type = VD->getType(); + if (auto *PVD = dyn_cast(VD)) { + Type = PVD->getOriginalType(); + } if (Type->isDependentType() || Type->isInstantiationDependentType()) { // It will be analyzed later. Vars.push_back(DE); @@ -6064,14 +6086,15 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef VarList, // A variable of class type (or array thereof) that appears in a // copyin clause requires an accessible, unambiguous copy assignment // operator for the class type. - Type = Context.getBaseElementType(Type).getNonReferenceType(); + auto ElemType = Context.getBaseElementType(Type).getNonReferenceType(); auto *SrcVD = buildVarDecl(*this, DE->getLocStart(), - Type.getUnqualifiedType(), ".copyin.src"); + ElemType.getUnqualifiedType(), ".copyin.src"); auto *PseudoSrcExpr = buildDeclRefExpr( - *this, SrcVD, Type.getUnqualifiedType(), DE->getExprLoc()); - auto *DstVD = buildVarDecl(*this, DE->getLocStart(), Type, ".copyin.dst"); + *this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc()); + auto *DstVD = + buildVarDecl(*this, DE->getLocStart(), ElemType, ".copyin.dst"); auto *PseudoDstExpr = - buildDeclRefExpr(*this, DstVD, Type, DE->getExprLoc()); + buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc()); // For arrays generate assignment operation for single element and replace // it by the original array element in CodeGen. auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, @@ -6131,6 +6154,9 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef VarList, VarDecl *VD = cast(D); QualType Type = VD->getType(); + if (auto *PVD = dyn_cast(VD)) { + Type = PVD->getOriginalType(); + } if (Type->isDependentType() || Type->isInstantiationDependentType()) { // It will be analyzed later. Vars.push_back(DE); diff --git a/test/OpenMP/for_firstprivate_messages.cpp b/test/OpenMP/for_firstprivate_messages.cpp index a7333718c5..de24bede7b 100644 --- a/test/OpenMP/for_firstprivate_messages.cpp +++ b/test/OpenMP/for_firstprivate_messages.cpp @@ -35,7 +35,7 @@ extern const int f; class S4 { int a; S4(); - S4(const S4 &s4); // expected-note 2 {{implicitly declared private here}} + S4(const S4 &s4); // expected-note 3 {{implicitly declared private here}} public: S4(int v) : a(v) {} @@ -152,6 +152,13 @@ int foomain(int argc, char **argv) { return 0; } +void bar(S4 a[2]) { +#pragma omp parallel +#pragma omp for firstprivate(a) // expected-error {{calling a private constructor of class 'S4'}} + for (int i = 0; i < 2; ++i) + foo(); +} + namespace A { double x; #pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}} diff --git a/test/OpenMP/for_lastprivate_messages.cpp b/test/OpenMP/for_lastprivate_messages.cpp index 632ed8446c..49485aa0df 100644 --- a/test/OpenMP/for_lastprivate_messages.cpp +++ b/test/OpenMP/for_lastprivate_messages.cpp @@ -36,7 +36,7 @@ const S3 ca[5]; // expected-note {{global variable is predetermined as share extern const int f; // expected-note {{global variable is predetermined as shared}} class S4 { int a; - S4(); // expected-note 3 {{implicitly declared private here}} + S4(); // expected-note 4 {{implicitly declared private here}} S4(const S4 &s4); public: @@ -142,6 +142,13 @@ int foomain(int argc, char **argv) { return 0; } +void bar(S4 a[2]) { +#pragma omp parallel +#pragma omp for lastprivate(a) // expected-error {{calling a private constructor of class 'S4'}} + for (int i = 0; i < 2; ++i) + foo(); +} + namespace A { double x; #pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}} diff --git a/test/OpenMP/for_private_messages.cpp b/test/OpenMP/for_private_messages.cpp index 635a17d6e5..90793f38af 100644 --- a/test/OpenMP/for_private_messages.cpp +++ b/test/OpenMP/for_private_messages.cpp @@ -26,7 +26,7 @@ public: const S3 ca[5]; class S4 { int a; - S4(); // expected-note {{implicitly declared private here}} + S4(); // expected-note 2 {{implicitly declared private here}} public: S4(int v) : a(v) {} @@ -108,6 +108,13 @@ int foomain(I argc, C **argv) { return 0; } +void bar(S4 a[2]) { +#pragma omp parallel +#pragma omp for private(a) // expected-error {{calling a private constructor of class 'S4'}} + for (int i = 0; i < 2; ++i) + foo(); +} + namespace A { double x; #pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}} diff --git a/test/OpenMP/single_copyprivate_messages.cpp b/test/OpenMP/single_copyprivate_messages.cpp index 793b4d5d0a..cb31f0cd10 100644 --- a/test/OpenMP/single_copyprivate_messages.cpp +++ b/test/OpenMP/single_copyprivate_messages.cpp @@ -21,7 +21,7 @@ public: class S4 { int a; S4(); - S4 &operator=(const S4 &s4); // expected-note 3 {{implicitly declared private here}} + S4 &operator=(const S4 &s4); // expected-note 4 {{implicitly declared private here}} public: S4(int v) : a(v) {} @@ -105,6 +105,11 @@ T tmain(T argc, C **argv) { return T(); } +void bar(S4 a[2]) { +#pragma omp single copyprivate(a) // expected-error {{'operator=' is a private member of 'S4'}} + foo(); +} + namespace A { double x; #pragma omp threadprivate(x) -- 2.40.0