diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:04:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:04:05 +0000 |
commit | 676fbe8105eeb6ff4bb2ed261cb212fcfdbe7b63 (patch) | |
tree | 02a1ac369cb734d0abfa5000dd86e5b7797e6a74 /lib/Sema/SemaOpenMP.cpp | |
parent | c7e70c433efc6953dc3888b9fbf9f3512d7da2b0 (diff) |
Diffstat (limited to 'lib/Sema/SemaOpenMP.cpp')
-rw-r--r-- | lib/Sema/SemaOpenMP.cpp | 1749 |
1 files changed, 1207 insertions, 542 deletions
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index e1a4c420d4024..36048a38b999c 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/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" @@ -73,6 +74,8 @@ public: }; using OperatorOffsetTy = llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>; + using DoacrossDependMapTy = + llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>; private: struct DSAInfo { @@ -97,8 +100,6 @@ private: llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>; using CriticalsWithHintsTy = llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>; - using DoacrossDependMapTy = - llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>; struct ReductionData { using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>; SourceRange ReductionRange; @@ -137,13 +138,16 @@ private: /// first argument (Expr *) contains optional argument of the /// 'ordered' clause, the second one is true if the regions has 'ordered' /// clause, false otherwise. - llvm::PointerIntPair<const Expr *, 1, bool> OrderedRegion; + 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()); @@ -398,23 +469,42 @@ public: } /// Marks current region as ordered (it has an 'ordered' clause). - void setOrderedRegion(bool IsOrdered, const Expr *Param) { + void setOrderedRegion(bool IsOrdered, const Expr *Param, + OMPOrderedClause *Clause) { assert(!isStackEmpty()); - Stack.back().first.back().OrderedRegion.setInt(IsOrdered); - Stack.back().first.back().OrderedRegion.setPointer(Param); + if (IsOrdered) + Stack.back().first.back().OrderedRegion.emplace(Param, Clause); + else + Stack.back().first.back().OrderedRegion.reset(); + } + /// Returns true, if region is ordered (has associated 'ordered' clause), + /// false - otherwise. + bool isOrderedRegion() const { + if (isStackEmpty()) + return false; + return Stack.back().first.rbegin()->OrderedRegion.hasValue(); + } + /// Returns optional parameter for the ordered region. + std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const { + if (isStackEmpty() || + !Stack.back().first.rbegin()->OrderedRegion.hasValue()) + return std::make_pair(nullptr, nullptr); + return Stack.back().first.rbegin()->OrderedRegion.getValue(); } /// Returns true, if parent region is ordered (has associated /// 'ordered' clause), false - otherwise. bool isParentOrderedRegion() const { if (isStackEmpty() || Stack.back().first.size() == 1) return false; - return std::next(Stack.back().first.rbegin())->OrderedRegion.getInt(); + return std::next(Stack.back().first.rbegin())->OrderedRegion.hasValue(); } /// Returns optional parameter for the ordered region. - const Expr *getParentOrderedRegionParam() const { - if (isStackEmpty() || Stack.back().first.size() == 1) - return nullptr; - return std::next(Stack.back().first.rbegin())->OrderedRegion.getPointer(); + std::pair<const Expr *, OMPOrderedClause *> + getParentOrderedRegionParam() const { + if (isStackEmpty() || Stack.back().first.size() == 1 || + !std::next(Stack.back().first.rbegin())->OrderedRegion.hasValue()) + return std::make_pair(nullptr, nullptr); + return std::next(Stack.back().first.rbegin())->OrderedRegion.getValue(); } /// Marks current region as nowait (it has a 'nowait' clause). void setNowaitRegion(bool IsNowait = true) { @@ -572,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(); @@ -716,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; @@ -963,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) @@ -977,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); @@ -1074,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 @@ -1147,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); @@ -1187,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( @@ -1239,17 +1394,6 @@ void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) { DSAStack->popFunction(OldFSI); } -static llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> -isDeclareTargetDeclaration(const ValueDecl *VD) { - for (const Decl *D : VD->redecls()) { - if (!D->hasAttrs()) - continue; - if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>()) - return Attr->getMapType(); - } - return llvm::None; -} - bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level) const { assert(LangOpts.OpenMP && "OpenMP is not allowed"); @@ -1368,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( @@ -1377,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>() && @@ -1417,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); @@ -1425,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 (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 && @@ -1440,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 = @@ -1463,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() && @@ -1780,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) @@ -1882,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, @@ -1950,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() || @@ -1968,7 +2236,7 @@ public: // Skip internally declared static variables. llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = - isDeclareTargetDeclaration(VD); + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); if (VD->hasGlobalStorage() && !CS->capturesVariable(VD) && (!Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)) return; @@ -1980,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; @@ -2057,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); @@ -2084,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; } @@ -2110,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)) { @@ -2171,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); + } } } @@ -2527,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"); @@ -2560,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); @@ -2697,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; } @@ -2812,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) { @@ -2845,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, @@ -2989,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; @@ -3023,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; @@ -3045,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; } @@ -3113,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(); @@ -3368,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"); @@ -3687,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. @@ -3736,6 +4028,13 @@ public: Expr *buildCounterInit() const; /// Build step of the counter be used for codegen. Expr *buildCounterStep() const; + /// Build loop data with counter value for depend clauses in ordered + /// directives. + Expr * + buildOrderedLoopData(Scope *S, Expr *Counter, + llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, + SourceLocation Loc, Expr *Inc = nullptr, + OverloadedOperatorKind OOK = OO_Amp); /// Return true if any expression is dependent. bool dependent() const; @@ -3746,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); }; @@ -3782,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; @@ -3804,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()) @@ -3830,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(); @@ -3897,10 +4203,15 @@ 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, nullptr, Var->getInit()); + return setLCDeclAndLB( + Var, + buildDeclRefExpr(SemaRef, Var, + Var->getType().getNonReferenceType(), + DS->getBeginLoc()), + Var->getInit()); } } } @@ -3924,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; @@ -3964,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) @@ -3977,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(); @@ -3995,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; } @@ -4033,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; } @@ -4066,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); @@ -4091,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); @@ -4111,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; } @@ -4143,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) @@ -4155,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; } @@ -4245,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(), @@ -4262,7 +4587,8 @@ Expr *OpenMPIterationSpaceChecker::buildPreCond( /// Build reference expression to the counter be used for codegen. DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar( - llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, DSAStackTy &DSA) const { + llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, + DSAStackTy &DSA) const { auto *VD = dyn_cast<VarDecl>(LCDecl); if (!VD) { VD = SemaRef.isOpenMPCapturedDecl(LCDecl); @@ -4302,6 +4628,63 @@ Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; } /// Build step of the counter be used for codegen. Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; } +Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData( + Scope *S, Expr *Counter, + llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc, + Expr *Inc, OverloadedOperatorKind OOK) { + Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get(); + if (!Cnt) + return nullptr; + if (Inc) { + assert((OOK == OO_Plus || OOK == OO_Minus) && + "Expected only + or - operations for depend clauses."); + BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub; + Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get(); + if (!Cnt) + return nullptr; + } + ExprResult Diff; + QualType VarType = LCDecl->getType().getNonReferenceType(); + if (VarType->isIntegerType() || VarType->isPointerType() || + SemaRef.getLangOpts().CPlusPlus) { + // Upper - Lower + Expr *Upper = + TestIsLessOp.getValue() ? Cnt : tryBuildCapture(SemaRef, UB, Captures).get(); + Expr *Lower = + TestIsLessOp.getValue() ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt; + if (!Upper || !Lower) + return nullptr; + + Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower); + + 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->getBeginLoc(), diag::err_omp_loop_diff_cxx) + << Upper->getSourceRange() << Lower->getSourceRange(); + return nullptr; + } + } + + if (!Diff.isUsable()) + return nullptr; + + // Parentheses (for dumping/debugging purposes only). + Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get()); + if (!Diff.isUsable()) + return nullptr; + + ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures); + if (!NewStep.isUsable()) + return nullptr; + // (Upper - Lower) / Step + Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get()); + if (!Diff.isUsable()) + return nullptr; + + return Diff.get(); +} + /// Iteration space of a single for loop. struct LoopIterationSpace final { /// Condition of the loop. @@ -4336,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()) { @@ -4350,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); @@ -4361,7 +4754,8 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) { static bool checkOpenMPIterationSpace( OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA, unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, - Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, + unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr, + Expr *OrderedLoopCountExpr, Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA, LoopIterationSpace &ResultIterSpace, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) { @@ -4369,11 +4763,11 @@ 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) << NestedLoopCount + << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount; - if (NestedLoopCount > 1) { + if (TotalNestedLoopCount > 1) { if (CollapseLoopCountExpr && OrderedLoopCountExpr) SemaRef.Diag(DSA.getConstructLoc(), diag::note_omp_collapse_ordered_expr) @@ -4414,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; } @@ -4452,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) @@ -4506,6 +4900,41 @@ static bool checkOpenMPIterationSpace( ResultIterSpace.PrivateCounterVar == nullptr || ResultIterSpace.CounterInit == nullptr || ResultIterSpace.CounterStep == nullptr); + if (!HasErrors && DSA.isOrderedRegion()) { + if (DSA.getOrderedRegionParam().second->getNumForLoops()) { + if (CurrentNestedLoopCount < + DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) { + DSA.getOrderedRegionParam().second->setLoopNumIterations( + CurrentNestedLoopCount, ResultIterSpace.NumIterations); + DSA.getOrderedRegionParam().second->setLoopCounter( + CurrentNestedLoopCount, ResultIterSpace.CounterVar); + } + } + for (auto &Pair : DSA.getDoacrossDependClauses()) { + if (CurrentNestedLoopCount >= Pair.first->getNumLoops()) { + // Erroneous case - clause has some problems. + continue; + } + if (Pair.first->getDependencyKind() == OMPC_DEPEND_sink && + Pair.second.size() <= CurrentNestedLoopCount) { + // Erroneous case - clause has some problems. + Pair.first->setLoopData(CurrentNestedLoopCount, nullptr); + continue; + } + Expr *CntValue; + if (Pair.first->getDependencyKind() == OMPC_DEPEND_source) + CntValue = ISC.buildOrderedLoopData( + DSA.getCurScope(), ResultIterSpace.CounterVar, Captures, + Pair.first->getDependencyLoc()); + else + CntValue = ISC.buildOrderedLoopData( + DSA.getCurScope(), ResultIterSpace.CounterVar, Captures, + Pair.first->getDependencyLoc(), + Pair.second[CurrentNestedLoopCount].first, + Pair.second[CurrentNestedLoopCount].second); + Pair.first->setLoopData(CurrentNestedLoopCount, CntValue); + } + } return HasErrors; } @@ -4687,14 +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) @@ -4703,20 +5134,21 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, diag::note_collapse_loop_count) << CollapseLoopCountExpr->getSourceRange(); } - NestedLoopCount = Result.getLimitedValue(); + OrderedLoopCount = Result.getLimitedValue(); } } // This is helper routine for loop directives (e.g., 'for', 'simd', // 'for simd', etc.). llvm::MapVector<const Expr *, DeclRefExpr *> Captures; SmallVector<LoopIterationSpace, 4> IterSpaces; - IterSpaces.resize(NestedLoopCount); + IterSpaces.resize(std::max(OrderedLoopCount, NestedLoopCount)); Stmt *CurStmt = AStmt->IgnoreContainers(/* IgnoreCaptured */ true); for (unsigned Cnt = 0; Cnt < NestedLoopCount; ++Cnt) { - if (checkOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA, Cnt, - NestedLoopCount, CollapseLoopCountExpr, - OrderedLoopCountExpr, VarsWithImplicitDSA, - IterSpaces[Cnt], Captures)) + if (checkOpenMPIterationSpace( + DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount, + std::max(OrderedLoopCount, NestedLoopCount), CollapseLoopCountExpr, + OrderedLoopCountExpr, VarsWithImplicitDSA, IterSpaces[Cnt], + Captures)) return 0; // Move on to the next nested for loop, or to the loop body. // OpenMP [2.8.1, simd construct, Restrictions] @@ -4725,6 +5157,27 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // any two loops. CurStmt = cast<ForStmt>(CurStmt)->getBody()->IgnoreContainers(); } + for (unsigned Cnt = NestedLoopCount; Cnt < OrderedLoopCount; ++Cnt) { + if (checkOpenMPIterationSpace( + DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount, + std::max(OrderedLoopCount, NestedLoopCount), CollapseLoopCountExpr, + OrderedLoopCountExpr, VarsWithImplicitDSA, IterSpaces[Cnt], + Captures)) + return 0; + if (Cnt > 0 && IterSpaces[Cnt].CounterVar) { + // Handle initialization of captured loop iterator variables. + auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar); + if (isa<OMPCapturedExprDecl>(DRE->getDecl())) { + Captures[DRE] = DRE; + } + } + // Move on to the next nested for loop, or to the loop body. + // OpenMP [2.8.1, simd construct, Restrictions] + // All loops associated with the construct must be perfectly nested; that + // is, there must be no intervening code nor any OpenMP directive between + // any two loops. + CurStmt = cast<ForStmt>(CurStmt)->getBody()->IgnoreContainers(); + } Built.clear(/* size */ NestedLoopCount); @@ -4817,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; @@ -4913,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 @@ -4942,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' @@ -4976,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 = @@ -4987,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; @@ -5030,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 @@ -5040,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)) { @@ -5051,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 @@ -5062,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; } @@ -5072,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"); @@ -5083,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. @@ -5104,33 +5578,60 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Built.Inits.resize(NestedLoopCount); Built.Updates.resize(NestedLoopCount); Built.Finals.resize(NestedLoopCount); - SmallVector<Expr *, 4> LoopMultipliers; { - 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( @@ -5159,23 +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; - } - LoopMultipliers.push_back(Div.get()); - } if (!Update.isUsable() || !Final.isUsable()) { HasErrors = true; break; @@ -5196,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(); @@ -5221,55 +5707,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Built.DistCombinedFields.Cond = CombCond.get(); Built.DistCombinedFields.NLB = CombNextLB.get(); Built.DistCombinedFields.NUB = CombNextUB.get(); - - Expr *CounterVal = SemaRef.DefaultLvalueConversion(IV.get()).get(); - // Fill data for doacross depend clauses. - for (const auto &Pair : DSA.getDoacrossDependClauses()) { - if (Pair.first->getDependencyKind() == OMPC_DEPEND_source) { - Pair.first->setCounterValue(CounterVal); - } else { - if (NestedLoopCount != Pair.second.size() || - NestedLoopCount != LoopMultipliers.size() + 1) { - // Erroneous case - clause has some problems. - Pair.first->setCounterValue(CounterVal); - continue; - } - assert(Pair.first->getDependencyKind() == OMPC_DEPEND_sink); - auto I = Pair.second.rbegin(); - auto IS = IterSpaces.rbegin(); - auto ILM = LoopMultipliers.rbegin(); - Expr *UpCounterVal = CounterVal; - Expr *Multiplier = nullptr; - for (int Cnt = NestedLoopCount - 1; Cnt >= 0; --Cnt) { - if (I->first) { - assert(IS->CounterStep); - Expr *NormalizedOffset = - SemaRef - .BuildBinOp(CurScope, I->first->getExprLoc(), BO_Div, - I->first, IS->CounterStep) - .get(); - if (Multiplier) { - NormalizedOffset = - SemaRef - .BuildBinOp(CurScope, I->first->getExprLoc(), BO_Mul, - NormalizedOffset, Multiplier) - .get(); - } - assert(I->second == OO_Plus || I->second == OO_Minus); - BinaryOperatorKind BOK = (I->second == OO_Plus) ? BO_Add : BO_Sub; - UpCounterVal = SemaRef - .BuildBinOp(CurScope, I->first->getExprLoc(), BOK, - UpCounterVal, NormalizedOffset) - .get(); - } - Multiplier = *ILM; - ++I; - ++IS; - ++ILM; - } - Pair.first->setCounterValue(UpCounterVal); - } - } + Built.DistCombinedFields.DistCond = CombDistCond.get(); + Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get(); return NestedLoopCount; } @@ -5305,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() || @@ -5316,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 @@ -5466,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(); } @@ -5474,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(); } @@ -5520,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(); } } @@ -5558,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(); @@ -5567,7 +6008,7 @@ StmtResult Sema::ActOnOpenMPCriticalDirective( DependentHint = true; } else { Hint = E->EvaluateKnownConstInt(Context); - HintLoc = C->getLocStart(); + HintLoc = C->getBeginLoc(); } } } @@ -5583,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; } } } @@ -5709,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(); } @@ -5717,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(); } @@ -5801,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; @@ -5809,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; } @@ -5835,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()) { - Diag(DependFound->getLocStart(), + } else if (DependFound && !DSAStack->getParentOrderedRegionParam().first) { + Diag(DependFound->getBeginLoc(), diag::err_omp_ordered_directive_without_param); ErrorFound = true; } else if (TC || Clauses.empty()) { - if (const Expr *Param = DSAStack->getParentOrderedRegionParam()) { - SourceLocation ErrLoc = TC ? TC->getLocStart() : StartLoc; + if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) { + 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; } } @@ -6068,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) { @@ -6125,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(); } } } @@ -6219,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) { @@ -6281,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) { @@ -6465,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); @@ -6475,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); @@ -6509,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) { @@ -6590,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(); } @@ -6894,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; @@ -6927,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; @@ -7859,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; @@ -7944,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"); @@ -8009,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"); @@ -8072,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"); @@ -8135,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"); @@ -8198,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"); @@ -8261,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"); @@ -8324,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"); @@ -8373,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; @@ -8619,9 +9077,11 @@ OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc, } else { NumForLoops = nullptr; } - DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops); - return new (Context) - OMPOrderedClause(NumForLoops, StartLoc, LParenLoc, EndLoc); + auto *Clause = OMPOrderedClause::Create( + Context, NumForLoops, NumForLoops ? DSAStack->getAssociatedLoops() : 0, + StartLoc, LParenLoc, EndLoc); + DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause); + return Clause; } OMPClause *Sema::ActOnOpenMPSimpleClause( @@ -8639,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: @@ -8688,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; @@ -8760,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, @@ -8844,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; @@ -8923,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()) @@ -8999,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: @@ -9038,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; @@ -9099,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; @@ -9157,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); @@ -9206,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; @@ -9321,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 @@ -9742,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] @@ -9807,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; @@ -9971,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, @@ -9989,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(); } @@ -10016,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]); @@ -10025,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() && @@ -10131,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); } @@ -10155,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); @@ -10342,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 @@ -10430,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; @@ -10683,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; @@ -10744,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(), @@ -10895,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(); @@ -10945,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); @@ -11028,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; @@ -11041,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'). @@ -11086,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); @@ -11129,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; @@ -11140,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); @@ -11168,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); @@ -11293,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()); @@ -11310,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; @@ -11341,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); @@ -11408,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; @@ -11477,8 +12121,9 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, DSAStackTy::OperatorOffsetTy OpsOffs; llvm::APSInt DepCounter(/*BitWidth=*/32); llvm::APSInt TotalDepCount(/*BitWidth=*/32); - if (DepKind == OMPC_DEPEND_sink) { - if (const Expr *OrderedCountExpr = DSAStack->getParentOrderedRegionParam()) { + if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) { + if (const Expr *OrderedCountExpr = + DSAStack->getParentOrderedRegionParam().first) { TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Context); TotalDepCount.setIsUnsigned(/*Val=*/true); } @@ -11494,7 +12139,7 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, SourceLocation ELoc = RefExpr->getExprLoc(); Expr *SimpleExpr = RefExpr->IgnoreParenCasts(); if (DepKind == OMPC_DEPEND_sink) { - if (DSAStack->getParentOrderedRegionParam() && + if (DSAStack->getParentOrderedRegionParam().first && DepCounter >= TotalDepCount) { Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr); continue; @@ -11539,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); @@ -11560,7 +12204,7 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, continue; } if (!CurContext->isDependentContext() && - DSAStack->getParentOrderedRegionParam() && + DSAStack->getParentOrderedRegionParam().first && DepCounter != DSAStack->isParentLoopControlVariable(D).first) { const ValueDecl *VD = DSAStack->getParentLoopControlVariable(DepCounter.getZExtValue()); @@ -11598,7 +12242,7 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, if (!CurContext->isDependentContext() && DepKind == OMPC_DEPEND_sink && TotalDepCount > VarList.size() && - DSAStack->getParentOrderedRegionParam() && + DSAStack->getParentOrderedRegionParam().first && DSAStack->getParentLoopControlVariable(VarList.size() + 1)) { Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration) << 1 << DSAStack->getParentLoopControlVariable(VarList.size() + 1); @@ -11608,7 +12252,8 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, return nullptr; auto *C = OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc, - DepKind, DepLoc, ColonLoc, Vars); + DepKind, DepLoc, ColonLoc, Vars, + TotalDepCount.getZExtValue()); if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) && DSAStack->isParentOrderedRegion()) DSAStack->addDoacrossDependClause(C, OpsOffs); @@ -11680,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; } @@ -11702,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(); } @@ -11736,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; } @@ -11896,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)) { @@ -11942,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 { @@ -12129,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); @@ -12259,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). @@ -12388,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, @@ -12397,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, @@ -12559,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) { @@ -12614,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; } @@ -12785,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()) @@ -12861,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, @@ -12904,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(); } @@ -12924,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, @@ -13012,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. @@ -13025,56 +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 *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 (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) { - if (FTD->hasAttr<OMPDeclareTargetDeclAttr>() && - (FTD->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() == - OMPDeclareTargetDeclAttr::MT_Link)) { - assert(IdLoc.isValid() && "Source location is expected"); - Diag(IdLoc, diag::err_omp_function_in_link_clause); - Diag(FTD->getLocation(), diag::note_defined_here) << FTD; - 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); } |