diff options
Diffstat (limited to 'clang/lib/Sema/SemaOpenMP.cpp')
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 107 |
1 files changed, 80 insertions, 27 deletions
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 59c4b49bfb1..7b702250b88 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -1080,6 +1080,43 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, iterator Iter) const { return false; } +static bool isConstNotMutableType(Sema &SemaRef, ValueDecl *D, + bool *IsClassType = nullptr) { + ASTContext &Context = SemaRef.getASTContext(); + QualType Type = D->getType().getNonReferenceType().getCanonicalType(); + bool IsConstant = Type.isConstant(Context); + Type = Context.getBaseElementType(Type); + const CXXRecordDecl *RD = + SemaRef.getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr; + if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD)) + if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate()) + RD = CTD->getTemplatedDecl(); + if (IsClassType) + *IsClassType = RD; + return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD && + RD->hasDefinition() && RD->hasMutableFields()); +} + +static bool rejectConstNotMutableType(Sema &SemaRef, ValueDecl *D, + OpenMPClauseKind CKind, + SourceLocation ELoc) { + ASTContext &Context = SemaRef.getASTContext(); + bool IsClassType; + if (isConstNotMutableType(SemaRef, D, &IsClassType)) { + SemaRef.Diag(ELoc, IsClassType ? diag::err_omp_const_not_mutable_variable + : diag::err_omp_const_variable) + << getOpenMPClauseName(CKind); + VarDecl *VD = dyn_cast<VarDecl>(D); + bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) == + VarDecl::DeclarationOnly; + SemaRef.Diag(D->getLocation(), + IsDecl ? diag::note_previous_decl : diag::note_defined_here) + << D; + return true; + } + return false; +} + const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) { D = getCanonicalDecl(D); @@ -1177,34 +1214,28 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, return DVar; } - QualType Type = D->getType().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 - // shared. - const CXXRecordDecl *RD = - SemaRef.getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr; - if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD)) - if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate()) - RD = CTD->getTemplatedDecl(); - if (IsConstant && - !(SemaRef.getLangOpts().CPlusPlus && RD && RD->hasDefinition() && - RD->hasMutableFields())) { - // Variables with const-qualified type having no mutable member may be - // listed in a firstprivate clause, even if they are static data members. - DSAVarData DVarTemp = hasInnermostDSA( - D, - [](OpenMPClauseKind C) { - return C == OMPC_firstprivate || C == OMPC_shared; - }, - MatchesAlways, FromParent); - if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr) - return DVarTemp; + // The predetermined shared attribute for const-qualified types having no + // mutable members was removed after OpenMP 3.1. + if (SemaRef.LangOpts.OpenMP <= 31) { + // 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 + // shared. + if (isConstNotMutableType(SemaRef, D)) { + // Variables with const-qualified type having no mutable member may be + // listed in a firstprivate clause, even if they are static data members. + DSAVarData DVarTemp = hasInnermostDSA( + D, + [](OpenMPClauseKind C) { + return C == OMPC_firstprivate || C == OMPC_shared; + }, + MatchesAlways, FromParent); + if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr) + return DVarTemp; - DVar.CKind = OMPC_shared; - return DVar; + DVar.CKind = OMPC_shared; + return DVar; + } } // Explicitly specified attributes and local variables with predetermined @@ -9791,6 +9822,17 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList, continue; Type = Type.getNonReferenceType(); + // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions] + // A variable that is privatized must not have a const-qualified type + // unless it is of class type with a mutable member. This restriction does + // not apply to the firstprivate clause. + // + // OpenMP 3.1 [2.9.3.3, private clause, Restrictions] + // A variable that appears in a private clause must not have a + // const-qualified type unless it is of class type with a mutable member. + if (rejectConstNotMutableType(*this, D, OMPC_private, ELoc)) + continue; + // 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 @@ -10212,6 +10254,17 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, continue; Type = Type.getNonReferenceType(); + // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions] + // A variable that is privatized must not have a const-qualified type + // unless it is of class type with a mutable member. This restriction does + // not apply to the firstprivate clause. + // + // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions] + // A variable that appears in a lastprivate clause must not have a + // const-qualified type unless it is of class type with a mutable member. + if (rejectConstNotMutableType(*this, D, OMPC_lastprivate, ELoc)) + continue; + OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective(); // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced // in a Construct] |