diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2015-12-30 13:34:49 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2015-12-30 13:34:49 +0000 | 
| commit | 0623d7483df5fc17b32ba7bc5cb9c7beebf6db9c (patch) | |
| tree | 28726ef2038e86121e353aabf52297b35a48efa2 /contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp | |
| parent | 7d523365ff1a3cc95bc058b33102500f61e8166d (diff) | |
| parent | 45b533945f0851ec234ca846e1af5ee1e4df0b6e (diff) | |
Notes
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp')
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp | 2746 | 
1 files changed, 2248 insertions, 498 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp index ca67a1c0bf24..5dd835498a9a 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp @@ -77,6 +77,11 @@ public:            ImplicitDSALoc() {}    }; +public: +  struct MapInfo { +    Expr *RefExpr; +  }; +  private:    struct DSAInfo {      OpenMPClauseKind Attributes; @@ -84,33 +89,41 @@ private:    };    typedef llvm::SmallDenseMap<VarDecl *, DSAInfo, 64> DeclSAMapTy;    typedef llvm::SmallDenseMap<VarDecl *, DeclRefExpr *, 64> AlignedMapTy; -  typedef llvm::DenseSet<VarDecl *> LoopControlVariablesSetTy; +  typedef llvm::DenseMap<VarDecl *, unsigned> LoopControlVariablesMapTy; +  typedef llvm::SmallDenseMap<VarDecl *, MapInfo, 64> MappedDeclsTy; +  typedef llvm::StringMap<std::pair<OMPCriticalDirective *, llvm::APSInt>> +      CriticalsWithHintsTy;    struct SharingMapTy {      DeclSAMapTy SharingMap;      AlignedMapTy AlignedMap; -    LoopControlVariablesSetTy LCVSet; +    MappedDeclsTy MappedDecls; +    LoopControlVariablesMapTy LCVMap;      DefaultDataSharingAttributes DefaultAttr;      SourceLocation DefaultAttrLoc;      OpenMPDirectiveKind Directive;      DeclarationNameInfo DirectiveName;      Scope *CurScope;      SourceLocation ConstructLoc; -    bool OrderedRegion; +    /// \brief first argument (Expr *) contains optional argument of the +    /// 'ordered' clause, the second one is true if the regions has 'ordered' +    /// clause, false otherwise. +    llvm::PointerIntPair<Expr *, 1, bool> OrderedRegion;      bool NowaitRegion; -    unsigned CollapseNumber; +    bool CancelRegion; +    unsigned AssociatedLoops;      SourceLocation InnerTeamsRegionLoc;      SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,                   Scope *CurScope, SourceLocation Loc) -        : SharingMap(), AlignedMap(), LCVSet(), DefaultAttr(DSA_unspecified), +        : SharingMap(), AlignedMap(), LCVMap(), DefaultAttr(DSA_unspecified),            Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope), -          ConstructLoc(Loc), OrderedRegion(false), NowaitRegion(false), -          CollapseNumber(1), InnerTeamsRegionLoc() {} +          ConstructLoc(Loc), OrderedRegion(), NowaitRegion(false), +          CancelRegion(false), AssociatedLoops(1), InnerTeamsRegionLoc() {}      SharingMapTy() -        : SharingMap(), AlignedMap(), LCVSet(), DefaultAttr(DSA_unspecified), +        : SharingMap(), AlignedMap(), LCVMap(), DefaultAttr(DSA_unspecified),            Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr), -          ConstructLoc(), OrderedRegion(false), NowaitRegion(false), -          CollapseNumber(1), InnerTeamsRegionLoc() {} +          ConstructLoc(), OrderedRegion(), NowaitRegion(false), +          CancelRegion(false), AssociatedLoops(1), InnerTeamsRegionLoc() {}    };    typedef SmallVector<SharingMapTy, 64> StackTy; @@ -122,6 +135,7 @@ private:    OpenMPClauseKind ClauseKindMode;    Sema &SemaRef;    bool ForceCapturing; +  CriticalsWithHintsTy Criticals;    typedef SmallVector<SharingMapTy, 8>::reverse_iterator reverse_iterator; @@ -152,6 +166,16 @@ public:      Stack.pop_back();    } +  void addCriticalWithHint(OMPCriticalDirective *D, llvm::APSInt Hint) { +    Criticals[D->getDirectiveName().getAsString()] = std::make_pair(D, Hint); +  } +  const std::pair<OMPCriticalDirective *, llvm::APSInt> +  getCriticalWithHint(const DeclarationNameInfo &Name) const { +    auto I = Criticals.find(Name.getAsString()); +    if (I != Criticals.end()) +      return I->second; +    return std::make_pair(nullptr, llvm::APSInt()); +  }    /// \brief If 'aligned' declaration for given variable \a D was not seen yet,    /// add it and return NULL; otherwise return previous occurrence's expression    /// for diagnostics. @@ -161,7 +185,17 @@ public:    void addLoopControlVariable(VarDecl *D);    /// \brief Check if the specified variable is a loop control variable for    /// current region. -  bool isLoopControlVariable(VarDecl *D); +  /// \return The index of the loop control variable in the list of associated +  /// for-loops (from outer to inner). +  unsigned isLoopControlVariable(VarDecl *D); +  /// \brief Check if the specified variable is a loop control variable for +  /// parent region. +  /// \return The index of the loop control variable in the list of associated +  /// for-loops (from outer to inner). +  unsigned isParentLoopControlVariable(VarDecl *D); +  /// \brief Get the loop control variable for the I-th loop (or nullptr) in +  /// parent directive. +  VarDecl *getParentLoopControlVariable(unsigned I);    /// \brief Adds explicit data sharing attribute to the specified declaration.    void addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A); @@ -190,6 +224,13 @@ public:    bool hasExplicitDSA(VarDecl *D,                        const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,                        unsigned Level); + +  /// \brief Returns true if the directive at level \Level matches in the +  /// specified \a DPred predicate. +  bool hasExplicitDirective( +      const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred, +      unsigned Level); +    /// \brief Finds a directive which matches specified \a DPred predicate.    template <class NamedDirectivesPredicate>    bool hasDirective(NamedDirectivesPredicate DPred, bool FromParent); @@ -204,6 +245,8 @@ public:        return Stack[Stack.size() - 2].Directive;      return OMPD_unknown;    } +  /// \brief Return the directive associated with the provided scope. +  OpenMPDirectiveKind getDirectiveForScope(const Scope *S) const;    /// \brief Set default data sharing attribute to none.    void setDefaultDSANone(SourceLocation Loc) { @@ -230,16 +273,23 @@ public:    }    /// \brief Marks current region as ordered (it has an 'ordered' clause). -  void setOrderedRegion(bool IsOrdered = true) { -    Stack.back().OrderedRegion = IsOrdered; +  void setOrderedRegion(bool IsOrdered, Expr *Param) { +    Stack.back().OrderedRegion.setInt(IsOrdered); +    Stack.back().OrderedRegion.setPointer(Param);    }    /// \brief Returns true, if parent region is ordered (has associated    /// 'ordered' clause), false - otherwise.    bool isParentOrderedRegion() const {      if (Stack.size() > 2) -      return Stack[Stack.size() - 2].OrderedRegion; +      return Stack[Stack.size() - 2].OrderedRegion.getInt();      return false;    } +  /// \brief Returns optional parameter for the ordered region. +  Expr *getParentOrderedRegionParam() const { +    if (Stack.size() > 2) +      return Stack[Stack.size() - 2].OrderedRegion.getPointer(); +    return nullptr; +  }    /// \brief Marks current region as nowait (it has a 'nowait' clause).    void setNowaitRegion(bool IsNowait = true) {      Stack.back().NowaitRegion = IsNowait; @@ -251,13 +301,21 @@ public:        return Stack[Stack.size() - 2].NowaitRegion;      return false;    } +  /// \brief Marks parent region as cancel region. +  void setParentCancelRegion(bool Cancel = true) { +    if (Stack.size() > 2) +      Stack[Stack.size() - 2].CancelRegion = +          Stack[Stack.size() - 2].CancelRegion || Cancel; +  } +  /// \brief Return true if current region has inner cancel construct. +  bool isCancelRegion() const { +    return Stack.back().CancelRegion; +  }    /// \brief Set collapse value for the region. -  void setCollapseNumber(unsigned Val) { Stack.back().CollapseNumber = Val; } +  void setAssociatedLoops(unsigned Val) { Stack.back().AssociatedLoops = Val; }    /// \brief Return collapse value for region. -  unsigned getCollapseNumber() const { -    return Stack.back().CollapseNumber; -  } +  unsigned getAssociatedLoops() const { return Stack.back().AssociatedLoops; }    /// \brief Marks current target region as one with closely nested teams    /// region. @@ -279,10 +337,37 @@ public:    Scope *getCurScope() const { return Stack.back().CurScope; }    Scope *getCurScope() { return Stack.back().CurScope; }    SourceLocation getConstructLoc() { return Stack.back().ConstructLoc; } + +  MapInfo getMapInfoForVar(VarDecl *VD) { +    MapInfo VarMI = {0}; +    for (auto Cnt = Stack.size() - 1; Cnt > 0; --Cnt) { +      if (Stack[Cnt].MappedDecls.count(VD)) { +        VarMI = Stack[Cnt].MappedDecls[VD]; +        break; +      } +    } +    return VarMI; +  } + +  void addMapInfoForVar(VarDecl *VD, MapInfo MI) { +    if (Stack.size() > 1) { +      Stack.back().MappedDecls[VD] = MI; +    } +  } + +  MapInfo IsMappedInCurrentRegion(VarDecl *VD) { +    assert(Stack.size() > 1 && "Target level is 0"); +    MapInfo VarMI = {0}; +    if (Stack.size() > 1 && Stack.back().MappedDecls.count(VD)) { +      VarMI = Stack.back().MappedDecls[VD]; +    } +    return VarMI; +  }  };  bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) {    return isOpenMPParallelDirective(DKind) || DKind == OMPD_task || -         isOpenMPTeamsDirective(DKind) || DKind == OMPD_unknown; +         isOpenMPTeamsDirective(DKind) || DKind == OMPD_unknown || +         isOpenMPTaskLoopDirective(DKind);  }  } // namespace @@ -409,13 +494,32 @@ DeclRefExpr *DSAStackTy::addUniqueAligned(VarDecl *D, DeclRefExpr *NewDE) {  void DSAStackTy::addLoopControlVariable(VarDecl *D) {    assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");    D = D->getCanonicalDecl(); -  Stack.back().LCVSet.insert(D); +  Stack.back().LCVMap.insert(std::make_pair(D, Stack.back().LCVMap.size() + 1));  } -bool DSAStackTy::isLoopControlVariable(VarDecl *D) { +unsigned DSAStackTy::isLoopControlVariable(VarDecl *D) {    assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");    D = D->getCanonicalDecl(); -  return Stack.back().LCVSet.count(D) > 0; +  return Stack.back().LCVMap.count(D) > 0 ? Stack.back().LCVMap[D] : 0; +} + +unsigned DSAStackTy::isParentLoopControlVariable(VarDecl *D) { +  assert(Stack.size() > 2 && "Data-sharing attributes stack is empty"); +  D = D->getCanonicalDecl(); +  return Stack[Stack.size() - 2].LCVMap.count(D) > 0 +             ? Stack[Stack.size() - 2].LCVMap[D] +             : 0; +} + +VarDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) { +  assert(Stack.size() > 2 && "Data-sharing attributes stack is empty"); +  if (Stack[Stack.size() - 2].LCVMap.size() < I) +    return nullptr; +  for (auto &Pair : Stack[Stack.size() - 2].LCVMap) { +    if (Pair.second == I) +      return Pair.first; +  } +  return nullptr;  }  void DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) { @@ -452,12 +556,17 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {  /// \brief Build a variable declaration for OpenMP loop iteration variable.  static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type, -                             StringRef Name) { +                             StringRef Name, const AttrVec *Attrs = nullptr) {    DeclContext *DC = SemaRef.CurContext;    IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);    TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);    VarDecl *Decl =        VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None); +  if (Attrs) { +    for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end()); +         I != E; ++I) +      Decl->addAttr(*I); +  }    Decl->setImplicit();    return Decl;  } @@ -496,41 +605,20 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {    }    // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced -  // in a Construct, C/C++, predetermined, p.1] -  // Variables with automatic storage duration that are declared in a scope -  // inside the construct are private. -  OpenMPDirectiveKind Kind = -      FromParent ? getParentDirective() : getCurrentDirective(); -  auto StartI = std::next(Stack.rbegin()); -  auto EndI = std::prev(Stack.rend()); -  if (FromParent && StartI != EndI) { -    StartI = std::next(StartI); -  } -  if (!isParallelOrTaskRegion(Kind)) { -    if (isOpenMPLocal(D, StartI) && -        ((D->isLocalVarDecl() && (D->getStorageClass() == SC_Auto || -                                  D->getStorageClass() == SC_None)) || -         isa<ParmVarDecl>(D))) { -      DVar.CKind = OMPC_private; +  // in a Construct, C/C++, predetermined, p.4] +  //  Static data members are shared. +  // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced +  // in a Construct, C/C++, predetermined, p.7] +  //  Variables with static storage duration that are declared in a scope +  //  inside the construct are shared. +  if (D->isStaticDataMember()) { +    DSAVarData DVarTemp = +        hasDSA(D, isOpenMPPrivate, MatchesAlways(), FromParent); +    if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)        return DVar; -    } -    // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced -    // in a Construct, C/C++, predetermined, p.4] -    //  Static data members are shared. -    // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced -    // in a Construct, C/C++, predetermined, p.7] -    //  Variables with static storage duration that are declared in a scope -    //  inside the construct are shared. -    if (D->isStaticDataMember() || D->isStaticLocal()) { -      DSAVarData DVarTemp = -          hasDSA(D, isOpenMPPrivate, MatchesAlways(), FromParent); -      if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr) -        return DVar; - -      DVar.CKind = OMPC_shared; -      return DVar; -    } +    DVar.CKind = OMPC_shared; +    return DVar;    }    QualType Type = D->getType().getNonReferenceType().getCanonicalType(); @@ -542,6 +630,9 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {    //  shared.    CXXRecordDecl *RD =        SemaRef.getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr; +  if (auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD)) +    if (auto *CTD = CTSD->getSpecializedTemplate()) +      RD = CTD->getTemplatedDecl();    if (IsConstant &&        !(SemaRef.getLangOpts().CPlusPlus && RD && RD->hasMutableFields())) {      // Variables with const-qualified type having no mutable member may be @@ -557,6 +648,11 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {    // Explicitly specified attributes and local variables with predetermined    // attributes. +  auto StartI = std::next(Stack.rbegin()); +  auto EndI = std::prev(Stack.rend()); +  if (FromParent && StartI != EndI) { +    StartI = std::next(StartI); +  }    auto I = std::prev(StartI);    if (I->SharingMap.count(D)) {      DVar.RefExpr = I->SharingMap[D].RefExpr; @@ -635,6 +731,19 @@ bool DSAStackTy::hasExplicitDSA(           CPred(StartI->SharingMap[D].Attributes);  } +bool DSAStackTy::hasExplicitDirective( +    const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred, +    unsigned Level) { +  if (isClauseParsingMode()) +    ++Level; +  auto StartI = Stack.rbegin(); +  auto EndI = std::prev(Stack.rend()); +  if (std::distance(StartI, EndI) <= (int)Level) +    return false; +  std::advance(StartI, Level); +  return DPred(StartI->Directive); +} +  template <class NamedDirectivesPredicate>  bool DSAStackTy::hasDirective(NamedDirectivesPredicate DPred, bool FromParent) {    auto StartI = std::next(Stack.rbegin()); @@ -649,15 +758,134 @@ bool DSAStackTy::hasDirective(NamedDirectivesPredicate DPred, bool FromParent) {    return false;  } +OpenMPDirectiveKind DSAStackTy::getDirectiveForScope(const Scope *S) const { +  for (auto I = Stack.rbegin(), EE = Stack.rend(); I != EE; ++I) +    if (I->CurScope == S) +      return I->Directive; +  return OMPD_unknown; +} +  void Sema::InitDataSharingAttributesStack() {    VarDataSharingAttributesStack = new DSAStackTy(*this);  }  #define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack) +bool Sema::IsOpenMPCapturedByRef(VarDecl *VD, +                                 const CapturedRegionScopeInfo *RSI) { +  assert(LangOpts.OpenMP && "OpenMP is not allowed"); + +  auto &Ctx = getASTContext(); +  bool IsByRef = true; + +  // Find the directive that is associated with the provided scope. +  auto DKind = DSAStack->getDirectiveForScope(RSI->TheScope); +  auto Ty = VD->getType(); + +  if (isOpenMPTargetDirective(DKind)) { +    // This table summarizes how a given variable should be passed to the device +    // given its type and the clauses where it appears. This table is based on +    // the description in OpenMP 4.5 [2.10.4, target Construct] and +    // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses]. +    // +    // ========================================================================= +    // | type |  defaultmap   | pvt | first | is_device_ptr |    map   | res.  | +    // |      |(tofrom:scalar)|     |  pvt  |               |          |       | +    // ========================================================================= +    // | scl  |               |     |       |       -       |          | bycopy| +    // | scl  |               |  -  |   x   |       -       |     -    | bycopy| +    // | scl  |               |  x  |   -   |       -       |     -    | null  | +    // | scl  |       x       |     |       |       -       |          | byref | +    // | scl  |       x       |  -  |   x   |       -       |     -    | bycopy| +    // | scl  |       x       |  x  |   -   |       -       |     -    | null  | +    // | scl  |               |  -  |   -   |       -       |     x    | byref | +    // | scl  |       x       |  -  |   -   |       -       |     x    | byref | +    // +    // | agg  |      n.a.     |     |       |       -       |          | byref | +    // | agg  |      n.a.     |  -  |   x   |       -       |     -    | byref | +    // | agg  |      n.a.     |  x  |   -   |       -       |     -    | null  | +    // | agg  |      n.a.     |  -  |   -   |       -       |     x    | byref | +    // | agg  |      n.a.     |  -  |   -   |       -       |    x[]   | byref | +    // +    // | ptr  |      n.a.     |     |       |       -       |          | bycopy| +    // | ptr  |      n.a.     |  -  |   x   |       -       |     -    | bycopy| +    // | ptr  |      n.a.     |  x  |   -   |       -       |     -    | null  | +    // | ptr  |      n.a.     |  -  |   -   |       -       |     x    | byref | +    // | ptr  |      n.a.     |  -  |   -   |       -       |    x[]   | bycopy| +    // | ptr  |      n.a.     |  -  |   -   |       x       |          | bycopy| +    // | ptr  |      n.a.     |  -  |   -   |       x       |     x    | bycopy| +    // | ptr  |      n.a.     |  -  |   -   |       x       |    x[]   | bycopy| +    // ========================================================================= +    // Legend: +    //  scl - scalar +    //  ptr - pointer +    //  agg - aggregate +    //  x - applies +    //  - - invalid in this combination +    //  [] - mapped with an array section +    //  byref - should be mapped by reference +    //  byval - should be mapped by value +    //  null - initialize a local variable to null on the device +    // +    // Observations: +    //  - All scalar declarations that show up in a map clause have to be passed +    //    by reference, because they may have been mapped in the enclosing data +    //    environment. +    //  - If the scalar value does not fit the size of uintptr, it has to be +    //    passed by reference, regardless the result in the table above. +    //  - For pointers mapped by value that have either an implicit map or an +    //    array section, the runtime library may pass the NULL value to the +    //    device instead of the value passed to it by the compiler. + +    // FIXME: Right now, only implicit maps are implemented. Properly mapping +    // values requires having the map, private, and firstprivate clauses SEMA +    // and parsing in place, which we don't yet. + +    if (Ty->isReferenceType()) +      Ty = Ty->castAs<ReferenceType>()->getPointeeType(); +    IsByRef = !Ty->isScalarType(); +  } + +  // When passing data by value, we need to make sure it fits the uintptr size +  // and alignment, because the runtime library only deals with uintptr types. +  // If it does not fit the uintptr size, we need to pass the data by reference +  // instead. +  if (!IsByRef && +      (Ctx.getTypeSizeInChars(Ty) > +           Ctx.getTypeSizeInChars(Ctx.getUIntPtrType()) || +       Ctx.getDeclAlign(VD) > Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) +    IsByRef = true; + +  return IsByRef; +} +  bool Sema::IsOpenMPCapturedVar(VarDecl *VD) {    assert(LangOpts.OpenMP && "OpenMP is not allowed");    VD = VD->getCanonicalDecl(); + +  // If we are attempting to capture a global variable in a directive with +  // 'target' we return true so that this global is also mapped to the device. +  // +  // FIXME: If the declaration is enclosed in a 'declare target' directive, +  // then it should not be captured. Therefore, an extra check has to be +  // inserted here once support for 'declare target' is added. +  // +  if (!VD->hasLocalStorage()) { +    if (DSAStack->getCurrentDirective() == OMPD_target && +        !DSAStack->isClauseParsingMode()) { +      return true; +    } +    if (DSAStack->getCurScope() && +        DSAStack->hasDirective( +            [](OpenMPDirectiveKind K, const DeclarationNameInfo &DNI, +               SourceLocation Loc) -> bool { +              return isOpenMPTargetDirective(K); +            }, +            false)) { +      return true; +    } +  } +    if (DSAStack->getCurrentDirective() != OMPD_unknown &&        (!DSAStack->isClauseParsingMode() ||         DSAStack->getParentDirective() != OMPD_unknown)) { @@ -682,6 +910,14 @@ bool Sema::isOpenMPPrivateVar(VarDecl *VD, unsigned Level) {        VD, [](OpenMPClauseKind K) -> bool { return K == OMPC_private; }, Level);  } +bool Sema::isOpenMPTargetCapturedVar(VarDecl *VD, unsigned Level) { +  assert(LangOpts.OpenMP && "OpenMP is not allowed"); +  // Return true if the current level is no longer enclosed in a target region. + +  return !VD->hasLocalStorage() && +         DSAStack->hasExplicitDirective(isOpenMPTargetDirective, Level); +} +  void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; }  void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind, @@ -715,7 +951,7 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {              continue;            }            auto *VD = cast<VarDecl>(cast<DeclRefExpr>(DE)->getDecl()); -          QualType Type = VD->getType(); +          QualType Type = VD->getType().getNonReferenceType();            auto DVar = DSAStack->getTopDSA(VD, false);            if (DVar.CKind == OMPC_lastprivate) {              // Generate helper private variable and initialize it with the @@ -723,9 +959,9 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {              // by the address of the new private variable in CodeGen. This new              // variable is not added to IdResolver, so the code in the OpenMP              // region uses original variable for proper diagnostics. -            auto *VDPrivate = -                buildVarDecl(*this, DE->getExprLoc(), Type.getUnqualifiedType(), -                             VD->getName()); +            auto *VDPrivate = buildVarDecl( +                *this, DE->getExprLoc(), Type.getUnqualifiedType(), +                VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr);              ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false);              if (VDPrivate->isInvalidDecl())                continue; @@ -1158,7 +1394,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {    switch (DKind) {    case OMPD_parallel: {      QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); -    QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty); +    QualType KmpInt32PtrTy = +        Context.getPointerType(KmpInt32Ty).withConst().withRestrict();      Sema::CapturedParamNameType Params[] = {          std::make_pair(".global_tid.", KmpInt32PtrTy),          std::make_pair(".bound_tid.", KmpInt32PtrTy), @@ -1234,7 +1471,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {    }    case OMPD_parallel_for: {      QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); -    QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty); +    QualType KmpInt32PtrTy = +        Context.getPointerType(KmpInt32Ty).withConst().withRestrict();      Sema::CapturedParamNameType Params[] = {          std::make_pair(".global_tid.", KmpInt32PtrTy),          std::make_pair(".bound_tid.", KmpInt32PtrTy), @@ -1246,7 +1484,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {    }    case OMPD_parallel_for_simd: {      QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); -    QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty); +    QualType KmpInt32PtrTy = +        Context.getPointerType(KmpInt32Ty).withConst().withRestrict();      Sema::CapturedParamNameType Params[] = {          std::make_pair(".global_tid.", KmpInt32PtrTy),          std::make_pair(".bound_tid.", KmpInt32PtrTy), @@ -1258,7 +1497,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {    }    case OMPD_parallel_sections: {      QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); -    QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty); +    QualType KmpInt32PtrTy = +        Context.getPointerType(KmpInt32Ty).withConst().withRestrict();      Sema::CapturedParamNameType Params[] = {          std::make_pair(".global_tid.", KmpInt32PtrTy),          std::make_pair(".bound_tid.", KmpInt32PtrTy), @@ -1309,6 +1549,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {                               Params);      break;    } +  case OMPD_target_data:    case OMPD_target: {      Sema::CapturedParamNameType Params[] = {          std::make_pair(StringRef(), QualType()) // __context with shared vars @@ -1319,7 +1560,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {    }    case OMPD_teams: {      QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); -    QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty); +    QualType KmpInt32PtrTy = +        Context.getPointerType(KmpInt32Ty).withConst().withRestrict();      Sema::CapturedParamNameType Params[] = {          std::make_pair(".global_tid.", KmpInt32PtrTy),          std::make_pair(".bound_tid.", KmpInt32PtrTy), @@ -1337,6 +1579,30 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {                               Params);      break;    } +  case OMPD_taskloop: { +    Sema::CapturedParamNameType Params[] = { +        std::make_pair(StringRef(), QualType()) // __context with shared vars +    }; +    ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, +                             Params); +    break; +  } +  case OMPD_taskloop_simd: { +    Sema::CapturedParamNameType Params[] = { +        std::make_pair(StringRef(), QualType()) // __context with shared vars +    }; +    ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, +                             Params); +    break; +  } +  case OMPD_distribute: { +    Sema::CapturedParamNameType Params[] = { +        std::make_pair(StringRef(), QualType()) // __context with shared vars +    }; +    ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, +                             Params); +    break; +  }    case OMPD_threadprivate:    case OMPD_taskyield:    case OMPD_barrier: @@ -1356,6 +1622,10 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,      ActOnCapturedRegionError();      return StmtError();    } + +  OMPOrderedClause *OC = nullptr; +  OMPScheduleClause *SC = nullptr; +  SmallVector<OMPLinearClause *, 4> LCs;    // This is required for proper codegen.    for (auto *Clause : Clauses) {      if (isOpenMPPrivate(Clause->getClauseKind()) || @@ -1377,10 +1647,42 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,        // Required for proper codegen of combined directives.        // TODO: add processing for other clauses.        if (auto *E = cast_or_null<Expr>( -              cast<OMPScheduleClause>(Clause)->getHelperChunkSize())) { -          MarkDeclarationsReferencedInExpr(E); -        } +              cast<OMPScheduleClause>(Clause)->getHelperChunkSize())) +        MarkDeclarationsReferencedInExpr(E);      } +    if (Clause->getClauseKind() == OMPC_schedule) +      SC = cast<OMPScheduleClause>(Clause); +    else if (Clause->getClauseKind() == OMPC_ordered) +      OC = cast<OMPOrderedClause>(Clause); +    else if (Clause->getClauseKind() == OMPC_linear) +      LCs.push_back(cast<OMPLinearClause>(Clause)); +  } +  bool ErrorFound = false; +  // OpenMP, 2.7.1 Loop Construct, Restrictions +  // The nonmonotonic modifier cannot be specified if an ordered clause is +  // specified. +  if (SC && +      (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic || +       SC->getSecondScheduleModifier() == +           OMPC_SCHEDULE_MODIFIER_nonmonotonic) && +      OC) { +    Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic +             ? SC->getFirstScheduleModifierLoc() +             : SC->getSecondScheduleModifierLoc(), +         diag::err_omp_schedule_nonmonotonic_ordered) +        << SourceRange(OC->getLocStart(), OC->getLocEnd()); +    ErrorFound = true; +  } +  if (!LCs.empty() && OC && OC->getNumForLoops()) { +    for (auto *C : LCs) { +      Diag(C->getLocStart(), diag::err_omp_linear_ordered) +          << SourceRange(OC->getLocStart(), OC->getLocEnd()); +    } +    ErrorFound = true; +  } +  if (ErrorFound) { +    ActOnCapturedRegionError(); +    return StmtError();    }    return ActOnCapturedRegionEnd(S.get());  } @@ -1419,6 +1721,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,    // | parallel         | cancellation    |                                    |    // |                  | point           | !                                  |    // | parallel         | cancel          | !                                  | +  // | parallel         | taskloop        | *                                  | +  // | parallel         | taskloop simd   | *                                  | +  // | parallel         | distribute      |                                    |      // +------------------+-----------------+------------------------------------+    // | for              | parallel        | *                                  |    // | for              | for             | +                                  | @@ -1445,6 +1750,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,    // | for              | cancellation    |                                    |    // |                  | point           | !                                  |    // | for              | cancel          | !                                  | +  // | for              | taskloop        | *                                  | +  // | for              | taskloop simd   | *                                  | +  // | for              | distribute      |                                    |    // +------------------+-----------------+------------------------------------+    // | master           | parallel        | *                                  |    // | master           | for             | +                                  | @@ -1471,6 +1779,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,    // | master           | cancellation    |                                    |    // |                  | point           |                                    |    // | master           | cancel          |                                    | +  // | master           | taskloop        | *                                  | +  // | master           | taskloop simd   | *                                  | +  // | master           | distribute      |                                    |    // +------------------+-----------------+------------------------------------+    // | critical         | parallel        | *                                  |    // | critical         | for             | +                                  | @@ -1496,6 +1807,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,    // | critical         | cancellation    |                                    |    // |                  | point           |                                    |    // | critical         | cancel          |                                    | +  // | critical         | taskloop        | *                                  | +  // | critical         | taskloop simd   | *                                  | +  // | critical         | distribute      |                                    |    // +------------------+-----------------+------------------------------------+    // | simd             | parallel        |                                    |    // | simd             | for             |                                    | @@ -1515,13 +1829,16 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,    // | simd             | taskwait        |                                    |    // | simd             | taskgroup       |                                    |    // | simd             | flush           |                                    | -  // | simd             | ordered         |                                    | +  // | simd             | ordered         | + (with simd clause)               |    // | simd             | atomic          |                                    |    // | simd             | target          |                                    |    // | simd             | teams           |                                    |    // | simd             | cancellation    |                                    |    // |                  | point           |                                    |    // | simd             | cancel          |                                    | +  // | simd             | taskloop        |                                    | +  // | simd             | taskloop simd   |                                    | +  // | simd             | distribute      |                                    |    // +------------------+-----------------+------------------------------------+    // | for simd         | parallel        |                                    |    // | for simd         | for             |                                    | @@ -1541,13 +1858,16 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,    // | for simd         | taskwait        |                                    |    // | for simd         | taskgroup       |                                    |    // | for simd         | flush           |                                    | -  // | for simd         | ordered         |                                    | +  // | for simd         | ordered         | + (with simd clause)               |    // | for simd         | atomic          |                                    |    // | for simd         | target          |                                    |    // | for simd         | teams           |                                    |    // | for simd         | cancellation    |                                    |    // |                  | point           |                                    |    // | for simd         | cancel          |                                    | +  // | for simd         | taskloop        |                                    | +  // | for simd         | taskloop simd   |                                    | +  // | for simd         | distribute      |                                    |    // +------------------+-----------------+------------------------------------+    // | parallel for simd| parallel        |                                    |    // | parallel for simd| for             |                                    | @@ -1567,13 +1887,16 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,    // | parallel for simd| taskwait        |                                    |    // | parallel for simd| taskgroup       |                                    |    // | parallel for simd| flush           |                                    | -  // | parallel for simd| ordered         |                                    | +  // | parallel for simd| ordered         | + (with simd clause)               |    // | parallel for simd| atomic          |                                    |    // | parallel for simd| target          |                                    |    // | parallel for simd| teams           |                                    |    // | parallel for simd| cancellation    |                                    |    // |                  | point           |                                    |    // | parallel for simd| cancel          |                                    | +  // | parallel for simd| taskloop        |                                    | +  // | parallel for simd| taskloop simd   |                                    | +  // | parallel for simd| distribute      |                                    |    // +------------------+-----------------+------------------------------------+    // | sections         | parallel        | *                                  |    // | sections         | for             | +                                  | @@ -1600,6 +1923,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,    // | sections         | cancellation    |                                    |    // |                  | point           | !                                  |    // | sections         | cancel          | !                                  | +  // | sections         | taskloop        | *                                  | +  // | sections         | taskloop simd   | *                                  | +  // | sections         | distribute      |                                    |    // +------------------+-----------------+------------------------------------+    // | section          | parallel        | *                                  |    // | section          | for             | +                                  | @@ -1626,6 +1952,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,    // | section          | cancellation    |                                    |    // |                  | point           | !                                  |    // | section          | cancel          | !                                  | +  // | section          | taskloop        | *                                  | +  // | section          | taskloop simd   | *                                  | +  // | section          | distribute      |                                    |    // +------------------+-----------------+------------------------------------+    // | single           | parallel        | *                                  |    // | single           | for             | +                                  | @@ -1652,6 +1981,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,    // | single           | cancellation    |                                    |    // |                  | point           |                                    |    // | single           | cancel          |                                    | +  // | single           | taskloop        | *                                  | +  // | single           | taskloop simd   | *                                  | +  // | single           | distribute      |                                    |    // +------------------+-----------------+------------------------------------+    // | parallel for     | parallel        | *                                  |    // | parallel for     | for             | +                                  | @@ -1678,6 +2010,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,    // | parallel for     | cancellation    |                                    |    // |                  | point           | !                                  |    // | parallel for     | cancel          | !                                  | +  // | parallel for     | taskloop        | *                                  | +  // | parallel for     | taskloop simd   | *                                  | +  // | parallel for     | distribute      |                                    |    // +------------------+-----------------+------------------------------------+    // | parallel sections| parallel        | *                                  |    // | parallel sections| for             | +                                  | @@ -1704,6 +2039,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,    // | parallel sections| cancellation    |                                    |    // |                  | point           | !                                  |    // | parallel sections| cancel          | !                                  | +  // | parallel sections| taskloop        | *                                  | +  // | parallel sections| taskloop simd   | *                                  | +  // | parallel sections| distribute      |                                    |     // +------------------+-----------------+------------------------------------+    // | task             | parallel        | *                                  |    // | task             | for             | +                                  | @@ -1730,6 +2068,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,    // | task             | cancellation    |                                    |    // |                  | point           | !                                  |    // | task             | cancel          | !                                  | +  // | task             | taskloop        | *                                  | +  // | task             | taskloop simd   | *                                  | +  // | task             | distribute      |                                    |    // +------------------+-----------------+------------------------------------+    // | ordered          | parallel        | *                                  |    // | ordered          | for             | +                                  | @@ -1756,6 +2097,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,    // | ordered          | cancellation    |                                    |    // |                  | point           |                                    |    // | ordered          | cancel          |                                    | +  // | ordered          | taskloop        | *                                  | +  // | ordered          | taskloop simd   | *                                  | +  // | ordered          | distribute      |                                    |    // +------------------+-----------------+------------------------------------+    // | atomic           | parallel        |                                    |    // | atomic           | for             |                                    | @@ -1782,6 +2126,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,    // | atomic           | cancellation    |                                    |    // |                  | point           |                                    |    // | atomic           | cancel          |                                    | +  // | atomic           | taskloop        |                                    | +  // | atomic           | taskloop simd   |                                    | +  // | atomic           | distribute      |                                    |     // +------------------+-----------------+------------------------------------+    // | target           | parallel        | *                                  |    // | target           | for             | *                                  | @@ -1808,6 +2155,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,    // | target           | cancellation    |                                    |    // |                  | point           |                                    |    // | target           | cancel          |                                    | +  // | target           | taskloop        | *                                  | +  // | target           | taskloop simd   | *                                  | +  // | target           | distribute      |                                    |    // +------------------+-----------------+------------------------------------+    // | teams            | parallel        | *                                  |    // | teams            | for             | +                                  | @@ -1834,6 +2184,95 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,    // | teams            | cancellation    |                                    |    // |                  | point           |                                    |    // | teams            | cancel          |                                    | +  // | teams            | taskloop        | +                                  | +  // | teams            | taskloop simd   | +                                  | +  // | teams            | distribute      | !                                  | +  // +------------------+-----------------+------------------------------------+ +  // | taskloop         | parallel        | *                                  | +  // | taskloop         | for             | +                                  | +  // | taskloop         | for simd        | +                                  | +  // | taskloop         | master          | +                                  | +  // | taskloop         | critical        | *                                  | +  // | taskloop         | simd            | *                                  | +  // | taskloop         | sections        | +                                  | +  // | taskloop         | section         | +                                  | +  // | taskloop         | single          | +                                  | +  // | taskloop         | parallel for    | *                                  | +  // | taskloop         |parallel for simd| *                                  | +  // | taskloop         |parallel sections| *                                  | +  // | taskloop         | task            | *                                  | +  // | taskloop         | taskyield       | *                                  | +  // | taskloop         | barrier         | +                                  | +  // | taskloop         | taskwait        | *                                  | +  // | taskloop         | taskgroup       | *                                  | +  // | taskloop         | flush           | *                                  | +  // | taskloop         | ordered         | +                                  | +  // | taskloop         | atomic          | *                                  | +  // | taskloop         | target          | *                                  | +  // | taskloop         | teams           | +                                  | +  // | taskloop         | cancellation    |                                    | +  // |                  | point           |                                    | +  // | taskloop         | cancel          |                                    | +  // | taskloop         | taskloop        | *                                  | +  // | taskloop         | distribute      |                                    | +  // +------------------+-----------------+------------------------------------+ +  // | taskloop simd    | parallel        |                                    | +  // | taskloop simd    | for             |                                    | +  // | taskloop simd    | for simd        |                                    | +  // | taskloop simd    | master          |                                    | +  // | taskloop simd    | critical        |                                    | +  // | taskloop simd    | simd            |                                    | +  // | taskloop simd    | sections        |                                    | +  // | taskloop simd    | section         |                                    | +  // | taskloop simd    | single          |                                    | +  // | taskloop simd    | parallel for    |                                    | +  // | taskloop simd    |parallel for simd|                                    | +  // | taskloop simd    |parallel sections|                                    | +  // | taskloop simd    | task            |                                    | +  // | taskloop simd    | taskyield       |                                    | +  // | taskloop simd    | barrier         |                                    | +  // | taskloop simd    | taskwait        |                                    | +  // | taskloop simd    | taskgroup       |                                    | +  // | taskloop simd    | flush           |                                    | +  // | taskloop simd    | ordered         | + (with simd clause)               | +  // | taskloop simd    | atomic          |                                    | +  // | taskloop simd    | target          |                                    | +  // | taskloop simd    | teams           |                                    | +  // | taskloop simd    | cancellation    |                                    | +  // |                  | point           |                                    | +  // | taskloop simd    | cancel          |                                    | +  // | taskloop simd    | taskloop        |                                    | +  // | taskloop simd    | taskloop simd   |                                    | +  // | taskloop simd    | distribute      |                                    | +  // +------------------+-----------------+------------------------------------+ +  // | distribute       | parallel        | *                                  | +  // | distribute       | for             | *                                  | +  // | distribute       | for simd        | *                                  | +  // | distribute       | master          | *                                  | +  // | distribute       | critical        | *                                  | +  // | distribute       | simd            | *                                  | +  // | distribute       | sections        | *                                  | +  // | distribute       | section         | *                                  | +  // | distribute       | single          | *                                  | +  // | distribute       | parallel for    | *                                  | +  // | distribute       |parallel for simd| *                                  | +  // | distribute       |parallel sections| *                                  | +  // | distribute       | task            | *                                  | +  // | distribute       | taskyield       | *                                  | +  // | distribute       | barrier         | *                                  | +  // | distribute       | taskwait        | *                                  | +  // | distribute       | taskgroup       | *                                  | +  // | distribute       | flush           | *                                  | +  // | distribute       | ordered         | +                                  | +  // | distribute       | atomic          | *                                  | +  // | distribute       | target          |                                    | +  // | distribute       | teams           |                                    | +  // | distribute       | cancellation    | +                                  | +  // |                  | point           |                                    | +  // | distribute       | cancel          | +                                  | +  // | distribute       | taskloop        | *                                  | +  // | distribute       | taskloop simd   | *                                  | +  // | distribute       | distribute      |                                    |    // +------------------+-----------------+------------------------------------+    if (Stack->getCurScope()) {      auto ParentRegion = Stack->getParentDirective(); @@ -1843,11 +2282,15 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,        NoRecommend,        ShouldBeInParallelRegion,        ShouldBeInOrderedRegion, -      ShouldBeInTargetRegion +      ShouldBeInTargetRegion, +      ShouldBeInTeamsRegion      } Recommend = NoRecommend; -    if (isOpenMPSimdDirective(ParentRegion)) { +    if (isOpenMPSimdDirective(ParentRegion) && CurrentRegion != OMPD_ordered) {        // OpenMP [2.16, Nesting of Regions]        // OpenMP constructs may not be nested inside a simd region. +      // OpenMP [2.8.1,simd Construct, Restrictions] +      // An ordered construct with the simd clause is the only OpenMP construct +      // that can appear in the simd region.        SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_simd);        return true;      } @@ -1890,16 +2333,19 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,        // construct-type-clause.        NestingProhibited =            !((CancelRegion == OMPD_parallel && ParentRegion == OMPD_parallel) || -            (CancelRegion == OMPD_for && ParentRegion == OMPD_for) || +            (CancelRegion == OMPD_for && +             (ParentRegion == OMPD_for || ParentRegion == OMPD_parallel_for)) ||              (CancelRegion == OMPD_taskgroup && ParentRegion == OMPD_task) ||              (CancelRegion == OMPD_sections && -             (ParentRegion == OMPD_section || ParentRegion == OMPD_sections))); +             (ParentRegion == OMPD_section || ParentRegion == OMPD_sections || +              ParentRegion == OMPD_parallel_sections)));      } else if (CurrentRegion == OMPD_master) {        // OpenMP [2.16, Nesting of Regions]        // A master region may not be closely nested inside a worksharing,        // atomic, or explicit task region.        NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) || -                          ParentRegion == OMPD_task; +                          ParentRegion == OMPD_task || +                          isOpenMPTaskLoopDirective(ParentRegion);      } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {        // OpenMP [2.16, Nesting of Regions]        // A critical region may not be nested (closely or otherwise) inside a @@ -1936,7 +2382,8 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,        NestingProhibited =            isOpenMPWorksharingDirective(ParentRegion) ||            ParentRegion == OMPD_task || ParentRegion == OMPD_master || -          ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered; +          ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered || +          isOpenMPTaskLoopDirective(ParentRegion);      } else if (isOpenMPWorksharingDirective(CurrentRegion) &&                 !isOpenMPParallelDirective(CurrentRegion)) {        // OpenMP [2.16, Nesting of Regions] @@ -1945,7 +2392,8 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,        NestingProhibited =            isOpenMPWorksharingDirective(ParentRegion) ||            ParentRegion == OMPD_task || ParentRegion == OMPD_master || -          ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered; +          ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered || +          isOpenMPTaskLoopDirective(ParentRegion);        Recommend = ShouldBeInParallelRegion;      } else if (CurrentRegion == OMPD_ordered) {        // OpenMP [2.16, Nesting of Regions] @@ -1953,9 +2401,14 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,        // atomic, or explicit task region.        // An ordered region must be closely nested inside a loop region (or        // parallel loop region) with an ordered clause. +      // OpenMP [2.8.1,simd Construct, Restrictions] +      // An ordered construct with the simd clause is the only OpenMP construct +      // that can appear in the simd region.        NestingProhibited = ParentRegion == OMPD_critical ||                            ParentRegion == OMPD_task || -                          !Stack->isParentOrderedRegion(); +                          isOpenMPTaskLoopDirective(ParentRegion) || +                          !(isOpenMPSimdDirective(ParentRegion) || +                            Stack->isParentOrderedRegion());        Recommend = ShouldBeInOrderedRegion;      } else if (isOpenMPTeamsDirective(CurrentRegion)) {        // OpenMP [2.16, Nesting of Regions] @@ -1970,10 +2423,17 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,        // distribute, parallel, parallel sections, parallel workshare, and the        // parallel loop and parallel loop SIMD constructs are the only OpenMP        // constructs that can be closely nested in the teams region. -      // TODO: add distribute directive. -      NestingProhibited = !isOpenMPParallelDirective(CurrentRegion); +      NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) && +                          !isOpenMPDistributeDirective(CurrentRegion);        Recommend = ShouldBeInParallelRegion;      } +    if (!NestingProhibited && isOpenMPDistributeDirective(CurrentRegion)) { +      // OpenMP 4.5 [2.17 Nesting of Regions] +      // The region associated with the distribute construct must be strictly +      // nested inside a teams region +      NestingProhibited = !isOpenMPTeamsDirective(ParentRegion); +      Recommend = ShouldBeInTeamsRegion; +    }      if (NestingProhibited) {        SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)            << CloseNesting << getOpenMPDirectiveName(ParentRegion) << Recommend @@ -1984,6 +2444,88 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,    return false;  } +static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, +                           ArrayRef<OMPClause *> Clauses, +                           ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) { +  bool ErrorFound = false; +  unsigned NamedModifiersNumber = 0; +  SmallVector<const OMPIfClause *, OMPC_unknown + 1> FoundNameModifiers( +      OMPD_unknown + 1); +  SmallVector<SourceLocation, 4> NameModifierLoc; +  for (const auto *C : Clauses) { +    if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) { +      // At most one if clause without a directive-name-modifier can appear on +      // the directive. +      OpenMPDirectiveKind CurNM = IC->getNameModifier(); +      if (FoundNameModifiers[CurNM]) { +        S.Diag(C->getLocStart(), diag::err_omp_more_one_clause) +            << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if) +            << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM); +        ErrorFound = true; +      } else if (CurNM != OMPD_unknown) { +        NameModifierLoc.push_back(IC->getNameModifierLoc()); +        ++NamedModifiersNumber; +      } +      FoundNameModifiers[CurNM] = IC; +      if (CurNM == OMPD_unknown) +        continue; +      // Check if the specified name modifier is allowed for the current +      // directive. +      // At most one if clause with the particular directive-name-modifier can +      // appear on the directive. +      bool MatchFound = false; +      for (auto NM : AllowedNameModifiers) { +        if (CurNM == NM) { +          MatchFound = true; +          break; +        } +      } +      if (!MatchFound) { +        S.Diag(IC->getNameModifierLoc(), +               diag::err_omp_wrong_if_directive_name_modifier) +            << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind); +        ErrorFound = true; +      } +    } +  } +  // If any if clause on the directive includes a directive-name-modifier then +  // 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(), +             diag::err_omp_no_more_if_clause); +    } else { +      std::string Values; +      std::string Sep(", "); +      unsigned AllowedCnt = 0; +      unsigned TotalAllowedNum = +          AllowedNameModifiers.size() - NamedModifiersNumber; +      for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End; +           ++Cnt) { +        OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt]; +        if (!FoundNameModifiers[NM]) { +          Values += "'"; +          Values += getOpenMPDirectiveName(NM); +          Values += "'"; +          if (AllowedCnt + 2 == TotalAllowedNum) +            Values += " or "; +          else if (AllowedCnt + 1 != TotalAllowedNum) +            Values += Sep; +          ++AllowedCnt; +        } +      } +      S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getLocStart(), +             diag::err_omp_unnamed_if_clause) +          << (TotalAllowedNum > 1) << Values; +    } +    for (auto Loc : NameModifierLoc) { +      S.Diag(Loc, diag::note_omp_previous_named_if_clause); +    } +    ErrorFound = true; +  } +  return ErrorFound; +} +  StmtResult Sema::ActOnOpenMPExecutableDirective(      OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,      OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses, @@ -2020,10 +2562,12 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(      }    } +  llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;    switch (Kind) {    case OMPD_parallel:      Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,                                         EndLoc); +    AllowedNameModifiers.push_back(OMPD_parallel);      break;    case OMPD_simd:      Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, @@ -2056,25 +2600,28 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(      Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);      break;    case OMPD_critical: -    assert(ClausesWithImplicit.empty() && -           "No clauses are allowed for 'omp critical' directive"); -    Res = ActOnOpenMPCriticalDirective(DirName, AStmt, StartLoc, EndLoc); +    Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt, +                                       StartLoc, EndLoc);      break;    case OMPD_parallel_for:      Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,                                            EndLoc, VarsWithInheritedDSA); +    AllowedNameModifiers.push_back(OMPD_parallel);      break;    case OMPD_parallel_for_simd:      Res = ActOnOpenMPParallelForSimdDirective(          ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); +    AllowedNameModifiers.push_back(OMPD_parallel);      break;    case OMPD_parallel_sections:      Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,                                                 StartLoc, EndLoc); +    AllowedNameModifiers.push_back(OMPD_parallel);      break;    case OMPD_task:      Res =          ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); +    AllowedNameModifiers.push_back(OMPD_task);      break;    case OMPD_taskyield:      assert(ClausesWithImplicit.empty() && @@ -2108,9 +2655,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(      Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);      break;    case OMPD_ordered: -    assert(ClausesWithImplicit.empty() && -           "No clauses are allowed for 'omp ordered' directive"); -    Res = ActOnOpenMPOrderedDirective(AStmt, StartLoc, EndLoc); +    Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc, +                                      EndLoc);      break;    case OMPD_atomic:      Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc, @@ -2123,6 +2669,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(    case OMPD_target:      Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,                                       EndLoc); +    AllowedNameModifiers.push_back(OMPD_target);      break;    case OMPD_cancellation_point:      assert(ClausesWithImplicit.empty() && @@ -2132,11 +2679,30 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(      Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);      break;    case OMPD_cancel: -    assert(ClausesWithImplicit.empty() && -           "No clauses are allowed for 'omp cancel' directive");      assert(AStmt == nullptr &&             "No associated statement allowed for 'omp cancel' directive"); -    Res = ActOnOpenMPCancelDirective(StartLoc, EndLoc, CancelRegion); +    Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc, +                                     CancelRegion); +    AllowedNameModifiers.push_back(OMPD_cancel); +    break; +  case OMPD_target_data: +    Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc, +                                         EndLoc); +    AllowedNameModifiers.push_back(OMPD_target_data); +    break; +  case OMPD_taskloop: +    Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc, +                                       EndLoc, VarsWithInheritedDSA); +    AllowedNameModifiers.push_back(OMPD_taskloop); +    break; +  case OMPD_taskloop_simd: +    Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc, +                                           EndLoc, VarsWithInheritedDSA); +    AllowedNameModifiers.push_back(OMPD_taskloop); +    break; +  case OMPD_distribute: +    Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc, +                                         EndLoc, VarsWithInheritedDSA);      break;    case OMPD_threadprivate:      llvm_unreachable("OpenMP Directive is not allowed"); @@ -2148,8 +2714,11 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(      Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)          << P.first << P.second->getSourceRange();    } -  if (!VarsWithInheritedDSA.empty()) -    return StmtError(); +  ErrorFound = !VarsWithInheritedDSA.empty() || ErrorFound; + +  if (!AllowedNameModifiers.empty()) +    ErrorFound = checkIfClauses(*this, Kind, Clauses, AllowedNameModifiers) || +                 ErrorFound;    if (ErrorFound)      return StmtError(); @@ -2160,7 +2729,9 @@ StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,                                                Stmt *AStmt,                                                SourceLocation StartLoc,                                                SourceLocation EndLoc) { -  assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); +  if (!AStmt) +    return StmtError(); +    CapturedStmt *CS = cast<CapturedStmt>(AStmt);    // 1.2.2 OpenMP Language Terminology    // Structured block - An executable statement with a single entry at the @@ -2171,8 +2742,8 @@ StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,    getCurFunction()->setHasBranchProtectedScope(); -  return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses, -                                      AStmt); +  return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, +                                      DSAStack->isCancelRegion());  }  namespace { @@ -2247,6 +2818,9 @@ public:    Expr *BuildPreCond(Scope *S, Expr *Cond) const;    /// \brief Build reference expression to the counter be used for codegen.    Expr *BuildCounterVar() const; +  /// \brief Build reference expression to the private counter be used for +  /// codegen. +  Expr *BuildPrivateCounterVar() const;    /// \brief Build initization of the counter be used for codegen.    Expr *BuildCounterInit() const;    /// \brief Build step of the counter be used for codegen. @@ -2261,8 +2835,8 @@ private:    /// \brief Helper to set loop counter variable and its initializer.    bool SetVarAndLB(VarDecl *NewVar, DeclRefExpr *NewVarRefExpr, Expr *NewLB);    /// \brief Helper to set upper bound. -  bool SetUB(Expr *NewUB, bool LessOp, bool StrictOp, const SourceRange &SR, -             const SourceLocation &SL); +  bool SetUB(Expr *NewUB, bool LessOp, bool StrictOp, SourceRange SR, +             SourceLocation SL);    /// \brief Helper to set loop increment.    bool SetStep(Expr *NewStep, bool Subtract);  }; @@ -2313,8 +2887,7 @@ bool OpenMPIterationSpaceChecker::SetVarAndLB(VarDecl *NewVar,  }  bool OpenMPIterationSpaceChecker::SetUB(Expr *NewUB, bool LessOp, bool StrictOp, -                                        const SourceRange &SR, -                                        const SourceLocation &SL) { +                                        SourceRange SR, SourceLocation SL) {    // State consistency checking to ensure correct usage.    assert(Var != nullptr && LB != nullptr && UB == nullptr && Step == nullptr &&           !TestIsLessOp && !TestIsStrictOp); @@ -2410,7 +2983,7 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S, bool EmitDiags) {    } else if (auto DS = dyn_cast<DeclStmt>(S)) {      if (DS->isSingleDecl()) {        if (auto Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) { -        if (Var->hasInit()) { +        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(), @@ -2630,6 +3203,8 @@ public:          NewVD->setPreviousDeclInSameBlockScope(              VD->isPreviousDeclInSameBlockScope());          VD->getDeclContext()->addHiddenDecl(NewVD); +        if (VD->hasAttrs()) +          NewVD->setAttrs(VD->getAttrs());          transformedLocalDecl(VD, NewVD);          return NewVD;        } @@ -2802,7 +3377,21 @@ Expr *OpenMPIterationSpaceChecker::BuildPreCond(Scope *S, Expr *Cond) const {  /// \brief Build reference expression to the counter be used for codegen.  Expr *OpenMPIterationSpaceChecker::BuildCounterVar() const { -  return buildDeclRefExpr(SemaRef, Var, Var->getType(), DefaultLoc); +  return buildDeclRefExpr(SemaRef, Var, Var->getType().getNonReferenceType(), +                          DefaultLoc); +} + +Expr *OpenMPIterationSpaceChecker::BuildPrivateCounterVar() const { +  if (Var && !Var->isInvalidDecl()) { +    auto Type = Var->getType().getNonReferenceType(); +    auto *PrivateVar = +        buildVarDecl(SemaRef, DefaultLoc, Type, Var->getName(), +                     Var->hasAttrs() ? &Var->getAttrs() : nullptr); +    if (PrivateVar->isInvalidDecl()) +      return nullptr; +    return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc); +  } +  return nullptr;  }  /// \brief Build initization of the counter be used for codegen. @@ -2820,6 +3409,8 @@ struct LoopIterationSpace {    Expr *NumIterations;    /// \brief The loop counter variable.    Expr *CounterVar; +  /// \brief Private loop counter variable. +  Expr *PrivateCounterVar;    /// \brief This is initializer for the initial value of #CounterVar.    Expr *CounterInit;    /// \brief This is step for the #CounterVar used to generate its update: @@ -2840,14 +3431,13 @@ struct LoopIterationSpace {  void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {    assert(getLangOpts().OpenMP && "OpenMP is not active.");    assert(Init && "Expected loop in canonical form."); -  unsigned CollapseIteration = DSAStack->getCollapseNumber(); -  if (CollapseIteration > 0 && +  unsigned AssociatedLoops = DSAStack->getAssociatedLoops(); +  if (AssociatedLoops > 0 &&        isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {      OpenMPIterationSpaceChecker ISC(*this, ForLoc); -    if (!ISC.CheckInit(Init, /*EmitDiags=*/false)) { +    if (!ISC.CheckInit(Init, /*EmitDiags=*/false))        DSAStack->addLoopControlVariable(ISC.GetLoopVar()); -    } -    DSAStack->setCollapseNumber(CollapseIteration - 1); +    DSAStack->setAssociatedLoops(AssociatedLoops - 1);    }  } @@ -2856,7 +3446,7 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {  static bool CheckOpenMPIterationSpace(      OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,      unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, -    Expr *NestedLoopCountExpr, +    Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr,      llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA,      LoopIterationSpace &ResultIterSpace) {    // OpenMP [2.6, Canonical Loop Form] @@ -2864,13 +3454,24 @@ static bool CheckOpenMPIterationSpace(    auto For = dyn_cast_or_null<ForStmt>(S);    if (!For) {      SemaRef.Diag(S->getLocStart(), diag::err_omp_not_for) -        << (NestedLoopCountExpr != nullptr) << getOpenMPDirectiveName(DKind) -        << NestedLoopCount << (CurrentNestedLoopCount > 0) -        << CurrentNestedLoopCount; -    if (NestedLoopCount > 1) -      SemaRef.Diag(NestedLoopCountExpr->getExprLoc(), -                   diag::note_omp_collapse_expr) -          << NestedLoopCountExpr->getSourceRange(); +        << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr) +        << getOpenMPDirectiveName(DKind) << NestedLoopCount +        << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount; +    if (NestedLoopCount > 1) { +      if (CollapseLoopCountExpr && OrderedLoopCountExpr) +        SemaRef.Diag(DSA.getConstructLoc(), +                     diag::note_omp_collapse_ordered_expr) +            << 2 << CollapseLoopCountExpr->getSourceRange() +            << OrderedLoopCountExpr->getSourceRange(); +      else if (CollapseLoopCountExpr) +        SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(), +                     diag::note_omp_collapse_ordered_expr) +            << 0 << CollapseLoopCountExpr->getSourceRange(); +      else +        SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(), +                     diag::note_omp_collapse_ordered_expr) +            << 1 << OrderedLoopCountExpr->getSourceRange(); +    }      return true;    }    assert(For->getBody()); @@ -2893,7 +3494,7 @@ static bool CheckOpenMPIterationSpace(    //   A variable of signed or unsigned integer type.    //   For C++, a variable of a random access iterator type.    //   For C, a variable of a pointer type. -  auto VarType = Var->getType(); +  auto VarType = Var->getType().getNonReferenceType();    if (!VarType->isDependentType() && !VarType->isIntegerType() &&        !VarType->isPointerType() &&        !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) { @@ -2929,12 +3530,12 @@ static bool CheckOpenMPIterationSpace(            ? ((NestedLoopCount == 1) ? OMPC_linear : OMPC_lastprivate)            : OMPC_private;    if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown && -        DVar.CKind != OMPC_threadprivate && DVar.CKind != PredeterminedCKind) || -       (isOpenMPWorksharingDirective(DKind) && !isOpenMPSimdDirective(DKind) && -        DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private && -        DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_threadprivate)) && -      ((DVar.CKind != OMPC_private && DVar.CKind != OMPC_threadprivate) || -       DVar.RefExpr != nullptr)) { +        DVar.CKind != PredeterminedCKind) || +       ((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop || +         isOpenMPDistributeDirective(DKind)) && +        !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)          << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind)          << getOpenMPClauseName(PredeterminedCKind); @@ -2945,7 +3546,8 @@ static bool CheckOpenMPIterationSpace(    } else if (LoopVarRefExpr != nullptr) {      // Make the loop iteration variable private (for worksharing constructs),      // linear (for simd directives with the only one associated loop) or -    // lastprivate (for simd directives with several collapsed loops). +    // lastprivate (for simd directives with several collapsed or ordered +    // loops).      if (DVar.CKind == OMPC_unknown)        DVar = DSA.hasDSA(Var, isOpenMPPrivate, MatchesAlways(),                          /*FromParent=*/false); @@ -2966,8 +3568,11 @@ static bool CheckOpenMPIterationSpace(    // Build the loop's iteration space representation.    ResultIterSpace.PreCond = ISC.BuildPreCond(DSA.getCurScope(), For->getCond());    ResultIterSpace.NumIterations = ISC.BuildNumIterations( -      DSA.getCurScope(), /* LimitedType */ isOpenMPWorksharingDirective(DKind)); +      DSA.getCurScope(), (isOpenMPWorksharingDirective(DKind) || +                          isOpenMPTaskLoopDirective(DKind) || +                          isOpenMPDistributeDirective(DKind)));    ResultIterSpace.CounterVar = ISC.BuildCounterVar(); +  ResultIterSpace.PrivateCounterVar = ISC.BuildPrivateCounterVar();    ResultIterSpace.CounterInit = ISC.BuildCounterInit();    ResultIterSpace.CounterStep = ISC.BuildCounterStep();    ResultIterSpace.InitSrcRange = ISC.GetInitSrcRange(); @@ -2978,6 +3583,7 @@ static bool CheckOpenMPIterationSpace(    HasErrors |= (ResultIterSpace.PreCond == nullptr ||                  ResultIterSpace.NumIterations == nullptr ||                  ResultIterSpace.CounterVar == nullptr || +                ResultIterSpace.PrivateCounterVar == nullptr ||                  ResultIterSpace.CounterInit == nullptr ||                  ResultIterSpace.CounterStep == nullptr); @@ -3091,17 +3697,33 @@ static bool FitsInto(unsigned Bits, bool Signed, Expr *E, Sema &SemaRef) {  /// \return Returns 0 if one of the collapsed stmts is not canonical for loop,  /// number of collapsed loops otherwise.  static unsigned -CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, -                Stmt *AStmt, Sema &SemaRef, DSAStackTy &DSA, +CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, +                Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef, +                DSAStackTy &DSA,                  llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA,                  OMPLoopDirective::HelperExprs &Built) {    unsigned NestedLoopCount = 1; -  if (NestedLoopCountExpr) { +  if (CollapseLoopCountExpr) {      // Found 'collapse' clause - calculate collapse number.      llvm::APSInt Result; -    if (NestedLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) +    if (CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext()))        NestedLoopCount = Result.getLimitedValue();    } +  if (OrderedLoopCountExpr) { +    // Found 'ordered' clause - calculate collapse number. +    llvm::APSInt Result; +    if (OrderedLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) { +      if (Result.getLimitedValue() < NestedLoopCount) { +        SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(), +                     diag::err_omp_wrong_ordered_loop_count) +            << OrderedLoopCountExpr->getSourceRange(); +        SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(), +                     diag::note_collapse_loop_count) +            << CollapseLoopCountExpr->getSourceRange(); +      } +      NestedLoopCount = Result.getLimitedValue(); +    } +  }    // This is helper routine for loop directives (e.g., 'for', 'simd',    // 'for simd', etc.).    SmallVector<LoopIterationSpace, 4> IterSpaces; @@ -3109,8 +3731,9 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,    Stmt *CurStmt = AStmt->IgnoreContainers(/* IgnoreCaptured */ true);    for (unsigned Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {      if (CheckOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA, Cnt, -                                  NestedLoopCount, NestedLoopCountExpr, -                                  VarsWithImplicitDSA, IterSpaces[Cnt])) +                                  NestedLoopCount, CollapseLoopCountExpr, +                                  OrderedLoopCountExpr, VarsWithImplicitDSA, +                                  IterSpaces[Cnt]))        return 0;      // Move on to the next nested for loop, or to the loop body.      // OpenMP [2.8.1, simd construct, Restrictions] @@ -3127,11 +3750,12 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,    // An example of what is generated for the following code:    // -  //   #pragma omp simd collapse(2) +  //   #pragma omp simd collapse(2) ordered(2)    //   for (i = 0; i < NI; ++i) -  //     for (j = J0; j < NJ; j+=2) { -  //     <loop body> -  //   } +  //     for (k = 0; k < NK; ++k) +  //       for (j = J0; j < NJ; j+=2) { +  //         <loop body> +  //       }    //    // We generate the code below.    // Note: the loop body may be outlined in CodeGen. @@ -3254,7 +3878,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,    QualType VType = LastIteration.get()->getType();    // Build variables passed into runtime, nesessary for worksharing directives.    ExprResult LB, UB, IL, ST, EUB; -  if (isOpenMPWorksharingDirective(DKind)) { +  if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) || +      isOpenMPDistributeDirective(DKind)) {      // Lower bound variable, initialized with zero.      VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");      LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc); @@ -3302,7 +3927,9 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,    {      VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.iv");      IV = buildDeclRefExpr(SemaRef, IVDecl, VType, InitLoc); -    Expr *RHS = isOpenMPWorksharingDirective(DKind) +    Expr *RHS = (isOpenMPWorksharingDirective(DKind) || +                 isOpenMPTaskLoopDirective(DKind) || +                 isOpenMPDistributeDirective(DKind))                      ? LB.get()                      : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();      Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS); @@ -3312,7 +3939,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,    // Loop condition (IV < NumIterations) or (IV <= UB) for worksharing loops.    SourceLocation CondLoc;    ExprResult Cond = -      isOpenMPWorksharingDirective(DKind) +      (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()); @@ -3332,7 +3960,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,    // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).    // Used for directives with static scheduling.    ExprResult NextLB, NextUB; -  if (isOpenMPWorksharingDirective(DKind)) { +  if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) || +      isOpenMPDistributeDirective(DKind)) {      // LB + ST      NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());      if (!NextLB.isUsable()) @@ -3437,6 +4066,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,        }        // Save results        Built.Counters[Cnt] = IS.CounterVar; +      Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;        Built.Inits[Cnt] = Init.get();        Built.Updates[Cnt] = Update.get();        Built.Finals[Cnt] = Final.get(); @@ -3467,26 +4097,60 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,    return NestedLoopCount;  } -static Expr *GetCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) { -  auto &&CollapseFilter = [](const OMPClause *C) -> bool { -    return C->getClauseKind() == OMPC_collapse; -  }; -  OMPExecutableDirective::filtered_clause_iterator<decltype(CollapseFilter)> I( -      Clauses, std::move(CollapseFilter)); -  if (I) -    return cast<OMPCollapseClause>(*I)->getNumForLoops(); +static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) { +  auto CollapseClauses = +      OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses); +  if (CollapseClauses.begin() != CollapseClauses.end()) +    return (*CollapseClauses.begin())->getNumForLoops(); +  return nullptr; +} + +static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) { +  auto OrderedClauses = +      OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses); +  if (OrderedClauses.begin() != OrderedClauses.end()) +    return (*OrderedClauses.begin())->getNumForLoops();    return nullptr;  } +static bool checkSimdlenSafelenValues(Sema &S, const Expr *Simdlen, +                                      const Expr *Safelen) { +  llvm::APSInt SimdlenRes, SafelenRes; +  if (Simdlen->isValueDependent() || Simdlen->isTypeDependent() || +      Simdlen->isInstantiationDependent() || +      Simdlen->containsUnexpandedParameterPack()) +    return false; +  if (Safelen->isValueDependent() || Safelen->isTypeDependent() || +      Safelen->isInstantiationDependent() || +      Safelen->containsUnexpandedParameterPack()) +    return false; +  Simdlen->EvaluateAsInt(SimdlenRes, S.Context); +  Safelen->EvaluateAsInt(SafelenRes, S.Context); +  // OpenMP 4.1 [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 parameter. +  if (SimdlenRes > SafelenRes) { +    S.Diag(Simdlen->getExprLoc(), diag::err_omp_wrong_simdlen_safelen_values) +        << Simdlen->getSourceRange() << Safelen->getSourceRange(); +    return true; +  } +  return false; +} +  StmtResult Sema::ActOnOpenMPSimdDirective(      ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,      SourceLocation EndLoc,      llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { +  if (!AStmt) +    return StmtError(); + +  assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");    OMPLoopDirective::HelperExprs B; -  // In presence of clause 'collapse', it will define the nested loops number. -  unsigned NestedLoopCount = -      CheckOpenMPLoop(OMPD_simd, GetCollapseNumberExpr(Clauses), AStmt, *this, -                      *DSAStack, VarsWithImplicitDSA, B); +  // In presence of clause 'collapse' or 'ordered' with number of loops, it will +  // define the nested loops number. +  unsigned NestedLoopCount = CheckOpenMPLoop( +      OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses), +      AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);    if (NestedLoopCount == 0)      return StmtError(); @@ -3503,6 +4167,24 @@ StmtResult Sema::ActOnOpenMPSimdDirective(      }    } +  // OpenMP 4.1 [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 parameter. +  OMPSafelenClause *Safelen = nullptr; +  OMPSimdlenClause *Simdlen = nullptr; +  for (auto *Clause : Clauses) { +    if (Clause->getClauseKind() == OMPC_safelen) +      Safelen = cast<OMPSafelenClause>(Clause); +    else if (Clause->getClauseKind() == OMPC_simdlen) +      Simdlen = cast<OMPSimdlenClause>(Clause); +    if (Safelen && Simdlen) +      break; +  } +  if (Simdlen && Safelen && +      checkSimdlenSafelenValues(*this, Simdlen->getSimdlen(), +                                Safelen->getSafelen())) +    return StmtError(); +    getCurFunction()->setHasBranchProtectedScope();    return OMPSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,                                    Clauses, AStmt, B); @@ -3512,31 +4194,52 @@ StmtResult Sema::ActOnOpenMPForDirective(      ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,      SourceLocation EndLoc,      llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { +  if (!AStmt) +    return StmtError(); + +  assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");    OMPLoopDirective::HelperExprs B; -  // In presence of clause 'collapse', it will define the nested loops number. -  unsigned NestedLoopCount = -      CheckOpenMPLoop(OMPD_for, GetCollapseNumberExpr(Clauses), AStmt, *this, -                      *DSAStack, VarsWithImplicitDSA, B); +  // In presence of clause 'collapse' or 'ordered' with number of loops, it will +  // define the nested loops number. +  unsigned NestedLoopCount = CheckOpenMPLoop( +      OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses), +      AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);    if (NestedLoopCount == 0)      return StmtError();    assert((CurContext->isDependentContext() || B.builtAll()) &&           "omp for loop exprs were not built"); +  if (!CurContext->isDependentContext()) { +    // Finalize the clauses that need pre-built expressions for CodeGen. +    for (auto C : Clauses) { +      if (auto LC = dyn_cast<OMPLinearClause>(C)) +        if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef), +                                     B.NumIterations, *this, CurScope)) +          return StmtError(); +    } +  } +    getCurFunction()->setHasBranchProtectedScope();    return OMPForDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount, -                                 Clauses, AStmt, B); +                                 Clauses, AStmt, B, DSAStack->isCancelRegion());  }  StmtResult Sema::ActOnOpenMPForSimdDirective(      ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,      SourceLocation EndLoc,      llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { +  if (!AStmt) +    return StmtError(); + +  assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");    OMPLoopDirective::HelperExprs B; -  // In presence of clause 'collapse', it will define the nested loops number. +  // In presence of clause 'collapse' or 'ordered' with number of loops, it will +  // define the nested loops number.    unsigned NestedLoopCount = -      CheckOpenMPLoop(OMPD_for_simd, GetCollapseNumberExpr(Clauses), AStmt, -                      *this, *DSAStack, VarsWithImplicitDSA, B); +      CheckOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses), +                      getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack, +                      VarsWithImplicitDSA, B);    if (NestedLoopCount == 0)      return StmtError(); @@ -3553,6 +4256,24 @@ StmtResult Sema::ActOnOpenMPForSimdDirective(      }    } +  // OpenMP 4.1 [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 parameter. +  OMPSafelenClause *Safelen = nullptr; +  OMPSimdlenClause *Simdlen = nullptr; +  for (auto *Clause : Clauses) { +    if (Clause->getClauseKind() == OMPC_safelen) +      Safelen = cast<OMPSafelenClause>(Clause); +    else if (Clause->getClauseKind() == OMPC_simdlen) +      Simdlen = cast<OMPSimdlenClause>(Clause); +    if (Safelen && Simdlen) +      break; +  } +  if (Simdlen && Safelen && +      checkSimdlenSafelenValues(*this, Simdlen->getSimdlen(), +                                Safelen->getSafelen())) +    return StmtError(); +    getCurFunction()->setHasBranchProtectedScope();    return OMPForSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,                                       Clauses, AStmt, B); @@ -3562,23 +4283,28 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,                                                Stmt *AStmt,                                                SourceLocation StartLoc,                                                SourceLocation EndLoc) { -  assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); +  if (!AStmt) +    return StmtError(); + +  assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");    auto BaseStmt = AStmt;    while (CapturedStmt *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))      BaseStmt = CS->getCapturedStmt();    if (auto C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {      auto S = C->children(); -    if (!S) +    if (S.begin() == S.end())        return StmtError();      // All associated statements must be '#pragma omp section' except for      // the first one. -    for (Stmt *SectionStmt : ++S) { +    for (Stmt *SectionStmt : llvm::make_range(std::next(S.begin()), S.end())) {        if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {          if (SectionStmt)            Diag(SectionStmt->getLocStart(),                 diag::err_omp_sections_substmt_not_section);          return StmtError();        } +      cast<OMPSectionDirective>(SectionStmt) +          ->setHasCancel(DSAStack->isCancelRegion());      }    } else {      Diag(AStmt->getLocStart(), diag::err_omp_sections_not_compound_stmt); @@ -3587,25 +4313,33 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,    getCurFunction()->setHasBranchProtectedScope(); -  return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses, -                                      AStmt); +  return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, +                                      DSAStack->isCancelRegion());  }  StmtResult Sema::ActOnOpenMPSectionDirective(Stmt *AStmt,                                               SourceLocation StartLoc,                                               SourceLocation EndLoc) { -  assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); +  if (!AStmt) +    return StmtError(); + +  assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");    getCurFunction()->setHasBranchProtectedScope(); +  DSAStack->setParentCancelRegion(DSAStack->isCancelRegion()); -  return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt); +  return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt, +                                     DSAStack->isCancelRegion());  }  StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,                                              Stmt *AStmt,                                              SourceLocation StartLoc,                                              SourceLocation EndLoc) { -  assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); +  if (!AStmt) +    return StmtError(); + +  assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");    getCurFunction()->setHasBranchProtectedScope(); @@ -3632,30 +4366,81 @@ StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,  StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt,                                              SourceLocation StartLoc,                                              SourceLocation EndLoc) { -  assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); +  if (!AStmt) +    return StmtError(); + +  assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");    getCurFunction()->setHasBranchProtectedScope();    return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt);  } -StmtResult -Sema::ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName, -                                   Stmt *AStmt, SourceLocation StartLoc, -                                   SourceLocation EndLoc) { -  assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); +StmtResult Sema::ActOnOpenMPCriticalDirective( +    const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses, +    Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { +  if (!AStmt) +    return StmtError(); + +  assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); + +  bool ErrorFound = false; +  llvm::APSInt Hint; +  SourceLocation HintLoc; +  bool DependentHint = false; +  for (auto *C : Clauses) { +    if (C->getClauseKind() == OMPC_hint) { +      if (!DirName.getName()) { +        Diag(C->getLocStart(), diag::err_omp_hint_clause_no_name); +        ErrorFound = true; +      } +      Expr *E = cast<OMPHintClause>(C)->getHint(); +      if (E->isTypeDependent() || E->isValueDependent() || +          E->isInstantiationDependent()) +        DependentHint = true; +      else { +        Hint = E->EvaluateKnownConstInt(Context); +        HintLoc = C->getLocStart(); +      } +    } +  } +  if (ErrorFound) +    return StmtError(); +  auto Pair = DSAStack->getCriticalWithHint(DirName); +  if (Pair.first && DirName.getName() && !DependentHint) { +    if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) { +      Diag(StartLoc, diag::err_omp_critical_with_hint); +      if (HintLoc.isValid()) { +        Diag(HintLoc, diag::note_omp_critical_hint_here) +            << 0 << Hint.toString(/*Radix=*/10, /*Signed=*/false); +      } else +        Diag(StartLoc, diag::note_omp_critical_no_hint) << 0; +      if (auto *C = Pair.first->getSingleClause<OMPHintClause>()) { +        Diag(C->getLocStart(), 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; +    } +  }    getCurFunction()->setHasBranchProtectedScope(); -  return OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc, -                                      AStmt); +  auto *Dir = OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc, +                                           Clauses, AStmt); +  if (!Pair.first && DirName.getName() && !DependentHint) +    DSAStack->addCriticalWithHint(Dir, Hint); +  return Dir;  }  StmtResult Sema::ActOnOpenMPParallelForDirective(      ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,      SourceLocation EndLoc,      llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { -  assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); +  if (!AStmt) +    return StmtError(); +    CapturedStmt *CS = cast<CapturedStmt>(AStmt);    // 1.2.2 OpenMP Language Terminology    // Structured block - An executable statement with a single entry at the @@ -3665,26 +4450,41 @@ StmtResult Sema::ActOnOpenMPParallelForDirective(    CS->getCapturedDecl()->setNothrow();    OMPLoopDirective::HelperExprs B; -  // In presence of clause 'collapse', it will define the nested loops number. +  // In presence of clause 'collapse' or 'ordered' with number of loops, it will +  // define the nested loops number.    unsigned NestedLoopCount = -      CheckOpenMPLoop(OMPD_parallel_for, GetCollapseNumberExpr(Clauses), AStmt, -                      *this, *DSAStack, VarsWithImplicitDSA, B); +      CheckOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses), +                      getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack, +                      VarsWithImplicitDSA, B);    if (NestedLoopCount == 0)      return StmtError();    assert((CurContext->isDependentContext() || B.builtAll()) &&           "omp parallel for loop exprs were not built"); +  if (!CurContext->isDependentContext()) { +    // Finalize the clauses that need pre-built expressions for CodeGen. +    for (auto C : Clauses) { +      if (auto LC = dyn_cast<OMPLinearClause>(C)) +        if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef), +                                     B.NumIterations, *this, CurScope)) +          return StmtError(); +    } +  } +    getCurFunction()->setHasBranchProtectedScope();    return OMPParallelForDirective::Create(Context, StartLoc, EndLoc, -                                         NestedLoopCount, Clauses, AStmt, B); +                                         NestedLoopCount, Clauses, AStmt, B, +                                         DSAStack->isCancelRegion());  }  StmtResult Sema::ActOnOpenMPParallelForSimdDirective(      ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,      SourceLocation EndLoc,      llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { -  assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); +  if (!AStmt) +    return StmtError(); +    CapturedStmt *CS = cast<CapturedStmt>(AStmt);    // 1.2.2 OpenMP Language Terminology    // Structured block - An executable statement with a single entry at the @@ -3694,10 +4494,12 @@ StmtResult Sema::ActOnOpenMPParallelForSimdDirective(    CS->getCapturedDecl()->setNothrow();    OMPLoopDirective::HelperExprs B; -  // In presence of clause 'collapse', it will define the nested loops number. +  // In presence of clause 'collapse' or 'ordered' with number of loops, it will +  // define the nested loops number.    unsigned NestedLoopCount = -      CheckOpenMPLoop(OMPD_parallel_for_simd, GetCollapseNumberExpr(Clauses), -                      AStmt, *this, *DSAStack, VarsWithImplicitDSA, B); +      CheckOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses), +                      getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack, +                      VarsWithImplicitDSA, B);    if (NestedLoopCount == 0)      return StmtError(); @@ -3711,6 +4513,24 @@ StmtResult Sema::ActOnOpenMPParallelForSimdDirective(      }    } +  // OpenMP 4.1 [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 parameter. +  OMPSafelenClause *Safelen = nullptr; +  OMPSimdlenClause *Simdlen = nullptr; +  for (auto *Clause : Clauses) { +    if (Clause->getClauseKind() == OMPC_safelen) +      Safelen = cast<OMPSafelenClause>(Clause); +    else if (Clause->getClauseKind() == OMPC_simdlen) +      Simdlen = cast<OMPSimdlenClause>(Clause); +    if (Safelen && Simdlen) +      break; +  } +  if (Simdlen && Safelen && +      checkSimdlenSafelenValues(*this, Simdlen->getSimdlen(), +                                Safelen->getSafelen())) +    return StmtError(); +    getCurFunction()->setHasBranchProtectedScope();    return OMPParallelForSimdDirective::Create(        Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); @@ -3720,23 +4540,28 @@ StmtResult  Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,                                             Stmt *AStmt, SourceLocation StartLoc,                                             SourceLocation EndLoc) { -  assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); +  if (!AStmt) +    return StmtError(); + +  assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");    auto BaseStmt = AStmt;    while (CapturedStmt *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))      BaseStmt = CS->getCapturedStmt();    if (auto C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {      auto S = C->children(); -    if (!S) +    if (S.begin() == S.end())        return StmtError();      // All associated statements must be '#pragma omp section' except for      // the first one. -    for (Stmt *SectionStmt : ++S) { +    for (Stmt *SectionStmt : llvm::make_range(std::next(S.begin()), S.end())) {        if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {          if (SectionStmt)            Diag(SectionStmt->getLocStart(),                 diag::err_omp_parallel_sections_substmt_not_section);          return StmtError();        } +      cast<OMPSectionDirective>(SectionStmt) +          ->setHasCancel(DSAStack->isCancelRegion());      }    } else {      Diag(AStmt->getLocStart(), @@ -3746,14 +4571,16 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,    getCurFunction()->setHasBranchProtectedScope(); -  return OMPParallelSectionsDirective::Create(Context, StartLoc, EndLoc, -                                              Clauses, AStmt); +  return OMPParallelSectionsDirective::Create( +      Context, StartLoc, EndLoc, Clauses, AStmt, DSAStack->isCancelRegion());  }  StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,                                            Stmt *AStmt, SourceLocation StartLoc,                                            SourceLocation EndLoc) { -  assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); +  if (!AStmt) +    return StmtError(); +    CapturedStmt *CS = cast<CapturedStmt>(AStmt);    // 1.2.2 OpenMP Language Terminology    // Structured block - An executable statement with a single entry at the @@ -3764,7 +4591,8 @@ StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,    getCurFunction()->setHasBranchProtectedScope(); -  return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt); +  return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, +                                  DSAStack->isCancelRegion());  }  StmtResult Sema::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, @@ -3785,7 +4613,10 @@ StmtResult Sema::ActOnOpenMPTaskwaitDirective(SourceLocation StartLoc,  StmtResult Sema::ActOnOpenMPTaskgroupDirective(Stmt *AStmt,                                                 SourceLocation StartLoc,                                                 SourceLocation EndLoc) { -  assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); +  if (!AStmt) +    return StmtError(); + +  assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");    getCurFunction()->setHasBranchProtectedScope(); @@ -3799,14 +4630,79 @@ StmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,    return OMPFlushDirective::Create(Context, StartLoc, EndLoc, Clauses);  } -StmtResult Sema::ActOnOpenMPOrderedDirective(Stmt *AStmt, +StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses, +                                             Stmt *AStmt,                                               SourceLocation StartLoc,                                               SourceLocation EndLoc) { -  assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); +  OMPClause *DependFound = nullptr; +  OMPClause *DependSourceClause = nullptr; +  OMPClause *DependSinkClause = nullptr; +  bool ErrorFound = false; +  OMPThreadsClause *TC = nullptr; +  OMPSIMDClause *SC = nullptr; +  for (auto *C : Clauses) { +    if (auto *DC = dyn_cast<OMPDependClause>(C)) { +      DependFound = C; +      if (DC->getDependencyKind() == OMPC_DEPEND_source) { +        if (DependSourceClause) { +          Diag(C->getLocStart(), diag::err_omp_more_one_clause) +              << getOpenMPDirectiveName(OMPD_ordered) +              << getOpenMPClauseName(OMPC_depend) << 2; +          ErrorFound = true; +        } else +          DependSourceClause = C; +        if (DependSinkClause) { +          Diag(C->getLocStart(), 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) +              << 1; +          ErrorFound = true; +        } +        DependSinkClause = C; +      } +    } else if (C->getClauseKind() == OMPC_threads) +      TC = cast<OMPThreadsClause>(C); +    else if (C->getClauseKind() == OMPC_simd) +      SC = cast<OMPSIMDClause>(C); +  } +  if (!ErrorFound && !SC && +      isOpenMPSimdDirective(DSAStack->getParentDirective())) { +    // OpenMP [2.8.1,simd Construct, Restrictions] +    // An ordered construct with the simd clause is the only OpenMP construct +    // that can appear in the simd region. +    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) +        << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind()); +    ErrorFound = true; +  } else if (DependFound && !DSAStack->getParentOrderedRegionParam()) { +    Diag(DependFound->getLocStart(), +         diag::err_omp_ordered_directive_without_param); +    ErrorFound = true; +  } else if (TC || Clauses.empty()) { +    if (auto *Param = DSAStack->getParentOrderedRegionParam()) { +      SourceLocation ErrLoc = TC ? TC->getLocStart() : StartLoc; +      Diag(ErrLoc, diag::err_omp_ordered_directive_with_param) +          << (TC != nullptr); +      Diag(Param->getLocStart(), diag::note_omp_ordered_param); +      ErrorFound = true; +    } +  } +  if ((!AStmt && !DependFound) || ErrorFound) +    return StmtError(); -  getCurFunction()->setHasBranchProtectedScope(); +  if (AStmt) { +    assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); -  return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, AStmt); +    getCurFunction()->setHasBranchProtectedScope(); +  } + +  return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);  }  namespace { @@ -4006,7 +4902,7 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,            NoteLoc = AtomicUnaryOp->getOperatorLoc();            NoteRange = SourceRange(NoteLoc, NoteLoc);          } -      } else { +      } else if (!AtomicBody->isInstantiationDependent()) {          ErrorFound = NotABinaryOrUnaryExpression;          NoteLoc = ErrorLoc = AtomicBody->getExprLoc();          NoteRange = ErrorRange = AtomicBody->getSourceRange(); @@ -4053,7 +4949,9 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,                                              Stmt *AStmt,                                              SourceLocation StartLoc,                                              SourceLocation EndLoc) { -  assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); +  if (!AStmt) +    return StmtError(); +    auto CS = cast<CapturedStmt>(AStmt);    // 1.2.2 OpenMP Language Terminology    // Structured block - An executable statement with a single entry at the @@ -4150,7 +5048,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,            NoteLoc = NotScalarExpr->getExprLoc();            NoteRange = NotScalarExpr->getSourceRange();          } -      } else { +      } else if (!AtomicBody->isInstantiationDependent()) {          ErrorFound = NotAnAssignmentOp;          ErrorLoc = AtomicBody->getExprLoc();          ErrorRange = AtomicBody->getSourceRange(); @@ -4211,7 +5109,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,            NoteLoc = NotScalarExpr->getExprLoc();            NoteRange = NotScalarExpr->getSourceRange();          } -      } else { +      } else if (!AtomicBody->isInstantiationDependent()) {          ErrorFound = NotAnAssignmentOp;          ErrorLoc = AtomicBody->getExprLoc();          ErrorRange = AtomicBody->getSourceRange(); @@ -4289,7 +5187,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,          UE = Checker.getUpdateExpr();          IsXLHSInRHSPart = Checker.isXLHSInRHSPart();          IsPostfixUpdate = Checker.isPostfixUpdate(); -      } else { +      } else if (!AtomicBody->isInstantiationDependent()) {          ErrorLoc = AtomicBody->getExprLoc();          ErrorRange = AtomicBody->getSourceRange();          NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc() @@ -4396,46 +5294,54 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,            }            if (!IsUpdateExprFound) {              //  { v = x; x = expr; } -            auto *FirstBinOp = dyn_cast<BinaryOperator>(First); -            if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) { -              ErrorFound = NotAnAssignmentOp; -              NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc() -                                              : First->getLocStart(); -              NoteRange = ErrorRange = FirstBinOp -                                           ? FirstBinOp->getSourceRange() -                                           : SourceRange(ErrorLoc, ErrorLoc); -            } else { -              auto *SecondBinOp = dyn_cast<BinaryOperator>(Second); -              if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) { +            auto *FirstExpr = dyn_cast<Expr>(First); +            auto *SecondExpr = dyn_cast<Expr>(Second); +            if (!FirstExpr || !SecondExpr || +                !(FirstExpr->isInstantiationDependent() || +                  SecondExpr->isInstantiationDependent())) { +              auto *FirstBinOp = dyn_cast<BinaryOperator>(First); +              if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {                  ErrorFound = NotAnAssignmentOp; -                NoteLoc = ErrorLoc = SecondBinOp ? SecondBinOp->getOperatorLoc() -                                                 : Second->getLocStart(); -                NoteRange = ErrorRange = SecondBinOp -                                             ? SecondBinOp->getSourceRange() +                NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc() +                                                : First->getLocStart(); +                NoteRange = ErrorRange = FirstBinOp +                                             ? FirstBinOp->getSourceRange()                                               : SourceRange(ErrorLoc, ErrorLoc);                } else { -                auto *PossibleXRHSInFirst = -                    FirstBinOp->getRHS()->IgnoreParenImpCasts(); -                auto *PossibleXLHSInSecond = -                    SecondBinOp->getLHS()->IgnoreParenImpCasts(); -                llvm::FoldingSetNodeID X1Id, X2Id; -                PossibleXRHSInFirst->Profile(X1Id, Context, /*Canonical=*/true); -                PossibleXLHSInSecond->Profile(X2Id, Context, -                                              /*Canonical=*/true); -                IsUpdateExprFound = X1Id == X2Id; -                if (IsUpdateExprFound) { -                  V = FirstBinOp->getLHS(); -                  X = SecondBinOp->getLHS(); -                  E = SecondBinOp->getRHS(); -                  UE = nullptr; -                  IsXLHSInRHSPart = false; -                  IsPostfixUpdate = true; +                auto *SecondBinOp = dyn_cast<BinaryOperator>(Second); +                if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) { +                  ErrorFound = NotAnAssignmentOp; +                  NoteLoc = ErrorLoc = SecondBinOp +                                           ? SecondBinOp->getOperatorLoc() +                                           : Second->getLocStart(); +                  NoteRange = ErrorRange = +                      SecondBinOp ? SecondBinOp->getSourceRange() +                                  : SourceRange(ErrorLoc, ErrorLoc);                  } else { -                  ErrorFound = NotASpecificExpression; -                  ErrorLoc = FirstBinOp->getExprLoc(); -                  ErrorRange = FirstBinOp->getSourceRange(); -                  NoteLoc = SecondBinOp->getLHS()->getExprLoc(); -                  NoteRange = SecondBinOp->getRHS()->getSourceRange(); +                  auto *PossibleXRHSInFirst = +                      FirstBinOp->getRHS()->IgnoreParenImpCasts(); +                  auto *PossibleXLHSInSecond = +                      SecondBinOp->getLHS()->IgnoreParenImpCasts(); +                  llvm::FoldingSetNodeID X1Id, X2Id; +                  PossibleXRHSInFirst->Profile(X1Id, Context, +                                               /*Canonical=*/true); +                  PossibleXLHSInSecond->Profile(X2Id, Context, +                                                /*Canonical=*/true); +                  IsUpdateExprFound = X1Id == X2Id; +                  if (IsUpdateExprFound) { +                    V = FirstBinOp->getLHS(); +                    X = SecondBinOp->getLHS(); +                    E = SecondBinOp->getRHS(); +                    UE = nullptr; +                    IsXLHSInRHSPart = false; +                    IsPostfixUpdate = true; +                  } else { +                    ErrorFound = NotASpecificExpression; +                    ErrorLoc = FirstBinOp->getExprLoc(); +                    ErrorRange = FirstBinOp->getSourceRange(); +                    NoteLoc = SecondBinOp->getLHS()->getExprLoc(); +                    NoteRange = SecondBinOp->getRHS()->getSourceRange(); +                  }                  }                }              } @@ -4474,7 +5380,16 @@ StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,                                              Stmt *AStmt,                                              SourceLocation StartLoc,                                              SourceLocation EndLoc) { -  assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); +  if (!AStmt) +    return StmtError(); + +  CapturedStmt *CS = cast<CapturedStmt>(AStmt); +  // 1.2.2 OpenMP Language Terminology +  // Structured block - An executable statement with a single entry at the +  // top and a single exit at the bottom. +  // The point of exit cannot be a branch out of the structured block. +  // longjmp() and throw() must not violate the entry/exit criteria. +  CS->getCapturedDecl()->setNothrow();    // OpenMP [2.16, Nesting of Regions]    // If specified, a teams construct must be contained within a target @@ -4511,10 +5426,27 @@ StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,    return OMPTargetDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);  } +StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses, +                                                Stmt *AStmt, +                                                SourceLocation StartLoc, +                                                SourceLocation EndLoc) { +  if (!AStmt) +    return StmtError(); + +  assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); + +  getCurFunction()->setHasBranchProtectedScope(); + +  return OMPTargetDataDirective::Create(Context, StartLoc, EndLoc, Clauses, +                                        AStmt); +} +  StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,                                             Stmt *AStmt, SourceLocation StartLoc,                                             SourceLocation EndLoc) { -  assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); +  if (!AStmt) +    return StmtError(); +    CapturedStmt *CS = cast<CapturedStmt>(AStmt);    // 1.2.2 OpenMP Language Terminology    // Structured block - An executable statement with a single entry at the @@ -4550,7 +5482,8 @@ Sema::ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc,                                                 CancelRegion);  } -StmtResult Sema::ActOnOpenMPCancelDirective(SourceLocation StartLoc, +StmtResult Sema::ActOnOpenMPCancelDirective(ArrayRef<OMPClause *> Clauses, +                                            SourceLocation StartLoc,                                              SourceLocation EndLoc,                                              OpenMPDirectiveKind CancelRegion) {    if (CancelRegion != OMPD_parallel && CancelRegion != OMPD_for && @@ -4567,7 +5500,123 @@ StmtResult Sema::ActOnOpenMPCancelDirective(SourceLocation StartLoc,      Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;      return StmtError();    } -  return OMPCancelDirective::Create(Context, StartLoc, EndLoc, CancelRegion); +  DSAStack->setParentCancelRegion(/*Cancel=*/true); +  return OMPCancelDirective::Create(Context, StartLoc, EndLoc, Clauses, +                                    CancelRegion); +} + +static bool checkGrainsizeNumTasksClauses(Sema &S, +                                          ArrayRef<OMPClause *> Clauses) { +  OMPClause *PrevClause = nullptr; +  bool ErrorFound = false; +  for (auto *C : Clauses) { +    if (C->getClauseKind() == OMPC_grainsize || +        C->getClauseKind() == OMPC_num_tasks) { +      if (!PrevClause) +        PrevClause = C; +      else if (PrevClause->getClauseKind() != C->getClauseKind()) { +        S.Diag(C->getLocStart(), +               diag::err_omp_grainsize_num_tasks_mutually_exclusive) +            << getOpenMPClauseName(C->getClauseKind()) +            << getOpenMPClauseName(PrevClause->getClauseKind()); +        S.Diag(PrevClause->getLocStart(), +               diag::note_omp_previous_grainsize_num_tasks) +            << getOpenMPClauseName(PrevClause->getClauseKind()); +        ErrorFound = true; +      } +    } +  } +  return ErrorFound; +} + +StmtResult Sema::ActOnOpenMPTaskLoopDirective( +    ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, +    SourceLocation EndLoc, +    llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { +  if (!AStmt) +    return StmtError(); + +  assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); +  OMPLoopDirective::HelperExprs B; +  // In presence of clause 'collapse' or 'ordered' with number of loops, it will +  // define the nested loops number. +  unsigned NestedLoopCount = +      CheckOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses), +                      /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack, +                      VarsWithImplicitDSA, B); +  if (NestedLoopCount == 0) +    return StmtError(); + +  assert((CurContext->isDependentContext() || B.builtAll()) && +         "omp for loop exprs were not built"); + +  // OpenMP, [2.9.2 taskloop Construct, Restrictions] +  // The grainsize clause and num_tasks clause are mutually exclusive and may +  // not appear on the same taskloop directive. +  if (checkGrainsizeNumTasksClauses(*this, Clauses)) +    return StmtError(); + +  getCurFunction()->setHasBranchProtectedScope(); +  return OMPTaskLoopDirective::Create(Context, StartLoc, EndLoc, +                                      NestedLoopCount, Clauses, AStmt, B); +} + +StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective( +    ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, +    SourceLocation EndLoc, +    llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { +  if (!AStmt) +    return StmtError(); + +  assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); +  OMPLoopDirective::HelperExprs B; +  // In presence of clause 'collapse' or 'ordered' with number of loops, it will +  // define the nested loops number. +  unsigned NestedLoopCount = +      CheckOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses), +                      /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack, +                      VarsWithImplicitDSA, B); +  if (NestedLoopCount == 0) +    return StmtError(); + +  assert((CurContext->isDependentContext() || B.builtAll()) && +         "omp for loop exprs were not built"); + +  // OpenMP, [2.9.2 taskloop Construct, Restrictions] +  // The grainsize clause and num_tasks clause are mutually exclusive and may +  // not appear on the same taskloop directive. +  if (checkGrainsizeNumTasksClauses(*this, Clauses)) +    return StmtError(); + +  getCurFunction()->setHasBranchProtectedScope(); +  return OMPTaskLoopSimdDirective::Create(Context, StartLoc, EndLoc, +                                          NestedLoopCount, Clauses, AStmt, B); +} + +StmtResult Sema::ActOnOpenMPDistributeDirective( +    ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, +    SourceLocation EndLoc, +    llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { +  if (!AStmt) +    return StmtError(); + +  assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); +  OMPLoopDirective::HelperExprs B; +  // In presence of clause 'collapse' with number of loops, it will +  // define the nested loops number. +  unsigned NestedLoopCount = +      CheckOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses), +                      nullptr /*ordered not a clause on distribute*/, AStmt, +                      *this, *DSAStack, VarsWithImplicitDSA, B); +  if (NestedLoopCount == 0) +    return StmtError(); + +  assert((CurContext->isDependentContext() || B.builtAll()) && +         "omp for loop exprs were not built"); + +  getCurFunction()->setHasBranchProtectedScope(); +  return OMPDistributeDirective::Create(Context, StartLoc, EndLoc, +                                        NestedLoopCount, Clauses, AStmt, B);  }  OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, @@ -4576,9 +5625,6 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,                                               SourceLocation EndLoc) {    OMPClause *Res = nullptr;    switch (Kind) { -  case OMPC_if: -    Res = ActOnOpenMPIfClause(Expr, StartLoc, LParenLoc, EndLoc); -    break;    case OMPC_final:      Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);      break; @@ -4588,9 +5634,37 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,    case OMPC_safelen:      Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);      break; +  case OMPC_simdlen: +    Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc); +    break;    case OMPC_collapse:      Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);      break; +  case OMPC_ordered: +    Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr); +    break; +  case OMPC_device: +    Res = ActOnOpenMPDeviceClause(Expr, StartLoc, LParenLoc, EndLoc); +    break; +  case OMPC_num_teams: +    Res = ActOnOpenMPNumTeamsClause(Expr, StartLoc, LParenLoc, EndLoc); +    break; +  case OMPC_thread_limit: +    Res = ActOnOpenMPThreadLimitClause(Expr, StartLoc, LParenLoc, EndLoc); +    break; +  case OMPC_priority: +    Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc); +    break; +  case OMPC_grainsize: +    Res = ActOnOpenMPGrainsizeClause(Expr, StartLoc, LParenLoc, EndLoc); +    break; +  case OMPC_num_tasks: +    Res = ActOnOpenMPNumTasksClause(Expr, StartLoc, LParenLoc, EndLoc); +    break; +  case OMPC_hint: +    Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc); +    break; +  case OMPC_if:    case OMPC_default:    case OMPC_proc_bind:    case OMPC_schedule: @@ -4603,7 +5677,6 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,    case OMPC_aligned:    case OMPC_copyin:    case OMPC_copyprivate: -  case OMPC_ordered:    case OMPC_nowait:    case OMPC_untied:    case OMPC_mergeable: @@ -4615,14 +5688,21 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,    case OMPC_capture:    case OMPC_seq_cst:    case OMPC_depend: +  case OMPC_threads: +  case OMPC_simd: +  case OMPC_map: +  case OMPC_nogroup:    case OMPC_unknown:      llvm_unreachable("Clause is not allowed.");    }    return Res;  } -OMPClause *Sema::ActOnOpenMPIfClause(Expr *Condition, SourceLocation StartLoc, +OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, +                                     Expr *Condition, SourceLocation StartLoc,                                       SourceLocation LParenLoc, +                                     SourceLocation NameModifierLoc, +                                     SourceLocation ColonLoc,                                       SourceLocation EndLoc) {    Expr *ValExpr = Condition;    if (!Condition->isValueDependent() && !Condition->isTypeDependent() && @@ -4636,7 +5716,8 @@ OMPClause *Sema::ActOnOpenMPIfClause(Expr *Condition, SourceLocation StartLoc,      ValExpr = Val.get();    } -  return new (Context) OMPIfClause(ValExpr, StartLoc, LParenLoc, EndLoc); +  return new (Context) OMPIfClause(NameModifier, ValExpr, StartLoc, LParenLoc, +                                   NameModifierLoc, ColonLoc, EndLoc);  }  OMPClause *Sema::ActOnOpenMPFinalClause(Expr *Condition, @@ -4701,38 +5782,52 @@ ExprResult Sema::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,    return PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);  } +static bool IsNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, +                                      OpenMPClauseKind CKind, +                                      bool StrictlyPositive) { +  if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() && +      !ValExpr->isInstantiationDependent()) { +    SourceLocation Loc = ValExpr->getExprLoc(); +    ExprResult Value = +        SemaRef.PerformOpenMPImplicitIntegerConversion(Loc, ValExpr); +    if (Value.isInvalid()) +      return false; + +    ValExpr = Value.get(); +    // The expression must evaluate to a non-negative integer value. +    llvm::APSInt Result; +    if (ValExpr->isIntegerConstantExpr(Result, SemaRef.Context) && +        Result.isSigned() && +        !((!StrictlyPositive && Result.isNonNegative()) || +          (StrictlyPositive && Result.isStrictlyPositive()))) { +      SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause) +          << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0) +          << ValExpr->getSourceRange(); +      return false; +    } +  } +  return true; +} +  OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,                                               SourceLocation StartLoc,                                               SourceLocation LParenLoc,                                               SourceLocation EndLoc) {    Expr *ValExpr = NumThreads; -  if (!NumThreads->isValueDependent() && !NumThreads->isTypeDependent() && -      !NumThreads->containsUnexpandedParameterPack()) { -    SourceLocation NumThreadsLoc = NumThreads->getLocStart(); -    ExprResult Val = -        PerformOpenMPImplicitIntegerConversion(NumThreadsLoc, NumThreads); -    if (Val.isInvalid()) -      return nullptr; -    ValExpr = Val.get(); - -    // OpenMP [2.5, Restrictions] -    //  The num_threads expression must evaluate to a positive integer value. -    llvm::APSInt Result; -    if (ValExpr->isIntegerConstantExpr(Result, Context) && Result.isSigned() && -        !Result.isStrictlyPositive()) { -      Diag(NumThreadsLoc, diag::err_omp_negative_expression_in_clause) -          << "num_threads" << NumThreads->getSourceRange(); -      return nullptr; -    } -  } +  // OpenMP [2.5, Restrictions] +  //  The num_threads expression must evaluate to a positive integer value. +  if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_num_threads, +                                 /*StrictlyPositive=*/true)) +    return nullptr;    return new (Context)        OMPNumThreadsClause(ValExpr, StartLoc, LParenLoc, EndLoc);  }  ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E, -                                                       OpenMPClauseKind CKind) { +                                                       OpenMPClauseKind CKind, +                                                       bool StrictlyPositive) {    if (!E)      return ExprError();    if (E->isValueDependent() || E->isTypeDependent() || @@ -4742,9 +5837,11 @@ ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,    ExprResult ICE = VerifyIntegerConstantExpression(E, &Result);    if (ICE.isInvalid())      return ExprError(); -  if (!Result.isStrictlyPositive()) { +  if ((StrictlyPositive && !Result.isStrictlyPositive()) || +      (!StrictlyPositive && !Result.isNonNegative())) {      Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause) -        << getOpenMPClauseName(CKind) << E->getSourceRange(); +        << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0) +        << E->getSourceRange();      return ExprError();    }    if (CKind == OMPC_aligned && !Result.isPowerOf2()) { @@ -4752,9 +5849,10 @@ ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,          << E->getSourceRange();      return ExprError();    } -  if (CKind == OMPC_collapse) { -    DSAStack->setCollapseNumber(Result.getExtValue()); -  } +  if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1) +    DSAStack->setAssociatedLoops(Result.getExtValue()); +  else if (CKind == OMPC_ordered) +    DSAStack->setAssociatedLoops(Result.getExtValue());    return ICE;  } @@ -4771,6 +5869,19 @@ OMPClause *Sema::ActOnOpenMPSafelenClause(Expr *Len, SourceLocation StartLoc,        OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);  } +OMPClause *Sema::ActOnOpenMPSimdlenClause(Expr *Len, SourceLocation StartLoc, +                                          SourceLocation LParenLoc, +                                          SourceLocation EndLoc) { +  // OpenMP [2.8.1, simd construct, Description] +  // The parameter of the simdlen clause must be a constant +  // positive integer expression. +  ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen); +  if (Simdlen.isInvalid()) +    return nullptr; +  return new (Context) +      OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc); +} +  OMPClause *Sema::ActOnOpenMPCollapseClause(Expr *NumForLoops,                                             SourceLocation StartLoc,                                             SourceLocation LParenLoc, @@ -4788,6 +5899,28 @@ OMPClause *Sema::ActOnOpenMPCollapseClause(Expr *NumForLoops,        OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);  } +OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc, +                                          SourceLocation EndLoc, +                                          SourceLocation LParenLoc, +                                          Expr *NumForLoops) { +  // OpenMP [2.7.1, loop construct, Description] +  // OpenMP [2.8.1, simd construct, Description] +  // OpenMP [2.9.6, distribute construct, Description] +  // The parameter of the ordered clause must be a constant +  // positive integer expression if any. +  if (NumForLoops && LParenLoc.isValid()) { +    ExprResult NumForLoopsResult = +        VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered); +    if (NumForLoopsResult.isInvalid()) +      return nullptr; +    NumForLoops = NumForLoopsResult.get(); +  } else +    NumForLoops = nullptr; +  DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops); +  return new (Context) +      OMPOrderedClause(NumForLoops, StartLoc, LParenLoc, EndLoc); +} +  OMPClause *Sema::ActOnOpenMPSimpleClause(      OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,      SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { @@ -4807,6 +5940,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(    case OMPC_final:    case OMPC_num_threads:    case OMPC_safelen: +  case OMPC_simdlen:    case OMPC_collapse:    case OMPC_schedule:    case OMPC_private: @@ -4830,39 +5964,58 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(    case OMPC_capture:    case OMPC_seq_cst:    case OMPC_depend: +  case OMPC_device: +  case OMPC_threads: +  case OMPC_simd: +  case OMPC_map: +  case OMPC_num_teams: +  case OMPC_thread_limit: +  case OMPC_priority: +  case OMPC_grainsize: +  case OMPC_nogroup: +  case OMPC_num_tasks: +  case OMPC_hint:    case OMPC_unknown:      llvm_unreachable("Clause is not allowed.");    }    return Res;  } +static std::string +getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, +                        ArrayRef<unsigned> Exclude = llvm::None) { +  std::string Values; +  unsigned Bound = Last >= 2 ? Last - 2 : 0; +  unsigned Skipped = Exclude.size(); +  auto S = Exclude.begin(), E = Exclude.end(); +  for (unsigned i = First; i < Last; ++i) { +    if (std::find(S, E, i) != E) { +      --Skipped; +      continue; +    } +    Values += "'"; +    Values += getOpenMPSimpleClauseTypeName(K, i); +    Values += "'"; +    if (i == Bound - Skipped) +      Values += " or "; +    else if (i != Bound + 1 - Skipped) +      Values += ", "; +  } +  return Values; +} +  OMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind,                                            SourceLocation KindKwLoc,                                            SourceLocation StartLoc,                                            SourceLocation LParenLoc,                                            SourceLocation EndLoc) {    if (Kind == OMPC_DEFAULT_unknown) { -    std::string Values;      static_assert(OMPC_DEFAULT_unknown > 0,                    "OMPC_DEFAULT_unknown not greater than 0"); -    std::string Sep(", "); -    for (unsigned i = 0; i < OMPC_DEFAULT_unknown; ++i) { -      Values += "'"; -      Values += getOpenMPSimpleClauseTypeName(OMPC_default, i); -      Values += "'"; -      switch (i) { -      case OMPC_DEFAULT_unknown - 2: -        Values += " or "; -        break; -      case OMPC_DEFAULT_unknown - 1: -        break; -      default: -        Values += Sep; -        break; -      } -    }      Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) -        << Values << getOpenMPClauseName(OMPC_default); +        << getListOfPossibleValues(OMPC_default, /*First=*/0, +                                   /*Last=*/OMPC_DEFAULT_unknown) +        << getOpenMPClauseName(OMPC_default);      return nullptr;    }    switch (Kind) { @@ -4886,25 +6039,10 @@ OMPClause *Sema::ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind,                                             SourceLocation LParenLoc,                                             SourceLocation EndLoc) {    if (Kind == OMPC_PROC_BIND_unknown) { -    std::string Values; -    std::string Sep(", "); -    for (unsigned i = 0; i < OMPC_PROC_BIND_unknown; ++i) { -      Values += "'"; -      Values += getOpenMPSimpleClauseTypeName(OMPC_proc_bind, i); -      Values += "'"; -      switch (i) { -      case OMPC_PROC_BIND_unknown - 2: -        Values += " or "; -        break; -      case OMPC_PROC_BIND_unknown - 1: -        break; -      default: -        Values += Sep; -        break; -      } -    }      Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) -        << Values << getOpenMPClauseName(OMPC_proc_bind); +        << getListOfPossibleValues(OMPC_proc_bind, /*First=*/0, +                                   /*Last=*/OMPC_PROC_BIND_unknown) +        << getOpenMPClauseName(OMPC_proc_bind);      return nullptr;    }    return new (Context) @@ -4912,21 +6050,33 @@ OMPClause *Sema::ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind,  }  OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause( -    OpenMPClauseKind Kind, unsigned Argument, Expr *Expr, +    OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,      SourceLocation StartLoc, SourceLocation LParenLoc, -    SourceLocation ArgumentLoc, SourceLocation CommaLoc, +    ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,      SourceLocation EndLoc) {    OMPClause *Res = nullptr;    switch (Kind) {    case OMPC_schedule: +    enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements }; +    assert(Argument.size() == NumberOfElements && +           ArgumentLoc.size() == NumberOfElements);      Res = ActOnOpenMPScheduleClause( -        static_cast<OpenMPScheduleClauseKind>(Argument), Expr, StartLoc, -        LParenLoc, ArgumentLoc, CommaLoc, EndLoc); +        static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]), +        static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]), +        static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr, +        StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2], +        ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);      break;    case OMPC_if: +    assert(Argument.size() == 1 && ArgumentLoc.size() == 1); +    Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()), +                              Expr, StartLoc, LParenLoc, ArgumentLoc.back(), +                              DelimLoc, EndLoc); +    break;    case OMPC_final:    case OMPC_num_threads:    case OMPC_safelen: +  case OMPC_simdlen:    case OMPC_collapse:    case OMPC_default:    case OMPC_proc_bind: @@ -4951,38 +6101,91 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(    case OMPC_capture:    case OMPC_seq_cst:    case OMPC_depend: +  case OMPC_device: +  case OMPC_threads: +  case OMPC_simd: +  case OMPC_map: +  case OMPC_num_teams: +  case OMPC_thread_limit: +  case OMPC_priority: +  case OMPC_grainsize: +  case OMPC_nogroup: +  case OMPC_num_tasks: +  case OMPC_hint:    case OMPC_unknown:      llvm_unreachable("Clause is not allowed.");    }    return Res;  } +static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1, +                                   OpenMPScheduleClauseModifier M2, +                                   SourceLocation M1Loc, SourceLocation M2Loc) { +  if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) { +    SmallVector<unsigned, 2> Excluded; +    if (M2 != OMPC_SCHEDULE_MODIFIER_unknown) +      Excluded.push_back(M2); +    if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) +      Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic); +    if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic) +      Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic); +    S.Diag(M1Loc, diag::err_omp_unexpected_clause_value) +        << getListOfPossibleValues(OMPC_schedule, +                                   /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1, +                                   /*Last=*/OMPC_SCHEDULE_MODIFIER_last, +                                   Excluded) +        << getOpenMPClauseName(OMPC_schedule); +    return true; +  } +  return false; +} +  OMPClause *Sema::ActOnOpenMPScheduleClause( +    OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,      OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, -    SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc, -    SourceLocation EndLoc) { +    SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, +    SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) { +  if (checkScheduleModifiers(*this, M1, M2, M1Loc, M2Loc) || +      checkScheduleModifiers(*this, M2, M1, M2Loc, M1Loc)) +    return nullptr; +  // OpenMP, 2.7.1, Loop Construct, Restrictions +  // Either the monotonic modifier or the nonmonotonic modifier can be specified +  // but not both. +  if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) || +      (M1 == OMPC_SCHEDULE_MODIFIER_monotonic && +       M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) || +      (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic && +       M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) { +    Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier) +        << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2) +        << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1); +    return nullptr; +  }    if (Kind == OMPC_SCHEDULE_unknown) {      std::string Values; -    std::string Sep(", "); -    for (unsigned i = 0; i < OMPC_SCHEDULE_unknown; ++i) { -      Values += "'"; -      Values += getOpenMPSimpleClauseTypeName(OMPC_schedule, i); -      Values += "'"; -      switch (i) { -      case OMPC_SCHEDULE_unknown - 2: -        Values += " or "; -        break; -      case OMPC_SCHEDULE_unknown - 1: -        break; -      default: -        Values += Sep; -        break; -      } +    if (M1Loc.isInvalid() && M2Loc.isInvalid()) { +      unsigned Exclude[] = {OMPC_SCHEDULE_unknown}; +      Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0, +                                       /*Last=*/OMPC_SCHEDULE_MODIFIER_last, +                                       Exclude); +    } else { +      Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0, +                                       /*Last=*/OMPC_SCHEDULE_unknown);      }      Diag(KindLoc, diag::err_omp_unexpected_clause_value)          << Values << getOpenMPClauseName(OMPC_schedule);      return nullptr;    } +  // OpenMP, 2.7.1, Loop Construct, Restrictions +  // The nonmonotonic modifier can only be specified with schedule(dynamic) or +  // schedule(guided). +  if ((M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic || +       M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) && +      Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) { +    Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc, +         diag::err_omp_schedule_nonmonotonic_static); +    return nullptr; +  }    Expr *ValExpr = ChunkSize;    Expr *HelperValExpr = nullptr;    if (ChunkSize) { @@ -5004,7 +6207,7 @@ OMPClause *Sema::ActOnOpenMPScheduleClause(        if (ValExpr->isIntegerConstantExpr(Result, Context)) {          if (Result.isSigned() && !Result.isStrictlyPositive()) {            Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause) -              << "schedule" << ChunkSize->getSourceRange(); +              << "schedule" << 1 << ChunkSize->getSourceRange();            return nullptr;          }        } else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective())) { @@ -5018,8 +6221,9 @@ OMPClause *Sema::ActOnOpenMPScheduleClause(      }    } -  return new (Context) OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, -                                         EndLoc, Kind, ValExpr, HelperValExpr); +  return new (Context) +      OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind, +                        ValExpr, HelperValExpr, M1, M1Loc, M2, M2Loc);  }  OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, @@ -5054,10 +6258,20 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,    case OMPC_seq_cst:      Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);      break; +  case OMPC_threads: +    Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc); +    break; +  case OMPC_simd: +    Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc); +    break; +  case OMPC_nogroup: +    Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc); +    break;    case OMPC_if:    case OMPC_final:    case OMPC_num_threads:    case OMPC_safelen: +  case OMPC_simdlen:    case OMPC_collapse:    case OMPC_schedule:    case OMPC_private: @@ -5074,18 +6288,20 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,    case OMPC_threadprivate:    case OMPC_flush:    case OMPC_depend: +  case OMPC_device: +  case OMPC_map: +  case OMPC_num_teams: +  case OMPC_thread_limit: +  case OMPC_priority: +  case OMPC_grainsize: +  case OMPC_num_tasks: +  case OMPC_hint:    case OMPC_unknown:      llvm_unreachable("Clause is not allowed.");    }    return Res;  } -OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc, -                                          SourceLocation EndLoc) { -  DSAStack->setOrderedRegion(); -  return new (Context) OMPOrderedClause(StartLoc, EndLoc); -} -  OMPClause *Sema::ActOnOpenMPNowaitClause(SourceLocation StartLoc,                                           SourceLocation EndLoc) {    DSAStack->setNowaitRegion(); @@ -5127,12 +6343,28 @@ OMPClause *Sema::ActOnOpenMPSeqCstClause(SourceLocation StartLoc,    return new (Context) OMPSeqCstClause(StartLoc, EndLoc);  } +OMPClause *Sema::ActOnOpenMPThreadsClause(SourceLocation StartLoc, +                                          SourceLocation EndLoc) { +  return new (Context) OMPThreadsClause(StartLoc, EndLoc); +} + +OMPClause *Sema::ActOnOpenMPSIMDClause(SourceLocation StartLoc, +                                       SourceLocation EndLoc) { +  return new (Context) OMPSIMDClause(StartLoc, EndLoc); +} + +OMPClause *Sema::ActOnOpenMPNogroupClause(SourceLocation StartLoc, +                                          SourceLocation EndLoc) { +  return new (Context) OMPNogroupClause(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, -    SourceLocation DepLoc) { +    OpenMPLinearClauseKind LinKind, OpenMPMapClauseKind MapTypeModifier,  +    OpenMPMapClauseKind MapType, SourceLocation DepLinMapLoc) {    OMPClause *Res = nullptr;    switch (Kind) {    case OMPC_private: @@ -5153,7 +6385,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(      break;    case OMPC_linear:      Res = ActOnOpenMPLinearClause(VarList, TailExpr, StartLoc, LParenLoc, -                                  ColonLoc, EndLoc); +                                  LinKind, DepLinMapLoc, ColonLoc, EndLoc);      break;    case OMPC_aligned:      Res = ActOnOpenMPAlignedClause(VarList, TailExpr, StartLoc, LParenLoc, @@ -5169,13 +6401,18 @@ OMPClause *Sema::ActOnOpenMPVarListClause(      Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);      break;    case OMPC_depend: -    Res = ActOnOpenMPDependClause(DepKind, DepLoc, ColonLoc, VarList, StartLoc, -                                  LParenLoc, EndLoc); +    Res = ActOnOpenMPDependClause(DepKind, DepLinMapLoc, ColonLoc, VarList,  +                                  StartLoc, LParenLoc, EndLoc); +    break; +  case OMPC_map: +    Res = ActOnOpenMPMapClause(MapTypeModifier, MapType, DepLinMapLoc, ColonLoc, +                               VarList, StartLoc, LParenLoc, EndLoc);      break;    case OMPC_if:    case OMPC_final:    case OMPC_num_threads:    case OMPC_safelen: +  case OMPC_simdlen:    case OMPC_collapse:    case OMPC_default:    case OMPC_proc_bind: @@ -5190,6 +6427,16 @@ OMPClause *Sema::ActOnOpenMPVarListClause(    case OMPC_update:    case OMPC_capture:    case OMPC_seq_cst: +  case OMPC_device: +  case OMPC_threads: +  case OMPC_simd: +  case OMPC_num_teams: +  case OMPC_thread_limit: +  case OMPC_priority: +  case OMPC_grainsize: +  case OMPC_nogroup: +  case OMPC_num_tasks: +  case OMPC_hint:    case OMPC_unknown:      llvm_unreachable("Clause is not allowed.");    } @@ -5240,16 +6487,7 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,                              diag::err_omp_private_incomplete_type)) {        continue;      } -    if (Type->isReferenceType()) { -      Diag(ELoc, diag::err_omp_clause_ref_type_arg) -          << getOpenMPClauseName(OMPC_private) << Type; -      bool IsDecl = -          VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; -      Diag(VD->getLocation(), -           IsDecl ? diag::note_previous_decl : diag::note_defined_here) -          << VD; -      continue; -    } +    Type = Type.getNonReferenceType();      // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced      // in a Construct] @@ -5290,7 +6528,8 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,      // IdResolver, so the code in the OpenMP region uses original variable for      // proper diagnostics.      Type = Type.getUnqualifiedType(); -    auto VDPrivate = buildVarDecl(*this, DE->getExprLoc(), Type, VD->getName()); +    auto VDPrivate = buildVarDecl(*this, DE->getExprLoc(), Type, VD->getName(), +                                  VD->hasAttrs() ? &VD->getAttrs() : nullptr);      ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false);      if (VDPrivate->isInvalidDecl())        continue; @@ -5384,23 +6623,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,                              diag::err_omp_firstprivate_incomplete_type)) {        continue;      } -    if (Type->isReferenceType()) { -      if (IsImplicitClause) { -        Diag(ImplicitClauseLoc, -             diag::err_omp_task_predetermined_firstprivate_ref_type_arg) -            << Type; -        Diag(RefExpr->getExprLoc(), diag::note_used_here); -      } else { -        Diag(ELoc, diag::err_omp_clause_ref_type_arg) -            << getOpenMPClauseName(OMPC_firstprivate) << Type; -      } -      bool IsDecl = -          VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; -      Diag(VD->getLocation(), -           IsDecl ? diag::note_previous_decl : diag::note_defined_here) -          << VD; -      continue; -    } +    Type = Type.getNonReferenceType();      // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]      //  A variable of class type (or array thereof) that appears in a private @@ -5492,6 +6715,49 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,            continue;          }        } + +      // OpenMP 4.5 [2.15.3.4, Restrictions, p.3] +      // A list item that is private within a teams region must not appear in a +      // firstprivate clause on a distribute construct if any of the distribute +      // regions arising from the distribute construct ever bind to any of the +      // teams regions arising from the teams construct. +      // OpenMP 4.5 [2.15.3.4, Restrictions, p.3] +      // A list item that appears in a reduction clause of a teams construct +      // must not appear in a firstprivate clause on a distribute construct if +      // any of the distribute regions arising from the distribute construct +      // ever bind to any of the teams regions arising from the teams construct. +      // OpenMP 4.5 [2.10.8, Distribute Construct, p.3] +      // A list item may appear in a firstprivate or lastprivate clause but not +      // both. +      if (CurrDir == OMPD_distribute) { +        DVar = DSAStack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_private), +                                         [](OpenMPDirectiveKind K) -> bool { +                                           return isOpenMPTeamsDirective(K); +                                         }, +                                         false); +        if (DVar.CKind == OMPC_private && isOpenMPTeamsDirective(DVar.DKind)) { +          Diag(ELoc, diag::err_omp_firstprivate_distribute_private_teams); +          ReportOriginalDSA(*this, DSAStack, VD, DVar); +          continue; +        } +        DVar = DSAStack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_reduction), +                                         [](OpenMPDirectiveKind K) -> bool { +                                           return isOpenMPTeamsDirective(K); +                                         }, +                                         false); +        if (DVar.CKind == OMPC_reduction && +            isOpenMPTeamsDirective(DVar.DKind)) { +          Diag(ELoc, diag::err_omp_firstprivate_distribute_in_teams_reduction); +          ReportOriginalDSA(*this, DSAStack, VD, DVar); +          continue; +        } +        DVar = DSAStack->getTopDSA(VD, false); +        if (DVar.CKind == OMPC_lastprivate) { +          Diag(ELoc, diag::err_omp_firstprivate_and_lastprivate_in_distribute); +          ReportOriginalDSA(*this, DSAStack, VD, DVar); +          continue; +        } +      }      }      // Variably modified types are not supported for tasks. @@ -5509,7 +6775,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,      }      Type = Type.getUnqualifiedType(); -    auto VDPrivate = buildVarDecl(*this, ELoc, Type, VD->getName()); +    auto VDPrivate = buildVarDecl(*this, ELoc, Type, VD->getName(), +                                  VD->hasAttrs() ? &VD->getAttrs() : nullptr);      // Generate helper private variable and initialize it with the value of the      // original variable. The address of the original variable is replaced by      // the address of the new private variable in the CodeGen. This new variable @@ -5536,6 +6803,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,          VDPrivate->setInvalidDecl();        else          VDPrivate->setInit(Result.getAs<Expr>()); +      // Remove temp variable declaration. +      Context.Deallocate(VDInitTemp);      } else {        auto *VDInit =            buildVarDecl(*this, DE->getLocStart(), Type, ".firstprivate.temp"); @@ -5618,16 +6887,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,                              diag::err_omp_lastprivate_incomplete_type)) {        continue;      } -    if (Type->isReferenceType()) { -      Diag(ELoc, diag::err_omp_clause_ref_type_arg) -          << getOpenMPClauseName(OMPC_lastprivate) << Type; -      bool IsDecl = -          VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; -      Diag(VD->getLocation(), -           IsDecl ? diag::note_previous_decl : diag::note_defined_here) -          << VD; -      continue; -    } +    Type = Type.getNonReferenceType();      // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced      // in a Construct] @@ -5674,11 +6934,13 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,      //  operator for the class type.      Type = Context.getBaseElementType(Type).getNonReferenceType();      auto *SrcVD = buildVarDecl(*this, DE->getLocStart(), -                               Type.getUnqualifiedType(), ".lastprivate.src"); +                               Type.getUnqualifiedType(), ".lastprivate.src", +                               VD->hasAttrs() ? &VD->getAttrs() : nullptr);      auto *PseudoSrcExpr = buildDeclRefExpr(          *this, SrcVD, Type.getUnqualifiedType(), DE->getExprLoc());      auto *DstVD = -        buildVarDecl(*this, DE->getLocStart(), Type, ".lastprivate.dst"); +        buildVarDecl(*this, DE->getLocStart(), Type, ".lastprivate.dst", +                     VD->hasAttrs() ? &VD->getAttrs() : nullptr);      auto *PseudoDstExpr =          buildDeclRefExpr(*this, DstVD, Type, DE->getExprLoc());      // For arrays generate assignment operation for single element and replace @@ -5692,6 +6954,18 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,      if (AssignmentOp.isInvalid())        continue; +    // OpenMP 4.5 [2.10.8, Distribute Construct, p.3] +    // A list item may appear in a firstprivate or lastprivate clause but not +    // both. +    if (CurrDir == OMPD_distribute) { +      DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false); +      if (DVar.CKind == OMPC_firstprivate) { +        Diag(ELoc, diag::err_omp_firstprivate_and_lastprivate_in_distribute); +        ReportOriginalDSA(*this, DSAStack, VD, DVar); +        continue; +      } +    } +      if (TopDVar.CKind != OMPC_firstprivate)        DSAStack->addDSA(VD, DE, OMPC_lastprivate);      Vars.push_back(DE); @@ -5879,6 +7153,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause(    case OO_Call:    case OO_Subscript:    case OO_Conditional: +  case OO_Coawait:    case NUM_OVERLOADED_OPERATORS:      llvm_unreachable("Unexpected reduction identifier");    case OO_None: @@ -5903,6 +7178,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause(    }    SmallVector<Expr *, 8> Vars; +  SmallVector<Expr *, 8> Privates;    SmallVector<Expr *, 8> LHSs;    SmallVector<Expr *, 8> RHSs;    SmallVector<Expr *, 8> ReductionOps; @@ -5911,6 +7187,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause(      if (isa<DependentScopeDeclRefExpr>(RefExpr)) {        // It will be analyzed later.        Vars.push_back(RefExpr); +      Privates.push_back(nullptr);        LHSs.push_back(nullptr);        RHSs.push_back(nullptr);        ReductionOps.push_back(nullptr); @@ -5922,6 +7199,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause(          RefExpr->containsUnexpandedParameterPack()) {        // It will be analyzed later.        Vars.push_back(RefExpr); +      Privates.push_back(nullptr);        LHSs.push_back(nullptr);        RHSs.push_back(nullptr);        ReductionOps.push_back(nullptr); @@ -5937,14 +7215,53 @@ OMPClause *Sema::ActOnOpenMPReductionClause(      // OpenMP  [2.14.3.3, Restrictions, p.1]      //  A variable that is part of another variable (as an array or      //  structure element) cannot appear in a private clause. -    auto DE = dyn_cast<DeclRefExpr>(RefExpr); -    if (!DE || !isa<VarDecl>(DE->getDecl())) { -      Diag(ELoc, diag::err_omp_expected_var_name) << ERange; +    auto *DE = dyn_cast<DeclRefExpr>(RefExpr); +    auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr); +    auto *OASE = dyn_cast<OMPArraySectionExpr>(RefExpr); +    if (!ASE && !OASE && (!DE || !isa<VarDecl>(DE->getDecl()))) { +      Diag(ELoc, diag::err_omp_expected_var_name_or_array_item) << ERange;        continue;      } -    auto D = DE->getDecl(); -    auto VD = cast<VarDecl>(D); -    auto Type = VD->getType(); +    QualType Type; +    VarDecl *VD = nullptr; +    if (DE) { +      auto D = DE->getDecl(); +      VD = cast<VarDecl>(D); +      Type = VD->getType(); +    } else if (ASE) { +      Type = ASE->getType(); +      auto *Base = ASE->getBase()->IgnoreParenImpCasts(); +      while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) +        Base = TempASE->getBase()->IgnoreParenImpCasts(); +      DE = dyn_cast<DeclRefExpr>(Base); +      if (DE) +        VD = dyn_cast<VarDecl>(DE->getDecl()); +      if (!VD) { +        Diag(Base->getExprLoc(), diag::err_omp_expected_base_var_name) +            << 0 << Base->getSourceRange(); +        continue; +      } +    } else if (OASE) { +      auto BaseType = OMPArraySectionExpr::getBaseOriginalType(OASE->getBase()); +      if (auto *ATy = BaseType->getAsArrayTypeUnsafe()) +        Type = ATy->getElementType(); +      else +        Type = BaseType->getPointeeType(); +      auto *Base = OASE->getBase()->IgnoreParenImpCasts(); +      while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) +        Base = TempOASE->getBase()->IgnoreParenImpCasts(); +      while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) +        Base = TempASE->getBase()->IgnoreParenImpCasts(); +      DE = dyn_cast<DeclRefExpr>(Base); +      if (DE) +        VD = dyn_cast<VarDecl>(DE->getDecl()); +      if (!VD) { +        Diag(Base->getExprLoc(), diag::err_omp_expected_base_var_name) +            << 1 << Base->getSourceRange(); +        continue; +      } +    } +      // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]      //  A variable that appears in a private clause must not have an incomplete      //  type or a reference type. @@ -5955,36 +7272,42 @@ OMPClause *Sema::ActOnOpenMPReductionClause(      // Arrays may not appear in a reduction clause.      if (Type.getNonReferenceType()->isArrayType()) {        Diag(ELoc, diag::err_omp_reduction_type_array) << Type << ERange; -      bool IsDecl = -          VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; -      Diag(VD->getLocation(), -           IsDecl ? diag::note_previous_decl : diag::note_defined_here) -          << VD; +      if (!ASE && !OASE) { +        bool IsDecl = VD->isThisDeclarationADefinition(Context) == +                      VarDecl::DeclarationOnly; +        Diag(VD->getLocation(), +             IsDecl ? diag::note_previous_decl : diag::note_defined_here) +            << VD; +      }        continue;      }      // 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)) { -      Diag(ELoc, diag::err_omp_const_variable) +      Diag(ELoc, diag::err_omp_const_reduction_list_item)            << getOpenMPClauseName(OMPC_reduction) << Type << ERange; -      bool IsDecl = -          VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; -      Diag(VD->getLocation(), -           IsDecl ? diag::note_previous_decl : diag::note_defined_here) -          << VD; +      if (!ASE && !OASE) { +        bool IsDecl = VD->isThisDeclarationADefinition(Context) == +                      VarDecl::DeclarationOnly; +        Diag(VD->getLocation(), +             IsDecl ? diag::note_previous_decl : diag::note_defined_here) +            << VD; +      }        continue;      }      // 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. -    VarDecl *VDDef = VD->getDefinition(); -    if (Type->isReferenceType() && VDDef) { -      DSARefChecker Check(DSAStack); -      if (Check.Visit(VDDef->getInit())) { -        Diag(ELoc, diag::err_omp_reduction_ref_type_arg) << ERange; -        Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef; -        continue; +    if (!ASE && !OASE) { +      VarDecl *VDDef = VD->getDefinition(); +      if (Type->isReferenceType() && VDDef) { +        DSARefChecker Check(DSAStack); +        if (Check.Visit(VDDef->getInit())) { +          Diag(ELoc, diag::err_omp_reduction_ref_type_arg) << ERange; +          Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef; +          continue; +        }        }      }      // OpenMP [2.14.3.6, reduction clause, Restrictions] @@ -6000,21 +7323,25 @@ OMPClause *Sema::ActOnOpenMPReductionClause(            (getLangOpts().CPlusPlus && Type->isArithmeticType()))) {        Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)            << getLangOpts().CPlusPlus; -      bool IsDecl = -          VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; -      Diag(VD->getLocation(), -           IsDecl ? diag::note_previous_decl : diag::note_defined_here) -          << VD; +      if (!ASE && !OASE) { +        bool IsDecl = VD->isThisDeclarationADefinition(Context) == +                      VarDecl::DeclarationOnly; +        Diag(VD->getLocation(), +             IsDecl ? diag::note_previous_decl : diag::note_defined_here) +            << VD; +      }        continue;      }      if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&          !getLangOpts().CPlusPlus && Type->isFloatingType()) {        Diag(ELoc, diag::err_omp_clause_floating_type_arg); -      bool IsDecl = -          VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; -      Diag(VD->getLocation(), -           IsDecl ? diag::note_previous_decl : diag::note_defined_here) -          << VD; +      if (!ASE && !OASE) { +        bool IsDecl = VD->isThisDeclarationADefinition(Context) == +                      VarDecl::DeclarationOnly; +        Diag(VD->getLocation(), +             IsDecl ? diag::note_previous_decl : diag::note_defined_here) +            << VD; +      }        continue;      }      // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced @@ -6028,7 +7355,8 @@ OMPClause *Sema::ActOnOpenMPReductionClause(      //  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 = DSAStack->getTopDSA(VD, false); +    DSAStackTy::DSAVarData DVar; +    DVar = DSAStack->getTopDSA(VD, false);      if (DVar.CKind == OMPC_reduction) {        Diag(ELoc, diag::err_omp_once_referenced)            << getOpenMPClauseName(OMPC_reduction); @@ -6059,9 +7387,27 @@ OMPClause *Sema::ActOnOpenMPReductionClause(          continue;        }      } +      Type = Type.getNonLValueExprType(Context).getUnqualifiedType(); -    auto *LHSVD = buildVarDecl(*this, ELoc, Type, ".reduction.lhs"); -    auto *RHSVD = buildVarDecl(*this, ELoc, Type, VD->getName()); +    auto *LHSVD = buildVarDecl(*this, ELoc, Type, ".reduction.lhs", +                               VD->hasAttrs() ? &VD->getAttrs() : nullptr); +    auto *RHSVD = buildVarDecl(*this, ELoc, Type, VD->getName(), +                               VD->hasAttrs() ? &VD->getAttrs() : nullptr); +    auto PrivateTy = Type; +    if (OASE) { +      // For array sections only: +      // Create pseudo array type for private copy. The size for this array will +      // be generated during codegen. +      // For array subscripts or single variables Private Ty is the same as Type +      // (type of the variable or single array element). +      PrivateTy = Context.getVariableArrayType( +          Type, new (Context) OpaqueValueExpr(SourceLocation(), +                                              Context.getSizeType(), VK_RValue), +          ArrayType::Normal, /*IndexTypeQuals=*/0, SourceRange()); +    } +    // Private copy. +    auto *PrivateVD = buildVarDecl(*this, ELoc, PrivateTy, VD->getName(), +                                   VD->hasAttrs() ? &VD->getAttrs() : nullptr);      // Add initializer for private variable.      Expr *Init = nullptr;      switch (BOK) { @@ -6170,21 +7516,27 @@ OMPClause *Sema::ActOnOpenMPReductionClause(      if (Init) {        AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false,                             /*TypeMayContainAuto=*/false); -    } else { +    } else        ActOnUninitializedDecl(RHSVD, /*TypeMayContainAuto=*/false); -    }      if (!RHSVD->hasInit()) {        Diag(ELoc, diag::err_omp_reduction_id_not_compatible) << Type                                                              << ReductionIdRange; -      bool IsDecl = -          VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; -      Diag(VD->getLocation(), -           IsDecl ? diag::note_previous_decl : diag::note_defined_here) -          << VD; +      if (VD) { +        bool IsDecl = VD->isThisDeclarationADefinition(Context) == +                      VarDecl::DeclarationOnly; +        Diag(VD->getLocation(), +             IsDecl ? diag::note_previous_decl : diag::note_defined_here) +            << VD; +      }        continue;      } +    // Store initializer for single element in private copy. Will be used during +    // codegen. +    PrivateVD->setInit(RHSVD->getInit()); +    PrivateVD->setInitStyle(RHSVD->getInitStyle());      auto *LHSDRE = buildDeclRefExpr(*this, LHSVD, Type, ELoc);      auto *RHSDRE = buildDeclRefExpr(*this, RHSVD, Type, ELoc); +    auto *PrivateDRE = buildDeclRefExpr(*this, PrivateVD, PrivateTy, ELoc);      ExprResult ReductionOp =          BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(), BOK,                     LHSDRE, RHSDRE); @@ -6201,15 +7553,14 @@ OMPClause *Sema::ActOnOpenMPReductionClause(              BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(),                         BO_Assign, LHSDRE, ConditionalOp);        } -      if (ReductionOp.isUsable()) { -        ReductionOp = ActOnFinishFullExpr(ReductionOp.get()); -      } +      ReductionOp = ActOnFinishFullExpr(ReductionOp.get());      }      if (ReductionOp.isInvalid())        continue;      DSAStack->addDSA(VD, DE, OMPC_reduction); -    Vars.push_back(DE); +    Vars.push_back(RefExpr); +    Privates.push_back(PrivateDRE);      LHSs.push_back(LHSDRE);      RHSs.push_back(RHSDRE);      ReductionOps.push_back(ReductionOp.get()); @@ -6220,22 +7571,28 @@ OMPClause *Sema::ActOnOpenMPReductionClause(    return OMPReductionClause::Create(        Context, StartLoc, LParenLoc, ColonLoc, EndLoc, Vars, -      ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId, LHSs, -      RHSs, ReductionOps); +      ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId, Privates, +      LHSs, RHSs, ReductionOps);  } -OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, -                                         SourceLocation StartLoc, -                                         SourceLocation LParenLoc, -                                         SourceLocation ColonLoc, -                                         SourceLocation EndLoc) { +OMPClause *Sema::ActOnOpenMPLinearClause( +    ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc, +    SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind, +    SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {    SmallVector<Expr *, 8> Vars; +  SmallVector<Expr *, 8> Privates;    SmallVector<Expr *, 8> Inits; +  if ((!LangOpts.CPlusPlus && LinKind != OMPC_LINEAR_val) || +      LinKind == OMPC_LINEAR_unknown) { +    Diag(LinLoc, diag::err_omp_wrong_linear_modifier) << LangOpts.CPlusPlus; +    LinKind = OMPC_LINEAR_val; +  }    for (auto &RefExpr : VarList) {      assert(RefExpr && "NULL expr in OpenMP linear clause.");      if (isa<DependentScopeDeclRefExpr>(RefExpr)) {        // It will be analyzed later.        Vars.push_back(RefExpr); +      Privates.push_back(nullptr);        Inits.push_back(nullptr);        continue;      } @@ -6278,6 +7635,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,      if (QType->isDependentType() || QType->isInstantiationDependentType()) {        // It will be analyzed later.        Vars.push_back(DE); +      Privates.push_back(nullptr);        Inits.push_back(nullptr);        continue;      } @@ -6287,16 +7645,13 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,                              diag::err_omp_linear_incomplete_type)) {        continue;      } -    if (QType->isReferenceType()) { -      Diag(ELoc, diag::err_omp_clause_ref_type_arg) -          << getOpenMPClauseName(OMPC_linear) << QType; -      bool IsDecl = -          VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; -      Diag(VD->getLocation(), -           IsDecl ? diag::note_previous_decl : diag::note_defined_here) -          << VD; +    if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) && +        !QType->isReferenceType()) { +      Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference) +          << QType << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);        continue;      } +    QType = QType.getNonReferenceType();      // A list item must not be const-qualified.      if (QType.isConstant(Context)) { @@ -6324,14 +7679,25 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,        continue;      } +    // Build private copy of original var. +    auto *Private = buildVarDecl(*this, ELoc, QType, VD->getName(), +                                 VD->hasAttrs() ? &VD->getAttrs() : nullptr); +    auto *PrivateRef = buildDeclRefExpr( +        *this, Private, DE->getType().getUnqualifiedType(), DE->getExprLoc());      // Build var to save initial value.      VarDecl *Init = buildVarDecl(*this, ELoc, QType, ".linear.start"); -    AddInitializerToDecl(Init, DefaultLvalueConversion(DE).get(), +    Expr *InitExpr; +    if (LinKind == OMPC_LINEAR_uval) +      InitExpr = VD->getInit(); +    else +      InitExpr = DE; +    AddInitializerToDecl(Init, DefaultLvalueConversion(InitExpr).get(),                           /*DirectInit*/ false, /*TypeMayContainAuto*/ false);      auto InitRef = buildDeclRefExpr(          *this, Init, DE->getType().getUnqualifiedType(), DE->getExprLoc());      DSAStack->addDSA(VD, DE, OMPC_linear);      Vars.push_back(DE); +    Privates.push_back(PrivateRef);      Inits.push_back(InitRef);    } @@ -6356,6 +7722,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,          buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc);      ExprResult CalcStep =          BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr); +    CalcStep = ActOnFinishFullExpr(CalcStep.get());      // Warn about zero linear step (it would be probably better specified as      // making corresponding variables 'const'). @@ -6371,8 +7738,9 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,      }    } -  return OMPLinearClause::Create(Context, StartLoc, LParenLoc, ColonLoc, EndLoc, -                                 Vars, Inits, StepExpr, CalcStepExpr); +  return OMPLinearClause::Create(Context, StartLoc, LParenLoc, LinKind, LinLoc, +                                 ColonLoc, EndLoc, Vars, Privates, Inits, +                                 StepExpr, CalcStepExpr);  }  static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, @@ -6391,27 +7759,35 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,      Step = cast<BinaryOperator>(CalcStep)->getLHS();    bool HasErrors = false;    auto CurInit = Clause.inits().begin(); +  auto CurPrivate = Clause.privates().begin(); +  auto LinKind = Clause.getModifier();    for (auto &RefExpr : Clause.varlists()) {      Expr *InitExpr = *CurInit;      // Build privatized reference to the current linear var.      auto DE = cast<DeclRefExpr>(RefExpr); -    auto PrivateRef = -        buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()), -                         DE->getType().getUnqualifiedType(), DE->getExprLoc(), -                         /*RefersToCapture=*/true); +    Expr *CapturedRef; +    if (LinKind == OMPC_LINEAR_uval) +      CapturedRef = cast<VarDecl>(DE->getDecl())->getInit(); +    else +      CapturedRef = +          buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()), +                           DE->getType().getUnqualifiedType(), DE->getExprLoc(), +                           /*RefersToCapture=*/true);      // Build update: Var = InitExpr + IV * Step      ExprResult Update = -        BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), PrivateRef, +        BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), *CurPrivate,                             InitExpr, IV, Step, /* Subtract */ false); -    Update = SemaRef.ActOnFinishFullExpr(Update.get()); +    Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getLocStart(), +                                         /*DiscardedValue=*/true);      // Build final: Var = InitExpr + NumIterations * Step      ExprResult Final = -        BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), PrivateRef, +        BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), CapturedRef,                             InitExpr, NumIterations, Step, /* Subtract */ false); -    Final = SemaRef.ActOnFinishFullExpr(Final.get()); +    Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getLocStart(), +                                        /*DiscardedValue=*/true);      if (!Update.isUsable() || !Final.isUsable()) {        Updates.push_back(nullptr);        Finals.push_back(nullptr); @@ -6420,7 +7796,7 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,        Updates.push_back(Update.get());        Finals.push_back(Final.get());      } -    ++CurInit; +    ++CurInit, ++CurPrivate;    }    Clause.setUpdates(Updates);    Clause.setFinals(Finals); @@ -6557,12 +7933,14 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,      //  copyin clause requires an accessible, unambiguous copy assignment      //  operator for the class type.      auto ElemType = Context.getBaseElementType(Type).getNonReferenceType(); -    auto *SrcVD = buildVarDecl(*this, DE->getLocStart(), -                               ElemType.getUnqualifiedType(), ".copyin.src"); +    auto *SrcVD = +        buildVarDecl(*this, DE->getLocStart(), ElemType.getUnqualifiedType(), +                     ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);      auto *PseudoSrcExpr = buildDeclRefExpr(          *this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());      auto *DstVD = -        buildVarDecl(*this, DE->getLocStart(), ElemType, ".copyin.dst"); +        buildVarDecl(*this, DE->getLocStart(), ElemType, ".copyin.dst", +                     VD->hasAttrs() ? &VD->getAttrs() : nullptr);      auto *PseudoDstExpr =          buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc());      // For arrays generate assignment operation for single element and replace @@ -6679,13 +8057,16 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,      //  A variable of class type (or array thereof) that appears in a      //  copyin clause requires an accessible, unambiguous copy assignment      //  operator for the class type. -    Type = Context.getBaseElementType(Type).getUnqualifiedType(); +    Type = Context.getBaseElementType(Type.getNonReferenceType()) +               .getUnqualifiedType();      auto *SrcVD = -        buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.src"); +        buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.src", +                     VD->hasAttrs() ? &VD->getAttrs() : nullptr);      auto *PseudoSrcExpr =          buildDeclRefExpr(*this, SrcVD, Type, DE->getExprLoc());      auto *DstVD = -        buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.dst"); +        buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.dst", +                     VD->hasAttrs() ? &VD->getAttrs() : nullptr);      auto *PseudoDstExpr =          buildDeclRefExpr(*this, DstVD, Type, DE->getExprLoc());      auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, @@ -6727,61 +8108,430 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,                                SourceLocation DepLoc, SourceLocation ColonLoc,                                ArrayRef<Expr *> VarList, SourceLocation StartLoc,                                SourceLocation LParenLoc, SourceLocation EndLoc) { -  if (DepKind == OMPC_DEPEND_unknown) { -    std::string Values; -    std::string Sep(", "); -    for (unsigned i = 0; i < OMPC_DEPEND_unknown; ++i) { -      Values += "'"; -      Values += getOpenMPSimpleClauseTypeName(OMPC_depend, i); -      Values += "'"; -      switch (i) { -      case OMPC_DEPEND_unknown - 2: -        Values += " or "; -        break; -      case OMPC_DEPEND_unknown - 1: -        break; -      default: -        Values += Sep; -        break; -      } -    } +  if (DSAStack->getCurrentDirective() == OMPD_ordered && +      DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) { +    Diag(DepLoc, diag::err_omp_unexpected_clause_value) +        << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend); +    return nullptr; +  } +  if (DSAStack->getCurrentDirective() != OMPD_ordered && +      (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source || +       DepKind == OMPC_DEPEND_sink)) { +    unsigned Except[] = {OMPC_DEPEND_source, OMPC_DEPEND_sink};      Diag(DepLoc, diag::err_omp_unexpected_clause_value) -        << Values << getOpenMPClauseName(OMPC_depend); +        << getListOfPossibleValues(OMPC_depend, /*First=*/0, +                                   /*Last=*/OMPC_DEPEND_unknown, Except) +        << getOpenMPClauseName(OMPC_depend);      return nullptr;    }    SmallVector<Expr *, 8> Vars; -  for (auto &RefExpr : VarList) { -    assert(RefExpr && "NULL expr in OpenMP shared clause."); -    if (isa<DependentScopeDeclRefExpr>(RefExpr)) { +  llvm::APSInt DepCounter(/*BitWidth=*/32); +  llvm::APSInt TotalDepCount(/*BitWidth=*/32); +  if (DepKind == OMPC_DEPEND_sink) { +    if (auto *OrderedCountExpr = DSAStack->getParentOrderedRegionParam()) { +      TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Context); +      TotalDepCount.setIsUnsigned(/*Val=*/true); +    } +  } +  if ((DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) || +      DSAStack->getParentOrderedRegionParam()) { +    for (auto &RefExpr : VarList) { +      assert(RefExpr && "NULL expr in OpenMP shared clause."); +      if (isa<DependentScopeDeclRefExpr>(RefExpr) || +          (DepKind == OMPC_DEPEND_sink && CurContext->isDependentContext())) { +        // It will be analyzed later. +        Vars.push_back(RefExpr); +        continue; +      } + +      SourceLocation ELoc = RefExpr->getExprLoc(); +      auto *SimpleExpr = RefExpr->IgnoreParenCasts(); +      if (DepKind == OMPC_DEPEND_sink) { +        if (DepCounter >= TotalDepCount) { +          Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr); +          continue; +        } +        ++DepCounter; +        // OpenMP  [2.13.9, Summary] +        // depend(dependence-type : vec), where dependence-type is: +        // 'sink' and where vec is the iteration vector, which has the form: +        //  x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn] +        // where n is the value specified by the ordered clause in the loop +        // directive, xi denotes the loop iteration variable of the i-th nested +        // loop associated with the loop directive, and di is a constant +        // non-negative integer. +        SimpleExpr = SimpleExpr->IgnoreImplicit(); +        auto *DE = dyn_cast<DeclRefExpr>(SimpleExpr); +        if (!DE) { +          OverloadedOperatorKind OOK = OO_None; +          SourceLocation OOLoc; +          Expr *LHS, *RHS; +          if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) { +            OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode()); +            OOLoc = BO->getOperatorLoc(); +            LHS = BO->getLHS()->IgnoreParenImpCasts(); +            RHS = BO->getRHS()->IgnoreParenImpCasts(); +          } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) { +            OOK = OCE->getOperator(); +            OOLoc = OCE->getOperatorLoc(); +            LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); +            RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); +          } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) { +            OOK = MCE->getMethodDecl() +                      ->getNameInfo() +                      .getName() +                      .getCXXOverloadedOperator(); +            OOLoc = MCE->getCallee()->getExprLoc(); +            LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts(); +            RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); +          } else { +            Diag(ELoc, diag::err_omp_depend_sink_wrong_expr); +            continue; +          } +          DE = dyn_cast<DeclRefExpr>(LHS); +          if (!DE) { +            Diag(LHS->getExprLoc(), +                 diag::err_omp_depend_sink_expected_loop_iteration) +                << DSAStack->getParentLoopControlVariable( +                    DepCounter.getZExtValue()); +            continue; +          } +          if (OOK != OO_Plus && OOK != OO_Minus) { +            Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus); +            continue; +          } +          ExprResult Res = VerifyPositiveIntegerConstantInClause( +              RHS, OMPC_depend, /*StrictlyPositive=*/false); +          if (Res.isInvalid()) +            continue; +        } +        auto *VD = dyn_cast<VarDecl>(DE->getDecl()); +        if (!CurContext->isDependentContext() && +            DSAStack->getParentOrderedRegionParam() && +            (!VD || DepCounter != DSAStack->isParentLoopControlVariable(VD))) { +          Diag(DE->getExprLoc(), +               diag::err_omp_depend_sink_expected_loop_iteration) +              << DSAStack->getParentLoopControlVariable( +                  DepCounter.getZExtValue()); +          continue; +        } +      } else { +        // OpenMP  [2.11.1.1, Restrictions, p.3] +        //  A variable that is part of another variable (such as a field of a +        //  structure) but is not an array element or an array section cannot +        //  appear  in a depend clause. +        auto *DE = dyn_cast<DeclRefExpr>(SimpleExpr); +        auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr); +        auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr); +        if (!RefExpr->IgnoreParenImpCasts()->isLValue() || +            (!ASE && !DE && !OASE) || (DE && !isa<VarDecl>(DE->getDecl())) || +            (ASE && !ASE->getBase()->getType()->isAnyPointerType() && +             !ASE->getBase()->getType()->isArrayType())) { +          Diag(ELoc, diag::err_omp_expected_var_name_or_array_item) +              << RefExpr->getSourceRange(); +          continue; +        } +      } + +      Vars.push_back(RefExpr->IgnoreParenImpCasts()); +    } + +    if (!CurContext->isDependentContext() && DepKind == OMPC_DEPEND_sink && +        TotalDepCount > VarList.size() && +        DSAStack->getParentOrderedRegionParam()) { +      Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration) +          << DSAStack->getParentLoopControlVariable(VarList.size() + 1); +    } +    if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink && +        Vars.empty()) +      return nullptr; +  } + +  return OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc, DepKind, +                                 DepLoc, ColonLoc, Vars); +} + +OMPClause *Sema::ActOnOpenMPDeviceClause(Expr *Device, SourceLocation StartLoc, +                                         SourceLocation LParenLoc, +                                         SourceLocation EndLoc) { +  Expr *ValExpr = Device; + +  // OpenMP [2.9.1, Restrictions] +  // The device expression must evaluate to a non-negative integer value. +  if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_device, +                                 /*StrictlyPositive=*/false)) +    return nullptr; + +  return new (Context) OMPDeviceClause(ValExpr, StartLoc, LParenLoc, EndLoc); +} + +static bool IsCXXRecordForMappable(Sema &SemaRef, SourceLocation Loc, +                                   DSAStackTy *Stack, CXXRecordDecl *RD) { +  if (!RD || RD->isInvalidDecl()) +    return true; + +  if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) +    if (auto *CTD = CTSD->getSpecializedTemplate()) +      RD = CTD->getTemplatedDecl(); +  auto QTy = SemaRef.Context.getRecordType(RD); +  if (RD->isDynamicClass()) { +    SemaRef.Diag(Loc, diag::err_omp_not_mappable_type) << QTy; +    SemaRef.Diag(RD->getLocation(), diag::note_omp_polymorphic_in_target); +    return false; +  } +  auto *DC = RD; +  bool IsCorrect = true; +  for (auto *I : DC->decls()) { +    if (I) { +      if (auto *MD = dyn_cast<CXXMethodDecl>(I)) { +        if (MD->isStatic()) { +          SemaRef.Diag(Loc, diag::err_omp_not_mappable_type) << QTy; +          SemaRef.Diag(MD->getLocation(), +                       diag::note_omp_static_member_in_target); +          IsCorrect = false; +        } +      } else if (auto *VD = dyn_cast<VarDecl>(I)) { +        if (VD->isStaticDataMember()) { +          SemaRef.Diag(Loc, diag::err_omp_not_mappable_type) << QTy; +          SemaRef.Diag(VD->getLocation(), +                       diag::note_omp_static_member_in_target); +          IsCorrect = false; +        } +      } +    } +  } + +  for (auto &I : RD->bases()) { +    if (!IsCXXRecordForMappable(SemaRef, I.getLocStart(), Stack, +                                I.getType()->getAsCXXRecordDecl())) +      IsCorrect = false; +  } +  return IsCorrect; +} + +static bool CheckTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef, +                              DSAStackTy *Stack, QualType QTy) { +  NamedDecl *ND; +  if (QTy->isIncompleteType(&ND)) { +    SemaRef.Diag(SL, diag::err_incomplete_type) << QTy << SR; +    return false; +  } else if (CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(ND)) { +    if (!RD->isInvalidDecl() && +        !IsCXXRecordForMappable(SemaRef, SL, Stack, RD)) +      return false; +  } +  return true; +} + +OMPClause *Sema::ActOnOpenMPMapClause( +    OpenMPMapClauseKind MapTypeModifier, OpenMPMapClauseKind MapType, +    SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList, +    SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { +  SmallVector<Expr *, 4> Vars; + +  for (auto &RE : VarList) { +    assert(RE && "Null expr in omp map"); +    if (isa<DependentScopeDeclRefExpr>(RE)) {        // It will be analyzed later. -      Vars.push_back(RefExpr); +      Vars.push_back(RE);        continue;      } +    SourceLocation ELoc = RE->getExprLoc(); -    SourceLocation ELoc = RefExpr->getExprLoc(); -    // OpenMP  [2.11.1.1, Restrictions, p.3] -    //  A variable that is part of another variable (such as a field of a +    // OpenMP [2.14.5, Restrictions] +    //  A variable that is part of another variable (such as field of a      //  structure) but is not an array element or an array section cannot appear -    //  in a depend clause. -    auto *SimpleExpr = RefExpr->IgnoreParenCasts(); -    DeclRefExpr *DE = dyn_cast<DeclRefExpr>(SimpleExpr); -    ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr); -    if (!RefExpr->IgnoreParenImpCasts()->isLValue() || (!ASE && !DE) || +    //  in a map clause. +    auto *VE = RE->IgnoreParenLValueCasts(); + +    if (VE->isValueDependent() || VE->isTypeDependent() || +        VE->isInstantiationDependent() || +        VE->containsUnexpandedParameterPack()) { +      // It will be analyzed later. +      Vars.push_back(RE); +      continue; +    } + +    auto *SimpleExpr = RE->IgnoreParenCasts(); +    auto *DE = dyn_cast<DeclRefExpr>(SimpleExpr); +    auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr); +    auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr); + +    if (!RE->IgnoreParenImpCasts()->isLValue() || +        (!OASE && !ASE && !DE) ||          (DE && !isa<VarDecl>(DE->getDecl())) ||          (ASE && !ASE->getBase()->getType()->isAnyPointerType() &&           !ASE->getBase()->getType()->isArrayType())) {        Diag(ELoc, diag::err_omp_expected_var_name_or_array_item) -          << RefExpr->getSourceRange(); +        << RE->getSourceRange();        continue;      } -    Vars.push_back(RefExpr->IgnoreParenImpCasts()); -  } +    Decl *D = nullptr; +    if (DE) { +      D = DE->getDecl(); +    } else if (ASE) { +      auto *B = ASE->getBase()->IgnoreParenCasts(); +      D = dyn_cast<DeclRefExpr>(B)->getDecl(); +    } else if (OASE) { +      auto *B = OASE->getBase(); +      D = dyn_cast<DeclRefExpr>(B)->getDecl(); +    } +    assert(D && "Null decl on map clause."); +    auto *VD = cast<VarDecl>(D); + +    // OpenMP [2.14.5, Restrictions, p.8] +    // threadprivate variables cannot appear in a map clause. +    if (DSAStack->isThreadPrivate(VD)) { +      auto DVar = DSAStack->getTopDSA(VD, false); +      Diag(ELoc, diag::err_omp_threadprivate_in_map); +      ReportOriginalDSA(*this, DSAStack, VD, DVar); +      continue; +    } + +    // OpenMP [2.14.5, Restrictions, p.2] +    //  At most one list item can be an array item derived from a given variable +    //  in map clauses of the same construct. +    // OpenMP [2.14.5, Restrictions, p.3] +    //  List items of map clauses in the same construct must not share original +    //  storage. +    // OpenMP [2.14.5, Restrictions, C/C++, p.2] +    //  A variable for which the type is pointer, reference to array, or +    //  reference to pointer and an array section derived from that variable +    //  must not appear as list items of map clauses of the same construct. +    DSAStackTy::MapInfo MI = DSAStack->IsMappedInCurrentRegion(VD); +    if (MI.RefExpr) { +      Diag(ELoc, diag::err_omp_map_shared_storage) << ELoc; +      Diag(MI.RefExpr->getExprLoc(), diag::note_used_here) +          << MI.RefExpr->getSourceRange(); +      continue; +    } + +    // OpenMP [2.14.5, Restrictions, C/C++, p.3,4] +    //  A variable for which the type is pointer, reference to array, or +    //  reference to pointer must not appear as a list item if the enclosing +    //  device data environment already contains an array section derived from +    //  that variable. +    //  An array section derived from a variable for which the type is pointer, +    //  reference to array, or reference to pointer must not appear as a list +    //  item if the enclosing device data environment already contains that +    //  variable. +    QualType Type = VD->getType(); +    MI = DSAStack->getMapInfoForVar(VD); +    if (MI.RefExpr && (isa<DeclRefExpr>(MI.RefExpr->IgnoreParenLValueCasts()) != +                       isa<DeclRefExpr>(VE)) && +        (Type->isPointerType() || Type->isReferenceType())) { +      Diag(ELoc, diag::err_omp_map_shared_storage) << ELoc; +      Diag(MI.RefExpr->getExprLoc(), diag::note_used_here) +          << MI.RefExpr->getSourceRange(); +      continue; +    } +    // OpenMP [2.14.5, Restrictions, C/C++, p.7] +    //  A list item must have a mappable type. +    if (!CheckTypeMappable(VE->getExprLoc(), VE->getSourceRange(), *this, +                           DSAStack, Type)) +      continue; + +    Vars.push_back(RE); +    MI.RefExpr = RE; +    DSAStack->addMapInfoForVar(VD, MI); +  }    if (Vars.empty())      return nullptr; -  return OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc, DepKind, -                                 DepLoc, ColonLoc, Vars); +  return OMPMapClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars, +                              MapTypeModifier, MapType, MapLoc); +} + +OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams,  +                                           SourceLocation StartLoc, +                                           SourceLocation LParenLoc, +                                           SourceLocation EndLoc) { +  Expr *ValExpr = NumTeams; + +  // OpenMP [teams Constrcut, Restrictions] +  // The num_teams expression must evaluate to a positive integer value. +  if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_num_teams, +                                 /*StrictlyPositive=*/true)) +    return nullptr; + +  return new (Context) OMPNumTeamsClause(ValExpr, StartLoc, LParenLoc, EndLoc); +} + +OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit, +                                              SourceLocation StartLoc, +                                              SourceLocation LParenLoc, +                                              SourceLocation EndLoc) { +  Expr *ValExpr = ThreadLimit; + +  // OpenMP [teams Constrcut, Restrictions] +  // The thread_limit expression must evaluate to a positive integer value. +  if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_thread_limit, +                                 /*StrictlyPositive=*/true)) +    return nullptr; + +  return new (Context) OMPThreadLimitClause(ValExpr, StartLoc, LParenLoc, +                                            EndLoc); +} + +OMPClause *Sema::ActOnOpenMPPriorityClause(Expr *Priority, +                                           SourceLocation StartLoc, +                                           SourceLocation LParenLoc, +                                           SourceLocation EndLoc) { +  Expr *ValExpr = Priority; + +  // OpenMP [2.9.1, task Constrcut] +  // The priority-value is a non-negative numerical scalar expression. +  if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_priority, +                                 /*StrictlyPositive=*/false)) +    return nullptr; + +  return new (Context) OMPPriorityClause(ValExpr, StartLoc, LParenLoc, EndLoc); +} + +OMPClause *Sema::ActOnOpenMPGrainsizeClause(Expr *Grainsize, +                                            SourceLocation StartLoc, +                                            SourceLocation LParenLoc, +                                            SourceLocation EndLoc) { +  Expr *ValExpr = Grainsize; + +  // OpenMP [2.9.2, taskloop Constrcut] +  // The parameter of the grainsize clause must be a positive integer +  // expression. +  if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_grainsize, +                                 /*StrictlyPositive=*/true)) +    return nullptr; + +  return new (Context) OMPGrainsizeClause(ValExpr, StartLoc, LParenLoc, EndLoc); +} + +OMPClause *Sema::ActOnOpenMPNumTasksClause(Expr *NumTasks, +                                           SourceLocation StartLoc, +                                           SourceLocation LParenLoc, +                                           SourceLocation EndLoc) { +  Expr *ValExpr = NumTasks; + +  // OpenMP [2.9.2, taskloop Constrcut] +  // The parameter of the num_tasks clause must be a positive integer +  // expression. +  if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_num_tasks, +                                 /*StrictlyPositive=*/true)) +    return nullptr; + +  return new (Context) OMPNumTasksClause(ValExpr, StartLoc, LParenLoc, EndLoc); +} + +OMPClause *Sema::ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc, +                                       SourceLocation LParenLoc, +                                       SourceLocation EndLoc) { +  // OpenMP [2.13.2, critical construct, Description] +  // ... where hint-expression is an integer constant expression that evaluates +  // to a valid lock hint. +  ExprResult HintExpr = VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint); +  if (HintExpr.isInvalid()) +    return nullptr; +  return new (Context) +      OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);  }  | 
