diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp')
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp | 1467 |
1 files changed, 1025 insertions, 442 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp index 6060e5b75c22..36048a38b999 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp @@ -22,6 +22,7 @@ #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtOpenMP.h" #include "clang/AST/StmtVisitor.h" +#include "clang/AST/TypeOrdering.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" @@ -138,12 +139,15 @@ private: /// 'ordered' clause, the second one is true if the regions has 'ordered' /// clause, false otherwise. llvm::Optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion; + unsigned AssociatedLoops = 1; + const Decl *PossiblyLoopCounter = nullptr; bool NowaitRegion = false; bool CancelRegion = false; - unsigned AssociatedLoops = 1; + bool LoopStart = false; SourceLocation InnerTeamsRegionLoc; /// Reference to the taskgroup task_reduction reference expression. Expr *TaskgroupReductionRef = nullptr; + llvm::DenseSet<QualType> MappedClassesQualTypes; SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name, Scope *CurScope, SourceLocation Loc) : Directive(DKind), DirectiveName(Name), CurScope(CurScope), @@ -162,6 +166,9 @@ private: OpenMPClauseKind ClauseKindMode = OMPC_unknown; Sema &SemaRef; bool ForceCapturing = false; + /// true if all the vaiables in the target executable directives must be + /// captured by reference. + bool ForceCaptureByReferenceInTargetExecutable = false; CriticalsWithHintsTy Criticals; using iterator = StackTy::const_reverse_iterator; @@ -177,6 +184,9 @@ private: Stack.back().first.empty(); } + /// Vector of previously declared requires directives + SmallVector<const OMPRequiresDecl *, 2> RequiresDecls; + public: explicit DSAStackTy(Sema &S) : SemaRef(S) {} @@ -190,6 +200,13 @@ public: bool isForceVarCapturing() const { return ForceCapturing; } void setForceVarCapturing(bool V) { ForceCapturing = V; } + void setForceCaptureByReferenceInTargetExecutable(bool V) { + ForceCaptureByReferenceInTargetExecutable = V; + } + bool isForceCaptureByReferenceInTargetExecutable() const { + return ForceCaptureByReferenceInTargetExecutable; + } + void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc) { if (Stack.empty() || @@ -205,6 +222,33 @@ public: Stack.back().first.pop_back(); } + /// Marks that we're started loop parsing. + void loopInit() { + assert(isOpenMPLoopDirective(getCurrentDirective()) && + "Expected loop-based directive."); + Stack.back().first.back().LoopStart = true; + } + /// Start capturing of the variables in the loop context. + void loopStart() { + assert(isOpenMPLoopDirective(getCurrentDirective()) && + "Expected loop-based directive."); + Stack.back().first.back().LoopStart = false; + } + /// true, if variables are captured, false otherwise. + bool isLoopStarted() const { + assert(isOpenMPLoopDirective(getCurrentDirective()) && + "Expected loop-based directive."); + return !Stack.back().first.back().LoopStart; + } + /// Marks (or clears) declaration as possibly loop counter. + void resetPossibleLoopCounter(const Decl *D = nullptr) { + Stack.back().first.back().PossiblyLoopCounter = + D ? D->getCanonicalDecl() : D; + } + /// Gets the possible loop counter decl. + const Decl *getPossiblyLoopCunter() const { + return Stack.back().first.back().PossiblyLoopCounter; + } /// Start new OpenMP region stack in new non-capturing function. void pushFunction() { const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction(); @@ -352,6 +396,33 @@ public: return std::next(Stack.back().first.rbegin())->Directive; } + /// Add requires decl to internal vector + void addRequiresDecl(OMPRequiresDecl *RD) { + RequiresDecls.push_back(RD); + } + + /// Checks for a duplicate clause amongst previously declared requires + /// directives + bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const { + bool IsDuplicate = false; + for (OMPClause *CNew : ClauseList) { + for (const OMPRequiresDecl *D : RequiresDecls) { + for (const OMPClause *CPrev : D->clauselists()) { + if (CNew->getClauseKind() == CPrev->getClauseKind()) { + SemaRef.Diag(CNew->getBeginLoc(), + diag::err_omp_requires_clause_redeclaration) + << getOpenMPClauseName(CNew->getClauseKind()); + SemaRef.Diag(CPrev->getBeginLoc(), + diag::note_omp_requires_previous_clause) + << getOpenMPClauseName(CPrev->getClauseKind()); + IsDuplicate = true; + } + } + } + } + return IsDuplicate; + } + /// Set default data sharing attribute to none. void setDefaultDSANone(SourceLocation Loc) { assert(!isStackEmpty()); @@ -591,17 +662,34 @@ public: return llvm::make_range(StackElem.DoacrossDepends.end(), StackElem.DoacrossDepends.end()); } + + // Store types of classes which have been explicitly mapped + void addMappedClassesQualTypes(QualType QT) { + SharingMapTy &StackElem = Stack.back().first.back(); + StackElem.MappedClassesQualTypes.insert(QT); + } + + // Return set of mapped classes types + bool isClassPreviouslyMapped(QualType QT) const { + const SharingMapTy &StackElem = Stack.back().first.back(); + return StackElem.MappedClassesQualTypes.count(QT) != 0; + } + }; -bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) { - return isOpenMPParallelDirective(DKind) || isOpenMPTaskingDirective(DKind) || - isOpenMPTeamsDirective(DKind) || DKind == OMPD_unknown; + +bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) { + return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind); +} + +bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) { + return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) || DKind == OMPD_unknown; } } // namespace static const Expr *getExprAsWritten(const Expr *E) { - if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(E)) - E = ExprTemp->getSubExpr(); + if (const auto *FE = dyn_cast<FullExpr>(E)) + E = FE->getSubExpr(); if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) E = MTE->GetTemporaryExpr(); @@ -735,7 +823,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(iterator &Iter, DVar.CKind = OMPC_firstprivate; return DVar; } - } while (I != E && !isParallelOrTaskRegion(I->Directive)); + } while (I != E && !isImplicitTaskingRegion(I->Directive)); DVar.CKind = (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared; return DVar; @@ -982,7 +1070,7 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, iterator Iter) const { if (!isStackEmpty()) { iterator I = Iter, E = Stack.back().first.rend(); Scope *TopScope = nullptr; - while (I != E && !isParallelOrTaskRegion(I->Directive) && + while (I != E && !isImplicitOrExplicitTaskingRegion(I->Directive) && !isOpenMPTargetExecutionDirective(I->Directive)) ++I; if (I == E) @@ -996,6 +1084,51 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, iterator Iter) const { return false; } +static bool isConstNotMutableType(Sema &SemaRef, QualType Type, + bool AcceptIfMutable = true, + bool *IsClassType = nullptr) { + ASTContext &Context = SemaRef.getASTContext(); + Type = Type.getNonReferenceType().getCanonicalType(); + bool IsConstant = Type.isConstant(Context); + Type = Context.getBaseElementType(Type); + const CXXRecordDecl *RD = AcceptIfMutable && 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, const ValueDecl *D, + QualType Type, OpenMPClauseKind CKind, + SourceLocation ELoc, + bool AcceptIfMutable = true, + bool ListItemNotVar = false) { + ASTContext &Context = SemaRef.getASTContext(); + bool IsClassType; + if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) { + unsigned Diag = ListItemNotVar + ? diag::err_omp_const_list_item + : IsClassType ? diag::err_omp_const_not_mutable_variable + : diag::err_omp_const_variable; + SemaRef.Diag(ELoc, Diag) << getOpenMPClauseName(CKind); + if (!ListItemNotVar && D) { + const 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); @@ -1093,31 +1226,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 = - hasDSA(D, [](OpenMPClauseKind C) { return C == OMPC_firstprivate; }, - MatchesAlways, FromParent); - if (DVarTemp.CKind == OMPC_firstprivate && 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->getType())) { + // 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 @@ -1166,7 +1296,7 @@ DSAStackTy::hasDSA(ValueDecl *D, if (FromParent && I != EndI) std::advance(I, 1); for (; I != EndI; std::advance(I, 1)) { - if (!DPred(I->Directive) && !isParallelOrTaskRegion(I->Directive)) + if (!DPred(I->Directive) && !isImplicitOrExplicitTaskingRegion(I->Directive)) continue; iterator NewI = I; DSAVarData DVar = getDSA(NewI, D); @@ -1206,10 +1336,16 @@ bool DSAStackTy::hasExplicitDSA( return false; std::advance(StartI, Level); auto I = StartI->SharingMap.find(D); - return (I != StartI->SharingMap.end()) && + if ((I != StartI->SharingMap.end()) && I->getSecond().RefExpr.getPointer() && CPred(I->getSecond().Attributes) && - (!NotLastprivate || !I->getSecond().RefExpr.getInt()); + (!NotLastprivate || !I->getSecond().RefExpr.getInt())) + return true; + // Check predetermined rules for the loop control variables. + auto LI = StartI->LCVMap.find(D); + if (LI != StartI->LCVMap.end()) + return CPred(OMPC_private); + return false; } bool DSAStackTy::hasExplicitDirective( @@ -1376,6 +1512,8 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level) const { // By default, all the data that has a scalar type is mapped by copy // (except for reduction variables). IsByRef = + (DSAStack->isForceCaptureByReferenceInTargetExecutable() && + !Ty->isAnyPointerType()) || !Ty->isScalarType() || DSAStack->getDefaultDMAAtLevel(Level) == DMA_tofrom_scalar || DSAStack->hasExplicitDSA( @@ -1385,10 +1523,12 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level) const { if (IsByRef && Ty.getNonReferenceType()->isScalarType()) { IsByRef = - !DSAStack->hasExplicitDSA( - D, - [](OpenMPClauseKind K) -> bool { return K == OMPC_firstprivate; }, - Level, /*NotLastprivate=*/true) && + ((DSAStack->isForceCaptureByReferenceInTargetExecutable() && + !Ty->isAnyPointerType()) || + !DSAStack->hasExplicitDSA( + D, + [](OpenMPClauseKind K) -> bool { return K == OMPC_firstprivate; }, + Level, /*NotLastprivate=*/true)) && // If the variable is artificial and must be captured by value - try to // capture by value. !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() && @@ -1425,7 +1565,7 @@ bool Sema::isInOpenMPTargetExecutionDirective() const { false); } -VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D) const { +VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D) { assert(LangOpts.OpenMP && "OpenMP is not allowed"); D = getCanonicalDecl(D); @@ -1433,13 +1573,65 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D) const { // 'target' we return true so that this global is also mapped to the device. // auto *VD = dyn_cast<VarDecl>(D); - if (VD && !VD->hasLocalStorage() && isInOpenMPTargetExecutionDirective()) { - // If the declaration is enclosed in a 'declare target' directive, - // then it should not be captured. - // - if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) + if (VD && !VD->hasLocalStorage()) { + if (isInOpenMPDeclareTargetContext() && + (getCurCapturedRegion() || getCurBlock() || getCurLambda())) { + // Try to mark variable as declare target if it is used in capturing + // regions. + if (!OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) + checkDeclIsAllowedInOpenMPTarget(nullptr, VD); return nullptr; - return VD; + } else if (isInOpenMPTargetExecutionDirective()) { + // If the declaration is enclosed in a 'declare target' directive, + // then it should not be captured. + // + if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) + return nullptr; + return VD; + } + } + // Capture variables captured by reference in lambdas for target-based + // directives. + if (VD && !DSAStack->isClauseParsingMode()) { + if (const auto *RD = VD->getType() + .getCanonicalType() + .getNonReferenceType() + ->getAsCXXRecordDecl()) { + bool SavedForceCaptureByReferenceInTargetExecutable = + DSAStack->isForceCaptureByReferenceInTargetExecutable(); + DSAStack->setForceCaptureByReferenceInTargetExecutable(/*V=*/true); + if (RD->isLambda()) { + llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; + FieldDecl *ThisCapture; + RD->getCaptureFields(Captures, ThisCapture); + for (const LambdaCapture &LC : RD->captures()) { + if (LC.getCaptureKind() == LCK_ByRef) { + VarDecl *VD = LC.getCapturedVar(); + DeclContext *VDC = VD->getDeclContext(); + if (!VDC->Encloses(CurContext)) + continue; + DSAStackTy::DSAVarData DVarPrivate = + DSAStack->getTopDSA(VD, /*FromParent=*/false); + // Do not capture already captured variables. + if (!OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && + DVarPrivate.CKind == OMPC_unknown && + !DSAStack->checkMappableExprComponentListsForDecl( + D, /*CurrentRegionOnly=*/true, + [](OMPClauseMappableExprCommon:: + MappableExprComponentListRef, + OpenMPClauseKind) { return true; })) + MarkVariableReferenced(LC.getLocation(), LC.getCapturedVar()); + } else if (LC.getCaptureKind() == LCK_This) { + QualType ThisTy = getCurrentThisType(); + if (!ThisTy.isNull() && + Context.typesAreCompatible(ThisTy, ThisCapture->getType())) + CheckCXXThisCapture(LC.getLocation()); + } + } + } + DSAStack->setForceCaptureByReferenceInTargetExecutable( + SavedForceCaptureByReferenceInTargetExecutable); + } } if (DSAStack->getCurrentDirective() != OMPD_unknown && @@ -1448,7 +1640,7 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D) const { auto &&Info = DSAStack->isLoopControlVariable(D); if (Info.first || (VD && VD->hasLocalStorage() && - isParallelOrTaskRegion(DSAStack->getCurrentDirective())) || + isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) || (VD && DSAStack->isForceVarCapturing())) return VD ? VD : Info.second; DSAStackTy::DSAVarData DVarPrivate = @@ -1471,8 +1663,28 @@ void Sema::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex, FunctionScopesIndex -= Regions.size(); } +void Sema::startOpenMPLoop() { + assert(LangOpts.OpenMP && "OpenMP must be enabled."); + if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) + DSAStack->loopInit(); +} + bool Sema::isOpenMPPrivateDecl(const ValueDecl *D, unsigned Level) const { assert(LangOpts.OpenMP && "OpenMP is not allowed"); + if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) { + if (DSAStack->getAssociatedLoops() > 0 && + !DSAStack->isLoopStarted()) { + DSAStack->resetPossibleLoopCounter(D); + DSAStack->loopStart(); + return true; + } + if ((DSAStack->getPossiblyLoopCunter() == D->getCanonicalDecl() || + DSAStack->isLoopControlVariable(D).first) && + !DSAStack->hasExplicitDSA( + D, [](OpenMPClauseKind K) { return K != OMPC_private; }, Level) && + !isOpenMPSimdDirective(DSAStack->getCurrentDirective())) + return true; + } return DSAStack->hasExplicitDSA( D, [](OpenMPClauseKind K) { return K == OMPC_private; }, Level) || (DSAStack->isClauseParsingMode() && @@ -1788,7 +2000,7 @@ public: bool VisitDeclRefExpr(const DeclRefExpr *E) { if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) { if (VD->hasLocalStorage()) { - SemaRef.Diag(E->getLocStart(), + SemaRef.Diag(E->getBeginLoc(), diag::err_omp_local_var_in_threadprivate_init) << E->getSourceRange(); SemaRef.Diag(VD->getLocation(), diag::note_defined_here) @@ -1890,6 +2102,30 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) { return D; } +Sema::DeclGroupPtrTy +Sema::ActOnOpenMPRequiresDirective(SourceLocation Loc, + ArrayRef<OMPClause *> ClauseList) { + OMPRequiresDecl *D = nullptr; + if (!CurContext->isFileContext()) { + Diag(Loc, diag::err_omp_invalid_scope) << "requires"; + } else { + D = CheckOMPRequiresDecl(Loc, ClauseList); + if (D) { + CurContext->addDecl(D); + DSAStack->addRequiresDecl(D); + } + } + return DeclGroupPtrTy::make(DeclGroupRef(D)); +} + +OMPRequiresDecl *Sema::CheckOMPRequiresDecl(SourceLocation Loc, + ArrayRef<OMPClause *> ClauseList) { + if (!DSAStack->hasDuplicateRequiresClause(ClauseList)) + return OMPRequiresDecl::Create(Context, getCurLexicalContext(), Loc, + ClauseList); + return nullptr; +} + static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack, const ValueDecl *D, const DSAStackTy::DSAVarData &DVar, @@ -1958,6 +2194,30 @@ class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> { Sema::VarsWithInheritedDSAType VarsWithInheritedDSA; llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations; + void VisitSubCaptures(OMPExecutableDirective *S) { + // Check implicitly captured variables. + if (!S->hasAssociatedStmt() || !S->getAssociatedStmt()) + return; + for (const CapturedStmt::Capture &Cap : + S->getInnermostCapturedStmt()->captures()) { + if (!Cap.capturesVariable()) + continue; + VarDecl *VD = Cap.getCapturedVar(); + // Do not try to map the variable if it or its sub-component was mapped + // already. + if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) && + Stack->checkMappableExprComponentListsForDecl( + VD, /*CurrentRegionOnly=*/true, + [](OMPClauseMappableExprCommon::MappableExprComponentListRef, + OpenMPClauseKind) { return true; })) + continue; + DeclRefExpr *DRE = buildDeclRefExpr( + SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context), + Cap.getLocation(), /*RefersToCapture=*/true); + Visit(DRE); + } + } + public: void VisitDeclRefExpr(DeclRefExpr *E) { if (E->isTypeDependent() || E->isValueDependent() || @@ -1988,7 +2248,7 @@ public: // attribute, must have its data-sharing attribute explicitly determined // by being listed in a data-sharing attribute clause. if (DVar.CKind == OMPC_unknown && Stack->getDefaultDSA() == DSA_none && - isParallelOrTaskRegion(DKind) && + isImplicitOrExplicitTaskingRegion(DKind) && VarsWithInheritedDSA.count(VD) == 0) { VarsWithInheritedDSA[VD] = E; return; @@ -2065,7 +2325,7 @@ public: return; auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl()); OpenMPDirectiveKind DKind = Stack->getCurrentDirective(); - if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) { + if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParens())) { if (!FD) return; DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false); @@ -2092,6 +2352,12 @@ public: // if (FD->isBitField()) return; + + // Check to see if the member expression is referencing a class that + // has already been explicitly mapped + if (Stack->isClassPreviouslyMapped(TE->getType())) + return; + ImplicitMap.emplace_back(E); return; } @@ -2118,8 +2384,14 @@ public: // Define implicit data-sharing attributes for task. DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false); if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared && - !Stack->isLoopControlVariable(FD).first) - ImplicitFirstprivate.push_back(E); + !Stack->isLoopControlVariable(FD).first) { + // Check if there is a captured expression for the current field in the + // region. Do not mark it as firstprivate unless there is no captured + // expression. + // TODO: try to make it firstprivate. + if (DVar.CKind != OMPC_unknown) + ImplicitFirstprivate.push_back(E); + } return; } if (isOpenMPTargetExecutionDirective(DKind)) { @@ -2179,11 +2451,16 @@ public: } } } + // Check implicitly captured variables. + VisitSubCaptures(S); } void VisitStmt(Stmt *S) { for (Stmt *C : S->children()) { - if (C && !isa<OMPExecutableDirective>(C)) + if (C) { + // Check implicitly captured variables in the task-based directives to + // check if they must be firstprivatized. Visit(C); + } } } @@ -2535,6 +2812,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { case OMPD_declare_simd: case OMPD_declare_target: case OMPD_end_declare_target: + case OMPD_requires: llvm_unreachable("OpenMP Directive is not allowed"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); @@ -2568,7 +2846,7 @@ static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id, WithInit = true; } auto *CED = OMPCapturedExprDecl::Create(C, S.CurContext, Id, Ty, - CaptureExpr->getLocStart()); + CaptureExpr->getBeginLoc()); if (!WithInit) CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C)); S.CurContext->addHiddenDecl(CED); @@ -2705,20 +2983,20 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S, ? SC->getFirstScheduleModifierLoc() : SC->getSecondScheduleModifierLoc(), diag::err_omp_schedule_nonmonotonic_ordered) - << SourceRange(OC->getLocStart(), OC->getLocEnd()); + << SourceRange(OC->getBeginLoc(), OC->getEndLoc()); ErrorFound = true; } if (!LCs.empty() && OC && OC->getNumForLoops()) { for (const OMPLinearClause *C : LCs) { - Diag(C->getLocStart(), diag::err_omp_linear_ordered) - << SourceRange(OC->getLocStart(), OC->getLocEnd()); + Diag(C->getBeginLoc(), diag::err_omp_linear_ordered) + << SourceRange(OC->getBeginLoc(), OC->getEndLoc()); } ErrorFound = true; } if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) && isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC && OC->getNumForLoops()) { - Diag(OC->getLocStart(), diag::err_omp_ordered_simd) + Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd) << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); ErrorFound = true; } @@ -2820,11 +3098,13 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, } return false; } - // Allow some constructs (except teams) to be orphaned (they could be - // used in functions, called from OpenMP regions with the required - // preconditions). + // Allow some constructs (except teams and cancellation constructs) to be + // orphaned (they could be used in functions, called from OpenMP regions + // with the required preconditions). if (ParentRegion == OMPD_unknown && - !isOpenMPNestingTeamsDirective(CurrentRegion)) + !isOpenMPNestingTeamsDirective(CurrentRegion) && + CurrentRegion != OMPD_cancellation_point && + CurrentRegion != OMPD_cancel) return false; if (CurrentRegion == OMPD_cancellation_point || CurrentRegion == OMPD_cancel) { @@ -2853,6 +3133,7 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, (CancelRegion == OMPD_sections && (ParentRegion == OMPD_section || ParentRegion == OMPD_sections || ParentRegion == OMPD_parallel_sections))); + OrphanSeen = ParentRegion == OMPD_unknown; } else if (CurrentRegion == OMPD_master) { // OpenMP [2.16, Nesting of Regions] // A master region may not be closely nested inside a worksharing, @@ -2997,7 +3278,7 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, // the directive. OpenMPDirectiveKind CurNM = IC->getNameModifier(); if (FoundNameModifiers[CurNM]) { - S.Diag(C->getLocStart(), diag::err_omp_more_one_clause) + S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause) << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if) << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM); ErrorFound = true; @@ -3031,7 +3312,7 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, // all if clauses on the directive must include a directive-name-modifier. if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) { if (NamedModifiersNumber == AllowedNameModifiers.size()) { - S.Diag(FoundNameModifiers[OMPD_unknown]->getLocStart(), + S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(), diag::err_omp_no_more_if_clause); } else { std::string Values; @@ -3053,7 +3334,7 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, ++AllowedCnt; } } - S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getLocStart(), + S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(), diag::err_omp_unnamed_if_clause) << (TotalAllowedNum > 1) << Values; } @@ -3121,9 +3402,10 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( } if (!ImplicitMaps.empty()) { if (OMPClause *Implicit = ActOnOpenMPMapClause( - OMPC_MAP_unknown, OMPC_MAP_tofrom, /*IsMapTypeImplicit=*/true, - SourceLocation(), SourceLocation(), ImplicitMaps, - SourceLocation(), SourceLocation(), SourceLocation())) { + llvm::None, llvm::None, OMPC_MAP_tofrom, + /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), + ImplicitMaps, SourceLocation(), SourceLocation(), + SourceLocation())) { ClausesWithImplicit.emplace_back(Implicit); ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() != ImplicitMaps.size(); @@ -3376,6 +3658,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( case OMPD_threadprivate: case OMPD_declare_reduction: case OMPD_declare_simd: + case OMPD_requires: llvm_unreachable("OpenMP Directive is not allowed"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); @@ -3695,7 +3978,8 @@ class OpenMPIterationSpaceChecker { /// Var <= UB /// UB > Var /// UB >= Var - bool TestIsLessOp = false; + /// This will have no value when the condition is != + llvm::Optional<bool> TestIsLessOp; /// This flag is true when condition is strict ( < or > ). bool TestIsStrictOp = false; /// This flag is true when step is subtracted on each iteration. @@ -3761,8 +4045,8 @@ private: /// Helper to set loop counter variable and its initializer. bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB); /// Helper to set upper bound. - bool setUB(Expr *NewUB, bool LessOp, bool StrictOp, SourceRange SR, - SourceLocation SL); + bool setUB(Expr *NewUB, llvm::Optional<bool> LessOp, bool StrictOp, + SourceRange SR, SourceLocation SL); /// Helper to set loop increment. bool setStep(Expr *NewStep, bool Subtract); }; @@ -3797,15 +4081,17 @@ bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl, return false; } -bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, bool LessOp, bool StrictOp, - SourceRange SR, SourceLocation SL) { +bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, llvm::Optional<bool> LessOp, + bool StrictOp, SourceRange SR, + SourceLocation SL) { // State consistency checking to ensure correct usage. assert(LCDecl != nullptr && LB != nullptr && UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp); if (!NewUB) return true; UB = NewUB; - TestIsLessOp = LessOp; + if (LessOp) + TestIsLessOp = LessOp; TestIsStrictOp = StrictOp; ConditionSrcRange = SR; ConditionLoc = SL; @@ -3819,7 +4105,7 @@ bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) { return true; if (!NewStep->isValueDependent()) { // Check that the step is integer expression. - SourceLocation StepLoc = NewStep->getLocStart(); + SourceLocation StepLoc = NewStep->getBeginLoc(); ExprResult Val = SemaRef.PerformOpenMPImplicitIntegerConversion( StepLoc, getExprAsWritten(NewStep)); if (Val.isInvalid()) @@ -3845,18 +4131,23 @@ bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) { bool IsConstPos = IsConstant && Result.isSigned() && (Subtract == Result.isNegative()); bool IsConstZero = IsConstant && !Result.getBoolValue(); + + // != with increment is treated as <; != with decrement is treated as > + if (!TestIsLessOp.hasValue()) + TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract); if (UB && (IsConstZero || - (TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract)) - : (IsConstPos || (IsUnsigned && !Subtract))))) { + (TestIsLessOp.getValue() ? + (IsConstNeg || (IsUnsigned && Subtract)) : + (IsConstPos || (IsUnsigned && !Subtract))))) { SemaRef.Diag(NewStep->getExprLoc(), diag::err_omp_loop_incr_not_compatible) - << LCDecl << TestIsLessOp << NewStep->getSourceRange(); + << LCDecl << TestIsLessOp.getValue() << NewStep->getSourceRange(); SemaRef.Diag(ConditionLoc, diag::note_omp_loop_cond_requres_compatible_incr) - << TestIsLessOp << ConditionSrcRange; + << TestIsLessOp.getValue() << ConditionSrcRange; return true; } - if (TestIsLessOp == Subtract) { + if (TestIsLessOp.getValue() == Subtract) { NewStep = SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep) .get(); @@ -3912,14 +4203,14 @@ bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) { if (Var->hasInit() && !Var->getType()->isReferenceType()) { // Accept non-canonical init form here but emit ext. warning. if (Var->getInitStyle() != VarDecl::CInit && EmitDiags) - SemaRef.Diag(S->getLocStart(), + SemaRef.Diag(S->getBeginLoc(), diag::ext_omp_loop_not_canonical_init) << S->getSourceRange(); return setLCDeclAndLB( Var, buildDeclRefExpr(SemaRef, Var, Var->getType().getNonReferenceType(), - DS->getLocStart()), + DS->getBeginLoc()), Var->getInit()); } } @@ -3944,7 +4235,7 @@ bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) { if (dependent() || SemaRef.CurContext->isDependentContext()) return false; if (EmitDiags) { - SemaRef.Diag(S->getLocStart(), diag::err_omp_loop_not_canonical_init) + SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init) << S->getSourceRange(); } return true; @@ -3984,7 +4275,7 @@ bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) { return true; } S = getExprAsWritten(S); - SourceLocation CondLoc = S->getLocStart(); + SourceLocation CondLoc = S->getBeginLoc(); if (auto *BO = dyn_cast<BinaryOperator>(S)) { if (BO->isRelationalOp()) { if (getInitLCDecl(BO->getLHS()) == LCDecl) @@ -3997,7 +4288,12 @@ bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) { (BO->getOpcode() == BO_GT || BO->getOpcode() == BO_GE), (BO->getOpcode() == BO_LT || BO->getOpcode() == BO_GT), BO->getSourceRange(), BO->getOperatorLoc()); - } + } else if (BO->getOpcode() == BO_NE) + return setUB(getInitLCDecl(BO->getLHS()) == LCDecl ? + BO->getRHS() : BO->getLHS(), + /*LessOp=*/llvm::None, + /*StrictOp=*/true, + BO->getSourceRange(), BO->getOperatorLoc()); } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) { if (CE->getNumArgs() == 2) { auto Op = CE->getOperator(); @@ -4015,6 +4311,14 @@ bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) { Op == OO_Less || Op == OO_Greater, CE->getSourceRange(), CE->getOperatorLoc()); break; + case OO_ExclaimEqual: + return setUB(getInitLCDecl(CE->getArg(0)) == LCDecl ? + CE->getArg(1) : CE->getArg(0), + /*LessOp=*/llvm::None, + /*StrictOp=*/true, + CE->getSourceRange(), + CE->getOperatorLoc()); + break; default: break; } @@ -4053,7 +4357,7 @@ bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) { } if (dependent() || SemaRef.CurContext->isDependentContext()) return false; - SemaRef.Diag(RHS->getLocStart(), diag::err_omp_loop_not_canonical_incr) + SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr) << RHS->getSourceRange() << LCDecl; return true; } @@ -4086,7 +4390,7 @@ bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) { if (UO->isIncrementDecrementOp() && getInitLCDecl(UO->getSubExpr()) == LCDecl) return setStep(SemaRef - .ActOnIntegerConstant(UO->getLocStart(), + .ActOnIntegerConstant(UO->getBeginLoc(), (UO->isDecrementOp() ? -1 : 1)) .get(), /*Subtract=*/false); @@ -4111,7 +4415,7 @@ bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) { if (getInitLCDecl(CE->getArg(0)) == LCDecl) return setStep(SemaRef .ActOnIntegerConstant( - CE->getLocStart(), + CE->getBeginLoc(), ((CE->getOperator() == OO_MinusMinus) ? -1 : 1)) .get(), /*Subtract=*/false); @@ -4131,7 +4435,7 @@ bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) { } if (dependent() || SemaRef.CurContext->isDependentContext()) return false; - SemaRef.Diag(S->getLocStart(), diag::err_omp_loop_not_canonical_incr) + SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr) << S->getSourceRange() << LCDecl; return true; } @@ -4163,8 +4467,8 @@ Expr *OpenMPIterationSpaceChecker::buildNumIterations( if (VarType->isIntegerType() || VarType->isPointerType() || SemaRef.getLangOpts().CPlusPlus) { // Upper - Lower - Expr *UBExpr = TestIsLessOp ? UB : LB; - Expr *LBExpr = TestIsLessOp ? LB : UB; + Expr *UBExpr = TestIsLessOp.getValue() ? UB : LB; + Expr *LBExpr = TestIsLessOp.getValue() ? LB : UB; Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures).get(); Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures).get(); if (!Upper || !Lower) @@ -4175,7 +4479,7 @@ Expr *OpenMPIterationSpaceChecker::buildNumIterations( if (!Diff.isUsable() && VarType->getAsCXXRecordDecl()) { // BuildBinOp already emitted error, this one is to point user to upper // and lower bound, and to tell what is passed to 'operator-'. - SemaRef.Diag(Upper->getLocStart(), diag::err_omp_loop_diff_cxx) + SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx) << Upper->getSourceRange() << Lower->getSourceRange(); return nullptr; } @@ -4265,8 +4569,9 @@ Expr *OpenMPIterationSpaceChecker::buildPreCond( ExprResult CondExpr = SemaRef.BuildBinOp(S, DefaultLoc, - TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE) - : (TestIsStrictOp ? BO_GT : BO_GE), + TestIsLessOp.getValue() ? + (TestIsStrictOp ? BO_LT : BO_LE) : + (TestIsStrictOp ? BO_GT : BO_GE), NewLB.get(), NewUB.get()); if (CondExpr.isUsable()) { if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(), @@ -4344,9 +4649,9 @@ Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData( SemaRef.getLangOpts().CPlusPlus) { // Upper - Lower Expr *Upper = - TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, UB, Captures).get(); + TestIsLessOp.getValue() ? Cnt : tryBuildCapture(SemaRef, UB, Captures).get(); Expr *Lower = - TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt; + TestIsLessOp.getValue() ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt; if (!Upper || !Lower) return nullptr; @@ -4355,7 +4660,7 @@ Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData( if (!Diff.isUsable() && VarType->getAsCXXRecordDecl()) { // BuildBinOp already emitted error, this one is to point user to upper // and lower bound, and to tell what is passed to 'operator-'. - SemaRef.Diag(Upper->getLocStart(), diag::err_omp_loop_diff_cxx) + SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx) << Upper->getSourceRange() << Lower->getSourceRange(); return nullptr; } @@ -4414,6 +4719,7 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) { unsigned AssociatedLoops = DSAStack->getAssociatedLoops(); if (AssociatedLoops > 0 && isOpenMPLoopDirective(DSAStack->getCurrentDirective())) { + DSAStack->loopStart(); OpenMPIterationSpaceChecker ISC(*this, ForLoc); if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) { if (ValueDecl *D = ISC.getLoopDecl()) { @@ -4428,6 +4734,15 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) { } } DSAStack->addLoopControlVariable(D, VD); + const Decl *LD = DSAStack->getPossiblyLoopCunter(); + if (LD != D->getCanonicalDecl()) { + DSAStack->resetPossibleLoopCounter(); + if (auto *Var = dyn_cast_or_null<VarDecl>(LD)) + MarkDeclarationsReferencedInExpr( + buildDeclRefExpr(*this, const_cast<VarDecl *>(Var), + Var->getType().getNonLValueExprType(Context), + ForLoc, /*RefersToCapture=*/true)); + } } } DSAStack->setAssociatedLoops(AssociatedLoops - 1); @@ -4448,7 +4763,7 @@ static bool checkOpenMPIterationSpace( // for (init-expr; test-expr; incr-expr) structured-block auto *For = dyn_cast_or_null<ForStmt>(S); if (!For) { - SemaRef.Diag(S->getLocStart(), diag::err_omp_not_for) + SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for) << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr) << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount; @@ -4493,7 +4808,7 @@ static bool checkOpenMPIterationSpace( if (!VarType->isDependentType() && !VarType->isIntegerType() && !VarType->isPointerType() && !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) { - SemaRef.Diag(Init->getLocStart(), diag::err_omp_loop_variable_type) + SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type) << SemaRef.getLangOpts().CPlusPlus; HasErrors = true; } @@ -4531,7 +4846,7 @@ static bool checkOpenMPIterationSpace( !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) && (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) { - SemaRef.Diag(Init->getLocStart(), diag::err_omp_loop_var_dsa) + SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa) << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(PredeterminedCKind); if (DVar.RefExpr == nullptr) @@ -4801,15 +5116,16 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, unsigned NestedLoopCount = 1; if (CollapseLoopCountExpr) { // Found 'collapse' clause - calculate collapse number. - llvm::APSInt Result; + Expr::EvalResult Result; if (CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) - NestedLoopCount = Result.getLimitedValue(); + NestedLoopCount = Result.Val.getInt().getLimitedValue(); } unsigned OrderedLoopCount = 1; if (OrderedLoopCountExpr) { // Found 'ordered' clause - calculate collapse number. - llvm::APSInt Result; - if (OrderedLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) { + Expr::EvalResult EVResult; + if (OrderedLoopCountExpr->EvaluateAsInt(EVResult, SemaRef.getASTContext())) { + llvm::APSInt Result = EVResult.Val.getInt(); if (Result.getLimitedValue() < NestedLoopCount) { SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(), diag::err_omp_wrong_ordered_loop_count) @@ -4954,13 +5270,14 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // Choose either the 32-bit or 64-bit version. ExprResult LastIteration = LastIteration64; - if (LastIteration32.isUsable() && - C.getTypeSize(LastIteration32.get()->getType()) == 32 && - (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 || - fitsInto( - /*Bits=*/32, - LastIteration32.get()->getType()->hasSignedIntegerRepresentation(), - LastIteration64.get(), SemaRef))) + if (SemaRef.getLangOpts().OpenMPOptimisticCollapse || + (LastIteration32.isUsable() && + C.getTypeSize(LastIteration32.get()->getType()) == 32 && + (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 || + fitsInto( + /*Bits=*/32, + LastIteration32.get()->getType()->hasSignedIntegerRepresentation(), + LastIteration64.get(), SemaRef)))) LastIteration = LastIteration32; QualType VType = LastIteration.get()->getType(); QualType RealVType = VType; @@ -5050,7 +5367,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, LastIteration.get(), UB.get()); EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(), CondOp.get()); - EUB = SemaRef.ActOnFinishFullExpr(EUB.get()); + EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false); // If we have a combined directive that combines 'distribute', 'for' or // 'simd' we need to be able to access the bounds of the schedule of the @@ -5079,7 +5396,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, LastIteration.get(), CombUB.get()); CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(), CombCondOp.get()); - CombEUB = SemaRef.ActOnFinishFullExpr(CombEUB.get()); + CombEUB = + SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false); const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl(); // We expect to have at least 2 more parameters than the 'parallel' @@ -5113,7 +5431,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, ? LB.get() : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS); - Init = SemaRef.ActOnFinishFullExpr(Init.get()); + Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false); if (isOpenMPLoopBoundSharingDirective(DKind)) { Expr *CombRHS = @@ -5124,32 +5442,40 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); CombInit = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS); - CombInit = SemaRef.ActOnFinishFullExpr(CombInit.get()); + CombInit = + SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false); } } // Loop condition (IV < NumIterations) or (IV <= UB) for worksharing loops. - SourceLocation CondLoc = AStmt->getLocStart(); + SourceLocation CondLoc = AStmt->getBeginLoc(); ExprResult Cond = (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind)) ? SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), UB.get()) : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(), NumIterations.get()); + ExprResult CombDistCond; + if (isOpenMPLoopBoundSharingDirective(DKind)) { + CombDistCond = + SemaRef.BuildBinOp( + CurScope, CondLoc, BO_LT, IV.get(), NumIterations.get()); + } + ExprResult CombCond; if (isOpenMPLoopBoundSharingDirective(DKind)) { CombCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), CombUB.get()); } // Loop increment (IV = IV + 1) - SourceLocation IncLoc = AStmt->getLocStart(); + SourceLocation IncLoc = AStmt->getBeginLoc(); ExprResult Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(), SemaRef.ActOnIntegerConstant(IncLoc, 1).get()); if (!Inc.isUsable()) return 0; Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get()); - Inc = SemaRef.ActOnFinishFullExpr(Inc.get()); + Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false); if (!Inc.isUsable()) return 0; @@ -5167,7 +5493,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // LB = LB + ST NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get()); - NextLB = SemaRef.ActOnFinishFullExpr(NextLB.get()); + NextLB = + SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false); if (!NextLB.isUsable()) return 0; // UB + ST @@ -5177,7 +5504,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // UB = UB + ST NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get()); - NextUB = SemaRef.ActOnFinishFullExpr(NextUB.get()); + NextUB = + SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false); if (!NextUB.isUsable()) return 0; if (isOpenMPLoopBoundSharingDirective(DKind)) { @@ -5188,7 +5516,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // LB = LB + ST CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(), CombNextLB.get()); - CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get()); + CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(), + /*DiscardedValue*/ false); if (!CombNextLB.isUsable()) return 0; // UB + ST @@ -5199,7 +5528,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // UB = UB + ST CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(), CombNextUB.get()); - CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get()); + CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(), + /*DiscardedValue*/ false); if (!CombNextUB.isUsable()) return 0; } @@ -5209,8 +5539,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // directive with for as IV = IV + ST; ensure upper bound expression based // on PrevUB instead of NumIterations - used to implement 'for' when found // in combination with 'distribute', like in 'distribute parallel for' - SourceLocation DistIncLoc = AStmt->getLocStart(); - ExprResult DistCond, DistInc, PrevEUB; + SourceLocation DistIncLoc = AStmt->getBeginLoc(); + ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond; if (isOpenMPLoopBoundSharingDirective(DKind)) { DistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), UB.get()); assert(DistCond.isUsable() && "distribute cond expr was not built"); @@ -5220,19 +5550,26 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, assert(DistInc.isUsable() && "distribute inc expr was not built"); DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(), DistInc.get()); - DistInc = SemaRef.ActOnFinishFullExpr(DistInc.get()); + DistInc = + SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false); assert(DistInc.isUsable() && "distribute inc expr was not built"); // Build expression: UB = min(UB, prevUB) for #for in composite or combined // construct - SourceLocation DistEUBLoc = AStmt->getLocStart(); + SourceLocation DistEUBLoc = AStmt->getBeginLoc(); ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT, UB.get(), PrevUB.get()); ExprResult CondOp = SemaRef.ActOnConditionalOp( DistEUBLoc, DistEUBLoc, IsUBGreater.get(), PrevUB.get(), UB.get()); PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(), CondOp.get()); - PrevEUB = SemaRef.ActOnFinishFullExpr(PrevEUB.get()); + PrevEUB = + SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false); + + // Build IV <= PrevUB to be used in parallel for is in combination with + // a distribute directive with schedule(static, 1) + ParForInDistCond = + SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), PrevUB.get()); } // Build updates and final values of the loop counters. @@ -5242,31 +5579,59 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Built.Updates.resize(NestedLoopCount); Built.Finals.resize(NestedLoopCount); { - ExprResult Div; - // Go from inner nested loop to outer. - for (int Cnt = NestedLoopCount - 1; Cnt >= 0; --Cnt) { + // We implement the following algorithm for obtaining the + // original loop iteration variable values based on the + // value of the collapsed loop iteration variable IV. + // + // Let n+1 be the number of collapsed loops in the nest. + // Iteration variables (I0, I1, .... In) + // Iteration counts (N0, N1, ... Nn) + // + // Acc = IV; + // + // To compute Ik for loop k, 0 <= k <= n, generate: + // Prod = N(k+1) * N(k+2) * ... * Nn; + // Ik = Acc / Prod; + // Acc -= Ik * Prod; + // + ExprResult Acc = IV; + for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) { LoopIterationSpace &IS = IterSpaces[Cnt]; SourceLocation UpdLoc = IS.IncSrcRange.getBegin(); - // Build: Iter = (IV / Div) % IS.NumIters - // where Div is product of previous iterations' IS.NumIters. ExprResult Iter; - if (Div.isUsable()) { - Iter = - SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, IV.get(), Div.get()); - } else { - Iter = IV; - assert((Cnt == (int)NestedLoopCount - 1) && - "unusable div expected on first iteration only"); - } - if (Cnt != 0 && Iter.isUsable()) - Iter = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Rem, Iter.get(), - IS.NumIterations); + // Compute prod + ExprResult Prod = + SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(); + for (unsigned int K = Cnt+1; K < NestedLoopCount; ++K) + Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(), + IterSpaces[K].NumIterations); + + // Iter = Acc / Prod + // If there is at least one more inner loop to avoid + // multiplication by 1. + if (Cnt + 1 < NestedLoopCount) + Iter = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, + Acc.get(), Prod.get()); + else + Iter = Acc; if (!Iter.isUsable()) { HasErrors = true; break; } + // Update Acc: + // Acc -= Iter * Prod + // Check if there is at least one more inner loop to avoid + // multiplication by 1. + if (Cnt + 1 < NestedLoopCount) + Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, + Iter.get(), Prod.get()); + else + Prod = Iter; + Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, + Acc.get(), Prod.get()); + // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl()); DeclRefExpr *CounterVar = buildDeclRefExpr( @@ -5295,22 +5660,6 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, break; } - // Build Div for the next iteration: Div <- Div * IS.NumIters - if (Cnt != 0) { - if (Div.isUnset()) - Div = IS.NumIterations; - else - Div = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Div.get(), - IS.NumIterations); - - // Add parentheses (for debugging purposes only). - if (Div.isUsable()) - Div = tryBuildCapture(SemaRef, Div.get(), Captures); - if (!Div.isUsable()) { - HasErrors = true; - break; - } - } if (!Update.isUsable() || !Final.isUsable()) { HasErrors = true; break; @@ -5331,8 +5680,10 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Built.IterationVarRef = IV.get(); Built.LastIteration = LastIteration.get(); Built.NumIterations = NumIterations.get(); - Built.CalcLastIteration = - SemaRef.ActOnFinishFullExpr(CalcLastIteration.get()).get(); + Built.CalcLastIteration = SemaRef + .ActOnFinishFullExpr(CalcLastIteration.get(), + /*DiscardedValue*/ false) + .get(); Built.PreCond = PreCond.get(); Built.PreInits = buildPreInits(C, Captures); Built.Cond = Cond.get(); @@ -5356,6 +5707,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Built.DistCombinedFields.Cond = CombCond.get(); Built.DistCombinedFields.NLB = CombNextLB.get(); Built.DistCombinedFields.NUB = CombNextUB.get(); + Built.DistCombinedFields.DistCond = CombDistCond.get(); + Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get(); return NestedLoopCount; } @@ -5391,7 +5744,6 @@ static bool checkSimdlenSafelenSpecified(Sema &S, } if (Simdlen && Safelen) { - llvm::APSInt SimdlenRes, SafelenRes; const Expr *SimdlenLength = Simdlen->getSimdlen(); const Expr *SafelenLength = Safelen->getSafelen(); if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() || @@ -5402,8 +5754,11 @@ static bool checkSimdlenSafelenSpecified(Sema &S, SafelenLength->isInstantiationDependent() || SafelenLength->containsUnexpandedParameterPack()) return false; - SimdlenLength->EvaluateAsInt(SimdlenRes, S.Context); - SafelenLength->EvaluateAsInt(SafelenRes, S.Context); + Expr::EvalResult SimdlenResult, SafelenResult; + SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context); + SafelenLength->EvaluateAsInt(SafelenResult, S.Context); + llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt(); + llvm::APSInt SafelenRes = SafelenResult.Val.getInt(); // OpenMP 4.5 [2.8.1, simd Construct, Restrictions] // If both simdlen and safelen clauses are specified, the value of the // simdlen parameter must be less than or equal to the value of the safelen @@ -5552,7 +5907,7 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses, for (Stmt *SectionStmt : llvm::make_range(std::next(S.begin()), S.end())) { if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) { if (SectionStmt) - Diag(SectionStmt->getLocStart(), + Diag(SectionStmt->getBeginLoc(), diag::err_omp_sections_substmt_not_section); return StmtError(); } @@ -5560,7 +5915,7 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses, ->setHasCancel(DSAStack->isCancelRegion()); } } else { - Diag(AStmt->getLocStart(), diag::err_omp_sections_not_compound_stmt); + Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt); return StmtError(); } @@ -5606,9 +5961,9 @@ StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses, else if (Clause->getClauseKind() == OMPC_copyprivate) Copyprivate = Clause; if (Copyprivate && Nowait) { - Diag(Copyprivate->getLocStart(), + Diag(Copyprivate->getBeginLoc(), diag::err_omp_single_copyprivate_with_nowait); - Diag(Nowait->getLocStart(), diag::note_omp_nowait_clause_here); + Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here); return StmtError(); } } @@ -5644,7 +5999,7 @@ StmtResult Sema::ActOnOpenMPCriticalDirective( for (const OMPClause *C : Clauses) { if (C->getClauseKind() == OMPC_hint) { if (!DirName.getName()) { - Diag(C->getLocStart(), diag::err_omp_hint_clause_no_name); + Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name); ErrorFound = true; } Expr *E = cast<OMPHintClause>(C)->getHint(); @@ -5653,7 +6008,7 @@ StmtResult Sema::ActOnOpenMPCriticalDirective( DependentHint = true; } else { Hint = E->EvaluateKnownConstInt(Context); - HintLoc = C->getLocStart(); + HintLoc = C->getBeginLoc(); } } } @@ -5669,12 +6024,12 @@ StmtResult Sema::ActOnOpenMPCriticalDirective( else Diag(StartLoc, diag::note_omp_critical_no_hint) << 0; if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) { - Diag(C->getLocStart(), diag::note_omp_critical_hint_here) + Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here) << 1 << C->getHint()->EvaluateKnownConstInt(Context).toString( /*Radix=*/10, /*Signed=*/false); } else { - Diag(Pair.first->getLocStart(), diag::note_omp_critical_no_hint) << 1; + Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1; } } } @@ -5795,7 +6150,7 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses, for (Stmt *SectionStmt : llvm::make_range(std::next(S.begin()), S.end())) { if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) { if (SectionStmt) - Diag(SectionStmt->getLocStart(), + Diag(SectionStmt->getBeginLoc(), diag::err_omp_parallel_sections_substmt_not_section); return StmtError(); } @@ -5803,7 +6158,7 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses, ->setHasCancel(DSAStack->isCancelRegion()); } } else { - Diag(AStmt->getLocStart(), + Diag(AStmt->getBeginLoc(), diag::err_omp_parallel_sections_not_compound_stmt); return StmtError(); } @@ -5887,7 +6242,7 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses, DependFound = C; if (DC->getDependencyKind() == OMPC_DEPEND_source) { if (DependSourceClause) { - Diag(C->getLocStart(), diag::err_omp_more_one_clause) + Diag(C->getBeginLoc(), diag::err_omp_more_one_clause) << getOpenMPDirectiveName(OMPD_ordered) << getOpenMPClauseName(OMPC_depend) << 2; ErrorFound = true; @@ -5895,13 +6250,13 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses, DependSourceClause = C; } if (DependSinkClause) { - Diag(C->getLocStart(), diag::err_omp_depend_sink_source_not_allowed) + Diag(C->getBeginLoc(), diag::err_omp_depend_sink_source_not_allowed) << 0; ErrorFound = true; } } else if (DC->getDependencyKind() == OMPC_DEPEND_sink) { if (DependSourceClause) { - Diag(C->getLocStart(), diag::err_omp_depend_sink_source_not_allowed) + Diag(C->getBeginLoc(), diag::err_omp_depend_sink_source_not_allowed) << 1; ErrorFound = true; } @@ -5921,19 +6276,19 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses, Diag(StartLoc, diag::err_omp_prohibited_region_simd); ErrorFound = true; } else if (DependFound && (TC || SC)) { - Diag(DependFound->getLocStart(), diag::err_omp_depend_clause_thread_simd) + Diag(DependFound->getBeginLoc(), diag::err_omp_depend_clause_thread_simd) << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind()); ErrorFound = true; } else if (DependFound && !DSAStack->getParentOrderedRegionParam().first) { - Diag(DependFound->getLocStart(), + Diag(DependFound->getBeginLoc(), diag::err_omp_ordered_directive_without_param); ErrorFound = true; } else if (TC || Clauses.empty()) { if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) { - SourceLocation ErrLoc = TC ? TC->getLocStart() : StartLoc; + SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc; Diag(ErrLoc, diag::err_omp_ordered_directive_with_param) << (TC != nullptr); - Diag(Param->getLocStart(), diag::note_omp_ordered_param); + Diag(Param->getBeginLoc(), diag::note_omp_ordered_param); ErrorFound = true; } } @@ -6154,12 +6509,12 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId, } } else { ErrorFound = NotAScalarType; - NoteLoc = ErrorLoc = AtomicBody->getLocStart(); + NoteLoc = ErrorLoc = AtomicBody->getBeginLoc(); NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); } } else { ErrorFound = NotAnExpression; - NoteLoc = ErrorLoc = S->getLocStart(); + NoteLoc = ErrorLoc = S->getBeginLoc(); NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); } if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) { @@ -6211,13 +6566,13 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, C->getClauseKind() == OMPC_update || C->getClauseKind() == OMPC_capture) { if (AtomicKind != OMPC_unknown) { - Diag(C->getLocStart(), diag::err_omp_atomic_several_clauses) - << SourceRange(C->getLocStart(), C->getLocEnd()); + Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses) + << SourceRange(C->getBeginLoc(), C->getEndLoc()); Diag(AtomicKindLoc, diag::note_omp_atomic_previous_clause) << getOpenMPClauseName(AtomicKind); } else { AtomicKind = C->getClauseKind(); - AtomicKindLoc = C->getLocStart(); + AtomicKindLoc = C->getBeginLoc(); } } } @@ -6305,7 +6660,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, } } else { ErrorFound = NotAnExpression; - NoteLoc = ErrorLoc = Body->getLocStart(); + NoteLoc = ErrorLoc = Body->getBeginLoc(); NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); } if (ErrorFound != NoError) { @@ -6367,7 +6722,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, } } else { ErrorFound = NotAnExpression; - NoteLoc = ErrorLoc = Body->getLocStart(); + NoteLoc = ErrorLoc = Body->getBeginLoc(); NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); } if (ErrorFound != NoError) { @@ -6551,7 +6906,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) { ErrorFound = NotAnAssignmentOp; NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc() - : First->getLocStart(); + : First->getBeginLoc(); NoteRange = ErrorRange = FirstBinOp ? FirstBinOp->getSourceRange() : SourceRange(ErrorLoc, ErrorLoc); @@ -6561,7 +6916,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, ErrorFound = NotAnAssignmentOp; NoteLoc = ErrorLoc = SecondBinOp ? SecondBinOp->getOperatorLoc() - : Second->getLocStart(); + : Second->getBeginLoc(); NoteRange = ErrorRange = SecondBinOp ? SecondBinOp->getSourceRange() : SourceRange(ErrorLoc, ErrorLoc); @@ -6595,15 +6950,15 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, } } } else { - NoteLoc = ErrorLoc = Body->getLocStart(); + NoteLoc = ErrorLoc = Body->getBeginLoc(); NoteRange = ErrorRange = - SourceRange(Body->getLocStart(), Body->getLocStart()); + SourceRange(Body->getBeginLoc(), Body->getBeginLoc()); ErrorFound = NotTwoSubstatements; } } else { - NoteLoc = ErrorLoc = Body->getLocStart(); + NoteLoc = ErrorLoc = Body->getBeginLoc(); NoteRange = ErrorRange = - SourceRange(Body->getLocStart(), Body->getLocStart()); + SourceRange(Body->getBeginLoc(), Body->getBeginLoc()); ErrorFound = NotACompoundStatement; } if (ErrorFound != NoError) { @@ -6676,7 +7031,7 @@ StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses, Diag(StartLoc, diag::err_omp_target_contains_not_only_teams); Diag(DSAStack->getInnerTeamsRegionLoc(), diag::note_omp_nested_teams_construct_here); - Diag(S->getLocStart(), diag::note_omp_nested_statement_here) + Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here) << isa<OMPExecutableDirective>(S); return StmtError(); } @@ -6980,11 +7335,11 @@ static bool checkGrainsizeNumTasksClauses(Sema &S, if (!PrevClause) PrevClause = C; else if (PrevClause->getClauseKind() != C->getClauseKind()) { - S.Diag(C->getLocStart(), + S.Diag(C->getBeginLoc(), diag::err_omp_grainsize_num_tasks_mutually_exclusive) << getOpenMPClauseName(C->getClauseKind()) << getOpenMPClauseName(PrevClause->getClauseKind()); - S.Diag(PrevClause->getLocStart(), + S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_grainsize_num_tasks) << getOpenMPClauseName(PrevClause->getClauseKind()); ErrorFound = true; @@ -7013,9 +7368,9 @@ static bool checkReductionClauseWithNogroup(Sema &S, } } if (ReductionClause && NogroupClause) { - S.Diag(ReductionClause->getLocStart(), diag::err_omp_reduction_with_nogroup) - << SourceRange(NogroupClause->getLocStart(), - NogroupClause->getLocEnd()); + S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup) + << SourceRange(NogroupClause->getBeginLoc(), + NogroupClause->getEndLoc()); return true; } return false; @@ -7945,6 +8300,11 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, case OMPC_from: case OMPC_use_device_ptr: case OMPC_is_device_ptr: + case OMPC_unified_address: + case OMPC_unified_shared_memory: + case OMPC_reverse_offload: + case OMPC_dynamic_allocators: + case OMPC_atomic_default_mem_order: llvm_unreachable("Clause is not allowed."); } return Res; @@ -8030,6 +8390,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_distribute_simd: case OMPD_teams_distribute: case OMPD_teams_distribute_simd: + case OMPD_requires: llvm_unreachable("Unexpected OpenMP directive with if-clause"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); @@ -8095,6 +8456,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_distribute_simd: case OMPD_teams_distribute: case OMPD_teams_distribute_simd: + case OMPD_requires: llvm_unreachable("Unexpected OpenMP directive with num_threads-clause"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); @@ -8158,6 +8520,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_ordered: case OMPD_atomic: case OMPD_distribute_simd: + case OMPD_requires: llvm_unreachable("Unexpected OpenMP directive with num_teams-clause"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); @@ -8221,6 +8584,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_ordered: case OMPD_atomic: case OMPD_distribute_simd: + case OMPD_requires: llvm_unreachable("Unexpected OpenMP directive with thread_limit-clause"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); @@ -8284,6 +8648,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_atomic: case OMPD_distribute_simd: case OMPD_target_teams: + case OMPD_requires: llvm_unreachable("Unexpected OpenMP directive with schedule clause"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); @@ -8347,6 +8712,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_ordered: case OMPD_atomic: case OMPD_target_teams: + case OMPD_requires: llvm_unreachable("Unexpected OpenMP directive with schedule clause"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); @@ -8410,6 +8776,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_ordered: case OMPD_atomic: case OMPD_distribute_simd: + case OMPD_requires: llvm_unreachable("Unexpected OpenMP directive with num_teams-clause"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); @@ -8459,6 +8826,11 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPC_from: case OMPC_use_device_ptr: case OMPC_is_device_ptr: + case OMPC_unified_address: + case OMPC_unified_shared_memory: + case OMPC_reverse_offload: + case OMPC_dynamic_allocators: + case OMPC_atomic_default_mem_order: llvm_unreachable("Unexpected OpenMP clause."); } return CaptureRegion; @@ -8727,6 +9099,11 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( static_cast<OpenMPProcBindClauseKind>(Argument), ArgumentLoc, StartLoc, LParenLoc, EndLoc); break; + case OMPC_atomic_default_mem_order: + Res = ActOnOpenMPAtomicDefaultMemOrderClause( + static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument), + ArgumentLoc, StartLoc, LParenLoc, EndLoc); + break; case OMPC_if: case OMPC_final: case OMPC_num_threads: @@ -8776,6 +9153,10 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( case OMPC_from: case OMPC_use_device_ptr: case OMPC_is_device_ptr: + case OMPC_unified_address: + case OMPC_unified_shared_memory: + case OMPC_reverse_offload: + case OMPC_dynamic_allocators: llvm_unreachable("Clause is not allowed."); } return Res; @@ -8848,6 +9229,21 @@ OMPClause *Sema::ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind, OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); } +OMPClause *Sema::ActOnOpenMPAtomicDefaultMemOrderClause( + OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindKwLoc, + SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { + if (Kind == OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) { + Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) + << getListOfPossibleValues( + OMPC_atomic_default_mem_order, /*First=*/0, + /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) + << getOpenMPClauseName(OMPC_atomic_default_mem_order); + return nullptr; + } + return new (Context) OMPAtomicDefaultMemOrderClause(Kind, KindKwLoc, StartLoc, + LParenLoc, EndLoc); +} + OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause( OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, @@ -8932,6 +9328,11 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause( case OMPC_from: case OMPC_use_device_ptr: case OMPC_is_device_ptr: + case OMPC_unified_address: + case OMPC_unified_shared_memory: + case OMPC_reverse_offload: + case OMPC_dynamic_allocators: + case OMPC_atomic_default_mem_order: llvm_unreachable("Clause is not allowed."); } return Res; @@ -9011,7 +9412,7 @@ OMPClause *Sema::ActOnOpenMPScheduleClause( if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() && !ChunkSize->isInstantiationDependent() && !ChunkSize->containsUnexpandedParameterPack()) { - SourceLocation ChunkSizeLoc = ChunkSize->getLocStart(); + SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc(); ExprResult Val = PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize); if (Val.isInvalid()) @@ -9087,6 +9488,18 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, case OMPC_nogroup: Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc); break; + case OMPC_unified_address: + Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc); + break; + case OMPC_unified_shared_memory: + Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc); + break; + case OMPC_reverse_offload: + Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc); + break; + case OMPC_dynamic_allocators: + Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc); + break; case OMPC_if: case OMPC_final: case OMPC_num_threads: @@ -9126,6 +9539,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, case OMPC_from: case OMPC_use_device_ptr: case OMPC_is_device_ptr: + case OMPC_atomic_default_mem_order: llvm_unreachable("Clause is not allowed."); } return Res; @@ -9187,12 +9601,34 @@ OMPClause *Sema::ActOnOpenMPNogroupClause(SourceLocation StartLoc, return new (Context) OMPNogroupClause(StartLoc, EndLoc); } +OMPClause *Sema::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, + SourceLocation EndLoc) { + return new (Context) OMPUnifiedAddressClause(StartLoc, EndLoc); +} + +OMPClause *Sema::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc, + SourceLocation EndLoc) { + return new (Context) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc); +} + +OMPClause *Sema::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc, + SourceLocation EndLoc) { + return new (Context) OMPReverseOffloadClause(StartLoc, EndLoc); +} + +OMPClause *Sema::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, + SourceLocation EndLoc) { + return new (Context) OMPDynamicAllocatorsClause(StartLoc, EndLoc); +} + OMPClause *Sema::ActOnOpenMPVarListClause( OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *TailExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, OpenMPDependClauseKind DepKind, - OpenMPLinearClauseKind LinKind, OpenMPMapClauseKind MapTypeModifier, + OpenMPLinearClauseKind LinKind, + ArrayRef<OpenMPMapModifierKind> MapTypeModifiers, + ArrayRef<SourceLocation> MapTypeModifiersLoc, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation DepLinMapLoc) { OMPClause *Res = nullptr; @@ -9245,9 +9681,9 @@ OMPClause *Sema::ActOnOpenMPVarListClause( StartLoc, LParenLoc, EndLoc); break; case OMPC_map: - Res = ActOnOpenMPMapClause(MapTypeModifier, MapType, IsMapTypeImplicit, - DepLinMapLoc, ColonLoc, VarList, StartLoc, - LParenLoc, EndLoc); + Res = ActOnOpenMPMapClause(MapTypeModifiers, MapTypeModifiersLoc, MapType, + IsMapTypeImplicit, DepLinMapLoc, ColonLoc, + VarList, StartLoc, LParenLoc, EndLoc); break; case OMPC_to: Res = ActOnOpenMPToClause(VarList, StartLoc, LParenLoc, EndLoc); @@ -9294,6 +9730,11 @@ OMPClause *Sema::ActOnOpenMPVarListClause( case OMPC_defaultmap: case OMPC_unknown: case OMPC_uniform: + case OMPC_unified_address: + case OMPC_unified_shared_memory: + case OMPC_reverse_offload: + case OMPC_dynamic_allocators: + case OMPC_atomic_default_mem_order: llvm_unreachable("Clause is not allowed."); } return Res; @@ -9409,6 +9850,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, Type, 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 @@ -9830,6 +10282,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, Type, OMPC_lastprivate, ELoc)) + continue; + OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective(); // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced // in a Construct] @@ -9895,8 +10358,8 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, PseudoDstExpr, PseudoSrcExpr); if (AssignmentOp.isInvalid()) continue; - AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), ELoc, - /*DiscardedValue=*/true); + AssignmentOp = + ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false); if (AssignmentOp.isInvalid()) continue; @@ -10059,6 +10522,79 @@ static T filterLookupForUDR(SmallVectorImpl<U> &Lookups, return T(); } +static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) { + assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case"); + + for (auto RD : D->redecls()) { + // Don't bother with extra checks if we already know this one isn't visible. + if (RD == D) + continue; + + auto ND = cast<NamedDecl>(RD); + if (LookupResult::isVisible(SemaRef, ND)) + return ND; + } + + return nullptr; +} + +static void +argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &ReductionId, + SourceLocation Loc, QualType Ty, + SmallVectorImpl<UnresolvedSet<8>> &Lookups) { + // Find all of the associated namespaces and classes based on the + // arguments we have. + Sema::AssociatedNamespaceSet AssociatedNamespaces; + Sema::AssociatedClassSet AssociatedClasses; + OpaqueValueExpr OVE(Loc, Ty, VK_LValue); + SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces, + AssociatedClasses); + + // C++ [basic.lookup.argdep]p3: + // Let X be the lookup set produced by unqualified lookup (3.4.1) + // and let Y be the lookup set produced by argument dependent + // lookup (defined as follows). If X contains [...] then Y is + // empty. Otherwise Y is the set of declarations found in the + // namespaces associated with the argument types as described + // below. The set of declarations found by the lookup of the name + // is the union of X and Y. + // + // Here, we compute Y and add its members to the overloaded + // candidate set. + for (auto *NS : AssociatedNamespaces) { + // When considering an associated namespace, the lookup is the + // same as the lookup performed when the associated namespace is + // used as a qualifier (3.4.3.2) except that: + // + // -- Any using-directives in the associated namespace are + // ignored. + // + // -- Any namespace-scope friend functions declared in + // associated classes are visible within their respective + // namespaces even if they are not visible during an ordinary + // lookup (11.4). + DeclContext::lookup_result R = NS->lookup(ReductionId.getName()); + for (auto *D : R) { + auto *Underlying = D; + if (auto *USD = dyn_cast<UsingShadowDecl>(D)) + Underlying = USD->getTargetDecl(); + + if (!isa<OMPDeclareReductionDecl>(Underlying)) + continue; + + if (!SemaRef.isVisible(D)) { + D = findAcceptableDecl(SemaRef, D); + if (!D) + continue; + if (auto *USD = dyn_cast<UsingShadowDecl>(D)) + Underlying = USD->getTargetDecl(); + } + Lookups.emplace_back(); + Lookups.back().addDecl(Underlying); + } + } +} + static ExprResult buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, Scope *S, CXXScopeSpec &ReductionIdScopeSpec, @@ -10077,7 +10613,7 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, } while (S && !S->isDeclScope(D)); if (S) S = S->getParent(); - Lookups.push_back(UnresolvedSet<8>()); + Lookups.emplace_back(); Lookups.back().append(Lookup.begin(), Lookup.end()); Lookup.clear(); } @@ -10104,6 +10640,8 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, })) { UnresolvedSet<8> ResSet; for (const UnresolvedSet<8> &Set : Lookups) { + if (Set.empty()) + continue; ResSet.append(Set.begin(), Set.end()); // The last item marks the end of all declarations at the specified scope. ResSet.addDecl(Set[Set.size() - 1]); @@ -10113,6 +10651,36 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId, /*ADL=*/true, /*Overloaded=*/true, ResSet.begin(), ResSet.end()); } + // Lookup inside the classes. + // C++ [over.match.oper]p3: + // For a unary operator @ with an operand of a type whose + // cv-unqualified version is T1, and for a binary operator @ with + // a left operand of a type whose cv-unqualified version is T1 and + // a right operand of a type whose cv-unqualified version is T2, + // three sets of candidate functions, designated member + // candidates, non-member candidates and built-in candidates, are + // constructed as follows: + // -- If T1 is a complete class type or a class currently being + // defined, the set of member candidates is the result of the + // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise, + // the set of member candidates is empty. + LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName); + Lookup.suppressDiagnostics(); + if (const auto *TyRec = Ty->getAs<RecordType>()) { + // Complete the type if it can be completed. + // If the type is neither complete nor being defined, bail out now. + if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() || + TyRec->getDecl()->getDefinition()) { + Lookup.clear(); + SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl()); + if (Lookup.empty()) { + Lookups.emplace_back(); + Lookups.back().append(Lookup.begin(), Lookup.end()); + } + } + } + // Perform ADL. + argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups); if (auto *VD = filterLookupForUDR<ValueDecl *>( Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * { if (!D->isInvalidDecl() && @@ -10219,10 +10787,11 @@ static bool checkOMPArraySectionConstantForReduction( SingleElement = true; ArraySizes.push_back(llvm::APSInt::get(1)); } else { - llvm::APSInt ConstantLengthValue; - if (!Length->EvaluateAsInt(ConstantLengthValue, Context)) + Expr::EvalResult Result; + if (!Length->EvaluateAsInt(Result, Context)) return false; + llvm::APSInt ConstantLengthValue = Result.Val.getInt(); SingleElement = (ConstantLengthValue.getSExtValue() == 1); ArraySizes.push_back(ConstantLengthValue); } @@ -10243,9 +10812,12 @@ static bool checkOMPArraySectionConstantForReduction( // This is an array subscript which has implicit length 1! ArraySizes.push_back(llvm::APSInt::get(1)); } else { - llvm::APSInt ConstantLengthValue; - if (!Length->EvaluateAsInt(ConstantLengthValue, Context) || - ConstantLengthValue.getSExtValue() != 1) + Expr::EvalResult Result; + if (!Length->EvaluateAsInt(Result, Context)) + return false; + + llvm::APSInt ConstantLengthValue = Result.Val.getInt(); + if (ConstantLengthValue.getSExtValue() != 1) return false; ArraySizes.push_back(ConstantLengthValue); @@ -10430,76 +11002,71 @@ static bool actOnOMPReductionKindClause( // OpenMP [2.14.3.6, reduction clause, Restrictions] // A list item that appears in a reduction clause must not be // const-qualified. - if (Type.getNonReferenceType().isConstant(Context)) { - S.Diag(ELoc, diag::err_omp_const_reduction_list_item) << ERange; - if (!ASE && !OASE) { - bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) == - VarDecl::DeclarationOnly; - S.Diag(D->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << D; - } + if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc, + /*AcceptIfMutable*/ false, ASE || OASE)) continue; - } + + OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective(); // OpenMP [2.9.3.6, Restrictions, C/C++, p.4] // If a list-item is a reference type then it must bind to the same object // for all threads of the team. - if (!ASE && !OASE && VD) { - VarDecl *VDDef = VD->getDefinition(); - if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) { - DSARefChecker Check(Stack); - if (Check.Visit(VDDef->getInit())) { - S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg) - << getOpenMPClauseName(ClauseKind) << ERange; - S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef; - continue; + if (!ASE && !OASE) { + if (VD) { + VarDecl *VDDef = VD->getDefinition(); + if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) { + DSARefChecker Check(Stack); + if (Check.Visit(VDDef->getInit())) { + S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg) + << getOpenMPClauseName(ClauseKind) << ERange; + S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef; + continue; + } } } - } - - // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced - // in a Construct] - // Variables with the predetermined data-sharing attributes may not be - // listed in data-sharing attributes clauses, except for the cases - // listed below. For these exceptions only, listing a predetermined - // variable in a data-sharing attribute clause is allowed and overrides - // the variable's predetermined data-sharing attributes. - // OpenMP [2.14.3.6, Restrictions, p.3] - // Any number of reduction clauses can be specified on the directive, - // but a list item can appear only once in the reduction clauses for that - // directive. - DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false); - if (DVar.CKind == OMPC_reduction) { - S.Diag(ELoc, diag::err_omp_once_referenced) - << getOpenMPClauseName(ClauseKind); - if (DVar.RefExpr) - S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced); - continue; - } - if (DVar.CKind != OMPC_unknown) { - S.Diag(ELoc, diag::err_omp_wrong_dsa) - << getOpenMPClauseName(DVar.CKind) - << getOpenMPClauseName(OMPC_reduction); - reportOriginalDsa(S, Stack, D, DVar); - continue; - } - // OpenMP [2.14.3.6, Restrictions, p.1] - // A list item that appears in a reduction clause of a worksharing - // construct must be shared in the parallel regions to which any of the - // worksharing regions arising from the worksharing construct bind. - OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective(); - if (isOpenMPWorksharingDirective(CurrDir) && - !isOpenMPParallelDirective(CurrDir) && - !isOpenMPTeamsDirective(CurrDir)) { - DVar = Stack->getImplicitDSA(D, true); - if (DVar.CKind != OMPC_shared) { - S.Diag(ELoc, diag::err_omp_required_access) - << getOpenMPClauseName(OMPC_reduction) - << getOpenMPClauseName(OMPC_shared); + // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a Construct] + // Variables with the predetermined data-sharing attributes may not be + // listed in data-sharing attributes clauses, except for the cases + // listed below. For these exceptions only, listing a predetermined + // variable in a data-sharing attribute clause is allowed and overrides + // the variable's predetermined data-sharing attributes. + // OpenMP [2.14.3.6, Restrictions, p.3] + // Any number of reduction clauses can be specified on the directive, + // but a list item can appear only once in the reduction clauses for that + // directive. + DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false); + if (DVar.CKind == OMPC_reduction) { + S.Diag(ELoc, diag::err_omp_once_referenced) + << getOpenMPClauseName(ClauseKind); + if (DVar.RefExpr) + S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced); + continue; + } + if (DVar.CKind != OMPC_unknown) { + S.Diag(ELoc, diag::err_omp_wrong_dsa) + << getOpenMPClauseName(DVar.CKind) + << getOpenMPClauseName(OMPC_reduction); reportOriginalDsa(S, Stack, D, DVar); continue; } + + // OpenMP [2.14.3.6, Restrictions, p.1] + // A list item that appears in a reduction clause of a worksharing + // construct must be shared in the parallel regions to which any of the + // worksharing regions arising from the worksharing construct bind. + if (isOpenMPWorksharingDirective(CurrDir) && + !isOpenMPParallelDirective(CurrDir) && + !isOpenMPTeamsDirective(CurrDir)) { + DVar = Stack->getImplicitDSA(D, true); + if (DVar.CKind != OMPC_shared) { + S.Diag(ELoc, diag::err_omp_required_access) + << getOpenMPClauseName(OMPC_reduction) + << getOpenMPClauseName(OMPC_shared); + reportOriginalDsa(S, Stack, D, DVar); + continue; + } + } } // Try to find 'declare reduction' corresponding construct before using @@ -10518,7 +11085,7 @@ static bool actOnOMPReductionKindClause( } if (BOK == BO_Comma && DeclareReductionRef.isUnset()) { // Not allowed reduction identifier is found. - S.Diag(ReductionId.getLocStart(), + S.Diag(ReductionId.getBeginLoc(), diag::err_omp_unknown_reduction_identifier) << Type << ReductionIdRange; continue; @@ -10771,26 +11338,27 @@ static bool actOnOMPReductionKindClause( ELoc, Context.getPointerType(FnTy), VK_RValue, OK_Ordinary, S.DefaultLvalueConversion(DeclareReductionRef.get()).get()); Expr *Args[] = {LHS.get(), RHS.get()}; - ReductionOp = new (Context) - CallExpr(Context, OVE, Args, Context.VoidTy, VK_RValue, ELoc); + ReductionOp = + CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_RValue, ELoc); } else { ReductionOp = S.BuildBinOp( - Stack->getCurScope(), ReductionId.getLocStart(), BOK, LHSDRE, RHSDRE); + Stack->getCurScope(), ReductionId.getBeginLoc(), BOK, LHSDRE, RHSDRE); if (ReductionOp.isUsable()) { if (BOK != BO_LT && BOK != BO_GT) { ReductionOp = - S.BuildBinOp(Stack->getCurScope(), ReductionId.getLocStart(), + S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BO_Assign, LHSDRE, ReductionOp.get()); } else { auto *ConditionalOp = new (Context) ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc, RHSDRE, Type, VK_LValue, OK_Ordinary); ReductionOp = - S.BuildBinOp(Stack->getCurScope(), ReductionId.getLocStart(), + S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BO_Assign, LHSDRE, ConditionalOp); } if (ReductionOp.isUsable()) - ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get()); + ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(), + /*DiscardedValue*/ false); } if (!ReductionOp.isUsable()) continue; @@ -10832,7 +11400,7 @@ static bool actOnOMPReductionKindClause( EmitError = RedId != ParentRedId; } if (EmitError) { - S.Diag(ReductionId.getLocStart(), + S.Diag(ReductionId.getBeginLoc(), diag::err_omp_reduction_identifier_mismatch) << ReductionIdRange << RefExpr->getSourceRange(); S.Diag(ParentSR.getBegin(), @@ -10983,20 +11551,12 @@ bool Sema::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, } Type = Type.getNonReferenceType(); - // A list item must not be const-qualified. - if (Type.isConstant(Context)) { - Diag(ELoc, diag::err_omp_const_variable) - << getOpenMPClauseName(OMPC_linear); - if (D) { - bool IsDecl = - !VD || - VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; - Diag(D->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << D; - } + // 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. + if (rejectConstNotMutableType(*this, D, Type, OMPC_linear, ELoc)) return true; - } // A list item must be of integral or pointer type. Type = Type.getUnqualifiedType().getCanonicalType(); @@ -11033,8 +11593,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause( SourceLocation ELoc; SourceRange ERange; Expr *SimpleRefExpr = RefExpr; - auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange, - /*AllowArraySection=*/false); + auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange); if (Res.second) { // It will be analyzed later. Vars.push_back(RefExpr); @@ -11116,7 +11675,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause( if (Step && !Step->isValueDependent() && !Step->isTypeDependent() && !Step->isInstantiationDependent() && !Step->containsUnexpandedParameterPack()) { - SourceLocation StepLoc = Step->getLocStart(); + SourceLocation StepLoc = Step->getBeginLoc(); ExprResult Val = PerformOpenMPImplicitIntegerConversion(StepLoc, Step); if (Val.isInvalid()) return nullptr; @@ -11129,7 +11688,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause( buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc); ExprResult CalcStep = BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr); - CalcStep = ActOnFinishFullExpr(CalcStep.get()); + CalcStep = ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false); // Warn about zero linear step (it would be probably better specified as // making corresponding variables 'const'). @@ -11174,8 +11733,7 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, SourceLocation ELoc; SourceRange ERange; Expr *SimpleRefExpr = RefExpr; - auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange, - /*AllowArraySection=*/false); + auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange); ValueDecl *D = Res.first; if (Res.second || !D) { Updates.push_back(nullptr); @@ -11217,8 +11775,8 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, InitExpr, IV, Step, /* Subtract */ false); else Update = *CurPrivate; - Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getLocStart(), - /*DiscardedValue=*/true); + Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(), + /*DiscardedValue*/ false); // Build final: Var = InitExpr + NumIterations * Step ExprResult Final; @@ -11228,8 +11786,8 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, InitExpr, NumIterations, Step, /*Subtract=*/false); else Final = *CurPrivate; - Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getLocStart(), - /*DiscardedValue=*/true); + Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(), + /*DiscardedValue*/ false); if (!Update.isUsable() || !Final.isUsable()) { Updates.push_back(nullptr); @@ -11256,8 +11814,7 @@ OMPClause *Sema::ActOnOpenMPAlignedClause( SourceLocation ELoc; SourceRange ERange; Expr *SimpleRefExpr = RefExpr; - auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange, - /*AllowArraySection=*/false); + auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange); if (Res.second) { // It will be analyzed later. Vars.push_back(RefExpr); @@ -11381,12 +11938,12 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList, // operator for the class type. QualType ElemType = Context.getBaseElementType(Type).getNonReferenceType(); VarDecl *SrcVD = - buildVarDecl(*this, DE->getLocStart(), ElemType.getUnqualifiedType(), + buildVarDecl(*this, DE->getBeginLoc(), ElemType.getUnqualifiedType(), ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr); DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr( *this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc()); VarDecl *DstVD = - buildVarDecl(*this, DE->getLocStart(), ElemType, ".copyin.dst", + buildVarDecl(*this, DE->getBeginLoc(), ElemType, ".copyin.dst", VD->hasAttrs() ? &VD->getAttrs() : nullptr); DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc()); @@ -11398,7 +11955,7 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList, if (AssignmentOp.isInvalid()) continue; AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(), - /*DiscardedValue=*/true); + /*DiscardedValue*/ false); if (AssignmentOp.isInvalid()) continue; @@ -11429,8 +11986,7 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, SourceLocation ELoc; SourceRange ERange; Expr *SimpleRefExpr = RefExpr; - auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange, - /*AllowArraySection=*/false); + auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange); if (Res.second) { // It will be analyzed later. Vars.push_back(RefExpr); @@ -11496,19 +12052,19 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, Type = Context.getBaseElementType(Type.getNonReferenceType()) .getUnqualifiedType(); VarDecl *SrcVD = - buildVarDecl(*this, RefExpr->getLocStart(), Type, ".copyprivate.src", + buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.src", D->hasAttrs() ? &D->getAttrs() : nullptr); DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(*this, SrcVD, Type, ELoc); VarDecl *DstVD = - buildVarDecl(*this, RefExpr->getLocStart(), Type, ".copyprivate.dst", + buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.dst", D->hasAttrs() ? &D->getAttrs() : nullptr); DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc); ExprResult AssignmentOp = BuildBinOp( DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr); if (AssignmentOp.isInvalid()) continue; - AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), ELoc, - /*DiscardedValue=*/true); + AssignmentOp = + ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false); if (AssignmentOp.isInvalid()) continue; @@ -11628,8 +12184,7 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, } SourceLocation ELoc; SourceRange ERange; - auto Res = getPrivateItem(*this, LHS, ELoc, ERange, - /*AllowArraySection=*/false); + auto Res = getPrivateItem(*this, LHS, ELoc, ERange); if (Res.second) { // It will be analyzed later. Vars.push_back(RefExpr); @@ -11770,9 +12325,11 @@ static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, // If there is a lower bound that does not evaluates to zero, we are not // covering the whole dimension. if (LowerBound) { - llvm::APSInt ConstLowerBound; - if (!LowerBound->EvaluateAsInt(ConstLowerBound, SemaRef.getASTContext())) + Expr::EvalResult Result; + if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext())) return false; // Can't get the integer value as a constant. + + llvm::APSInt ConstLowerBound = Result.Val.getInt(); if (ConstLowerBound.getSExtValue()) return true; } @@ -11792,10 +12349,11 @@ static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, if (!CATy) return false; - llvm::APSInt ConstLength; - if (!Length->EvaluateAsInt(ConstLength, SemaRef.getASTContext())) + Expr::EvalResult Result; + if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext())) return false; // Can't get the integer value as a constant. + llvm::APSInt ConstLength = Result.Val.getInt(); return CATy->getSize().getSExtValue() != ConstLength.getSExtValue(); } @@ -11826,10 +12384,11 @@ static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef, } // Check if the length evaluates to 1. - llvm::APSInt ConstLength; - if (!Length->EvaluateAsInt(ConstLength, SemaRef.getASTContext())) + Expr::EvalResult Result; + if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext())) return false; // Can't get the integer value as a constant. + llvm::APSInt ConstLength = Result.Val.getInt(); return ConstLength.getSExtValue() != 1; } @@ -11986,6 +12545,19 @@ static const Expr *checkMapClauseExpressionBase( E->getType())) AllowWholeSizeArraySection = false; + if (const auto *TE = dyn_cast<CXXThisExpr>(E)) { + Expr::EvalResult Result; + if (CurE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext())) { + if (!Result.Val.getInt().isNullValue()) { + SemaRef.Diag(CurE->getIdx()->getExprLoc(), + diag::err_omp_invalid_map_this_expr); + SemaRef.Diag(CurE->getIdx()->getExprLoc(), + diag::note_omp_invalid_subscript_on_this_ptr_map); + } + } + RelevantExpr = TE; + } + // Record the component - we don't have any declaration associated. CurComponents.emplace_back(CurE, nullptr); } else if (auto *CurE = dyn_cast<OMPArraySectionExpr>(E)) { @@ -12032,6 +12604,30 @@ static const Expr *checkMapClauseExpressionBase( return nullptr; } + if (const auto *TE = dyn_cast<CXXThisExpr>(E)) { + Expr::EvalResult ResultR; + Expr::EvalResult ResultL; + if (CurE->getLength()->EvaluateAsInt(ResultR, + SemaRef.getASTContext())) { + if (!ResultR.Val.getInt().isOneValue()) { + SemaRef.Diag(CurE->getLength()->getExprLoc(), + diag::err_omp_invalid_map_this_expr); + SemaRef.Diag(CurE->getLength()->getExprLoc(), + diag::note_omp_invalid_length_on_this_ptr_mapping); + } + } + if (CurE->getLowerBound() && CurE->getLowerBound()->EvaluateAsInt( + ResultL, SemaRef.getASTContext())) { + if (!ResultL.Val.getInt().isNullValue()) { + SemaRef.Diag(CurE->getLowerBound()->getExprLoc(), + diag::err_omp_invalid_map_this_expr); + SemaRef.Diag(CurE->getLowerBound()->getExprLoc(), + diag::note_omp_invalid_lower_bound_on_this_ptr_mapping); + } + } + RelevantExpr = TE; + } + // Record the component - we don't have any declaration associated. CurComponents.emplace_back(CurE, nullptr); } else { @@ -12219,6 +12815,26 @@ static bool checkMapConflicts( // An expression is a subset of the other. if (CurrentRegionOnly && (CI == CE || SI == SE)) { if (CKind == OMPC_map) { + if (CI != CE || SI != SE) { + // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is + // a pointer. + auto Begin = + CI != CE ? CurComponents.begin() : StackComponents.begin(); + auto End = CI != CE ? CurComponents.end() : StackComponents.end(); + auto It = Begin; + while (It != End && !It->getAssociatedDeclaration()) + std::advance(It, 1); + assert(It != End && + "Expected at least one component with the declaration."); + if (It != Begin && It->getAssociatedDeclaration() + ->getType() + .getCanonicalType() + ->isAnyPointerType()) { + IsEnclosedByDataEnvironmentExpr = false; + EnclosingExpr = nullptr; + return false; + } + } SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange; } else { assert(CKind == OMPC_to || CKind == OMPC_from); @@ -12349,6 +12965,18 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS, assert(!CurComponents.empty() && "Invalid mappable expression information."); + if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) { + // Add store "this" pointer to class in DSAStackTy for future checking + DSAS->addMappedClassesQualTypes(TE->getType()); + // Skip restriction checking for variable or field declarations + MVLI.ProcessedVarList.push_back(RE); + MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1); + MVLI.VarComponents.back().append(CurComponents.begin(), + CurComponents.end()); + MVLI.VarBaseDeclarations.push_back(nullptr); + continue; + } + // For the following checks, we rely on the base declaration which is // expected to be associated with the last component. The declaration is // expected to be a variable or a field (if 'this' is being mapped). @@ -12478,7 +13106,8 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS, } OMPClause * -Sema::ActOnOpenMPMapClause(OpenMPMapClauseKind MapTypeModifier, +Sema::ActOnOpenMPMapClause(ArrayRef<OpenMPMapModifierKind> MapTypeModifiers, + ArrayRef<SourceLocation> MapTypeModifiersLoc, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc, @@ -12487,12 +13116,31 @@ Sema::ActOnOpenMPMapClause(OpenMPMapClauseKind MapTypeModifier, checkMappableExpressionList(*this, DSAStack, OMPC_map, MVLI, StartLoc, MapType, IsMapTypeImplicit); + OpenMPMapModifierKind Modifiers[] = { OMPC_MAP_MODIFIER_unknown, + OMPC_MAP_MODIFIER_unknown }; + SourceLocation ModifiersLoc[OMPMapClause::NumberOfModifiers]; + + // Process map-type-modifiers, flag errors for duplicate modifiers. + unsigned Count = 0; + for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) { + if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown && + llvm::find(Modifiers, MapTypeModifiers[I]) != std::end(Modifiers)) { + Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier); + continue; + } + assert(Count < OMPMapClause::NumberOfModifiers && + "Modifiers exceed the allowed number of map type modifiers"); + Modifiers[Count] = MapTypeModifiers[I]; + ModifiersLoc[Count] = MapTypeModifiersLoc[I]; + ++Count; + } + // We need to produce a map clause even if we don't have variables so that // other diagnostics related with non-existing map clauses are accurate. return OMPMapClause::Create(Context, StartLoc, LParenLoc, EndLoc, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, - MVLI.VarComponents, MapTypeModifier, MapType, - IsMapTypeImplicit, MapLoc); + MVLI.VarComponents, Modifiers, ModifiersLoc, + MapType, IsMapTypeImplicit, MapLoc); } QualType Sema::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, @@ -12649,6 +13297,11 @@ void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) { DRD->addDecl(OmpInParm); DRD->addDecl(OmpOutParm); } + Expr *InE = + ::buildDeclRefExpr(*this, OmpInParm, ReductionType, D->getLocation()); + Expr *OutE = + ::buildDeclRefExpr(*this, OmpOutParm, ReductionType, D->getLocation()); + DRD->setCombinerData(InE, OutE); } void Sema::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner) { @@ -12704,6 +13357,11 @@ VarDecl *Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) { DRD->addDecl(OmpPrivParm); DRD->addDecl(OmpOrigParm); } + Expr *OrigE = + ::buildDeclRefExpr(*this, OmpOrigParm, ReductionType, D->getLocation()); + Expr *PrivE = + ::buildDeclRefExpr(*this, OmpPrivParm, ReductionType, D->getLocation()); + DRD->setInitializerData(OrigE, PrivE); return OmpPrivParm; } @@ -12875,7 +13533,7 @@ OMPClause *Sema::ActOnOpenMPDistScheduleClause( if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() && !ChunkSize->isInstantiationDependent() && !ChunkSize->containsUnexpandedParameterPack()) { - SourceLocation ChunkSizeLoc = ChunkSize->getLocStart(); + SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc(); ExprResult Val = PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize); if (Val.isInvalid()) @@ -12951,19 +13609,14 @@ bool Sema::ActOnStartOpenMPDeclareTargetDirective(SourceLocation Loc) { Diag(Loc, diag::err_omp_region_not_file_context); return false; } - if (IsInOpenMPDeclareTargetContext) { - Diag(Loc, diag::err_omp_enclosed_declare_target); - return false; - } - - IsInOpenMPDeclareTargetContext = true; + ++DeclareTargetNestingLevel; return true; } void Sema::ActOnFinishOpenMPDeclareTargetDirective() { - assert(IsInOpenMPDeclareTargetContext && + assert(DeclareTargetNestingLevel > 0 && "Unexpected ActOnFinishOpenMPDeclareTargetDirective"); - IsInOpenMPDeclareTargetContext = false; + --DeclareTargetNestingLevel; } void Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope, @@ -12994,16 +13647,20 @@ void Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope, } NamedDecl *ND = Lookup.getAsSingle<NamedDecl>(); - if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND)) { + if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND) || + isa<FunctionTemplateDecl>(ND)) { if (!SameDirectiveDecls.insert(cast<NamedDecl>(ND->getCanonicalDecl()))) Diag(Id.getLoc(), diag::err_omp_declare_target_multiple) << Id.getName(); - if (!ND->hasAttr<OMPDeclareTargetDeclAttr>()) { + llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( + cast<ValueDecl>(ND)); + if (!Res) { auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(Context, MT); ND->addAttr(A); if (ASTMutationListener *ML = Context.getASTMutationListener()) ML->DeclarationMarkedOpenMPDeclareTarget(ND, A); checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Id.getLoc()); - } else if (ND->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() != MT) { + } else if (*Res != MT) { Diag(Id.getLoc(), diag::err_omp_declare_target_to_and_link) << Id.getName(); } @@ -13014,79 +13671,13 @@ void Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope, static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR, Sema &SemaRef, Decl *D) { - if (!D) + if (!D || !isa<VarDecl>(D)) return; - const Decl *LD = nullptr; - if (isa<TagDecl>(D)) { - LD = cast<TagDecl>(D)->getDefinition(); - } else if (isa<VarDecl>(D)) { - LD = cast<VarDecl>(D)->getDefinition(); - - // If this is an implicit variable that is legal and we do not need to do - // anything. - if (cast<VarDecl>(D)->isImplicit()) { - auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( - SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To); - D->addAttr(A); - if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener()) - ML->DeclarationMarkedOpenMPDeclareTarget(D, A); - return; - } - } else if (const auto *F = dyn_cast<FunctionDecl>(D)) { - const FunctionDecl *FD = nullptr; - if (cast<FunctionDecl>(D)->hasBody(FD)) { - LD = FD; - // If the definition is associated with the current declaration in the - // target region (it can be e.g. a lambda) that is legal and we do not - // need to do anything else. - if (LD == D) { - auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( - SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To); - D->addAttr(A); - if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener()) - ML->DeclarationMarkedOpenMPDeclareTarget(D, A); - return; - } - } else if (F->isFunctionTemplateSpecialization() && - F->getTemplateSpecializationKind() == - TSK_ImplicitInstantiation) { - // Check if the function is implicitly instantiated from the template - // defined in the declare target region. - const FunctionTemplateDecl *FTD = F->getPrimaryTemplate(); - if (FTD && FTD->hasAttr<OMPDeclareTargetDeclAttr>()) - return; - } - } - if (!LD) - LD = D; - if (LD && !LD->hasAttr<OMPDeclareTargetDeclAttr>() && - ((isa<VarDecl>(LD) && !isa<ParmVarDecl>(LD)) || isa<FunctionDecl>(LD))) { - // Outlined declaration is not declared target. - if (!isa<FunctionDecl>(LD)) { - if (LD->isOutOfLine()) { - SemaRef.Diag(LD->getLocation(), diag::warn_omp_not_in_target_context); - SemaRef.Diag(SL, diag::note_used_here) << SR; - } else { - const DeclContext *DC = LD->getDeclContext(); - while (DC && - (!isa<FunctionDecl>(DC) || - !cast<FunctionDecl>(DC)->hasAttr<OMPDeclareTargetDeclAttr>())) - DC = DC->getParent(); - if (DC) - return; - - // Is not declared in target context. - SemaRef.Diag(LD->getLocation(), diag::warn_omp_not_in_target_context); - SemaRef.Diag(SL, diag::note_used_here) << SR; - } - } - // Mark decl as declared target to prevent further diagnostic. - auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( - SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To); - D->addAttr(A); - if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener()) - ML->DeclarationMarkedOpenMPDeclareTarget(D, A); - } + auto *VD = cast<VarDecl>(D); + if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) + return; + SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context); + SemaRef.Diag(SL, diag::note_used_here) << SR; } static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR, @@ -13102,10 +13693,11 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, if (!D || D->isInvalidDecl()) return; SourceRange SR = E ? E->getSourceRange() : D->getSourceRange(); - SourceLocation SL = E ? E->getLocStart() : D->getLocation(); + SourceLocation SL = E ? E->getBeginLoc() : D->getLocation(); if (auto *VD = dyn_cast<VarDecl>(D)) { // Only global variables can be marked as declare target. - if (VD->isLocalVarDeclOrParm()) + if (!VD->isFileVarDecl() && !VD->isStaticLocal() && + !VD->isStaticDataMember()) return; // 2.10.6: threadprivate variable cannot appear in a declare target // directive. @@ -13115,48 +13707,39 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, return; } } + if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) + D = FTD->getTemplatedDecl(); + if (const auto *FD = dyn_cast<FunctionDecl>(D)) { + llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD); + if (Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) { + assert(IdLoc.isValid() && "Source location is expected"); + Diag(IdLoc, diag::err_omp_function_in_link_clause); + Diag(FD->getLocation(), diag::note_defined_here) << FD; + return; + } + } if (auto *VD = dyn_cast<ValueDecl>(D)) { // Problem if any with var declared with incomplete type will be reported // as normal, so no need to check it here. if ((E || !VD->getType()->isIncompleteType()) && - !checkValueDeclInTarget(SL, SR, *this, DSAStack, VD)) { - // Mark decl as declared target to prevent further diagnostic. - if (isa<VarDecl>(VD) || isa<FunctionDecl>(VD) || - isa<FunctionTemplateDecl>(VD)) { + !checkValueDeclInTarget(SL, SR, *this, DSAStack, VD)) + return; + if (!E && !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { + // Checking declaration inside declare target region. + if (isa<VarDecl>(D) || isa<FunctionDecl>(D) || + isa<FunctionTemplateDecl>(D)) { auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( Context, OMPDeclareTargetDeclAttr::MT_To); - VD->addAttr(A); + D->addAttr(A); if (ASTMutationListener *ML = Context.getASTMutationListener()) - ML->DeclarationMarkedOpenMPDeclareTarget(VD, A); + ML->DeclarationMarkedOpenMPDeclareTarget(D, A); } return; } } - if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) - D = FTD->getTemplatedDecl(); - if (const auto *FD = dyn_cast<FunctionDecl>(D)) { - if (FD->hasAttr<OMPDeclareTargetDeclAttr>() && - (FD->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() == - OMPDeclareTargetDeclAttr::MT_Link)) { - assert(IdLoc.isValid() && "Source location is expected"); - Diag(IdLoc, diag::err_omp_function_in_link_clause); - Diag(FD->getLocation(), diag::note_defined_here) << FD; - return; - } - } - if (!E) { - // Checking declaration inside declare target region. - if (!D->hasAttr<OMPDeclareTargetDeclAttr>() && - (isa<VarDecl>(D) || isa<FunctionDecl>(D) || - isa<FunctionTemplateDecl>(D))) { - auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( - Context, OMPDeclareTargetDeclAttr::MT_To); - D->addAttr(A); - if (ASTMutationListener *ML = Context.getASTMutationListener()) - ML->DeclarationMarkedOpenMPDeclareTarget(D, A); - } + if (!E) return; - } checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), *this, D); } |
