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