1276479Sdim//===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ---------===// 2249261Sdim// 3249261Sdim// The LLVM Compiler Infrastructure 4249261Sdim// 5249261Sdim// This file is distributed under the University of Illinois Open Source 6249261Sdim// License. See LICENSE.TXT for details. 7249261Sdim// 8249261Sdim//===----------------------------------------------------------------------===// 9249261Sdim/// \file 10249261Sdim/// \brief This file implements semantic analysis for OpenMP directives and 11261991Sdim/// clauses. 12249261Sdim/// 13249261Sdim//===----------------------------------------------------------------------===// 14249261Sdim 15288943Sdim#include "TreeTransform.h" 16276479Sdim#include "clang/AST/ASTContext.h" 17280031Sdim#include "clang/AST/ASTMutationListener.h" 18249261Sdim#include "clang/AST/Decl.h" 19261991Sdim#include "clang/AST/DeclCXX.h" 20249261Sdim#include "clang/AST/DeclOpenMP.h" 21261991Sdim#include "clang/AST/StmtCXX.h" 22261991Sdim#include "clang/AST/StmtOpenMP.h" 23261991Sdim#include "clang/AST/StmtVisitor.h" 24276479Sdim#include "clang/Basic/OpenMPKinds.h" 25288943Sdim#include "clang/Basic/TargetInfo.h" 26249261Sdim#include "clang/Lex/Preprocessor.h" 27261991Sdim#include "clang/Sema/Initialization.h" 28249261Sdim#include "clang/Sema/Lookup.h" 29261991Sdim#include "clang/Sema/Scope.h" 30261991Sdim#include "clang/Sema/ScopeInfo.h" 31276479Sdim#include "clang/Sema/SemaInternal.h" 32249261Sdimusing namespace clang; 33249261Sdim 34261991Sdim//===----------------------------------------------------------------------===// 35261991Sdim// Stack of data-sharing attributes for variables 36261991Sdim//===----------------------------------------------------------------------===// 37261991Sdim 38249261Sdimnamespace { 39261991Sdim/// \brief Default data sharing attributes, which can be applied to directive. 40261991Sdimenum DefaultDataSharingAttributes { 41276479Sdim DSA_unspecified = 0, /// \brief Data sharing attribute not specified. 42276479Sdim DSA_none = 1 << 0, /// \brief Default data sharing attribute 'none'. 43276479Sdim DSA_shared = 1 << 1 /// \brief Default data sharing attribute 'shared'. 44261991Sdim}; 45249261Sdim 46276479Sdimtemplate <class T> struct MatchesAny { 47276479Sdim explicit MatchesAny(ArrayRef<T> Arr) : Arr(std::move(Arr)) {} 48276479Sdim bool operator()(T Kind) { 49276479Sdim for (auto KindEl : Arr) 50276479Sdim if (KindEl == Kind) 51276479Sdim return true; 52276479Sdim return false; 53276479Sdim } 54276479Sdim 55276479Sdimprivate: 56276479Sdim ArrayRef<T> Arr; 57276479Sdim}; 58276479Sdimstruct MatchesAlways { 59276479Sdim MatchesAlways() {} 60276479Sdim template <class T> bool operator()(T) { return true; } 61276479Sdim}; 62276479Sdim 63276479Sdimtypedef MatchesAny<OpenMPClauseKind> MatchesAnyClause; 64276479Sdimtypedef MatchesAny<OpenMPDirectiveKind> MatchesAnyDirective; 65276479Sdim 66261991Sdim/// \brief Stack for tracking declarations used in OpenMP directives and 67261991Sdim/// clauses and their data-sharing attributes. 68261991Sdimclass DSAStackTy { 69261991Sdimpublic: 70261991Sdim struct DSAVarData { 71261991Sdim OpenMPDirectiveKind DKind; 72261991Sdim OpenMPClauseKind CKind; 73261991Sdim DeclRefExpr *RefExpr; 74276479Sdim SourceLocation ImplicitDSALoc; 75276479Sdim DSAVarData() 76276479Sdim : DKind(OMPD_unknown), CKind(OMPC_unknown), RefExpr(nullptr), 77276479Sdim ImplicitDSALoc() {} 78261991Sdim }; 79276479Sdim 80296417Sdimpublic: 81296417Sdim struct MapInfo { 82296417Sdim Expr *RefExpr; 83296417Sdim }; 84296417Sdim 85261991Sdimprivate: 86261991Sdim struct DSAInfo { 87261991Sdim OpenMPClauseKind Attributes; 88261991Sdim DeclRefExpr *RefExpr; 89261991Sdim }; 90261991Sdim typedef llvm::SmallDenseMap<VarDecl *, DSAInfo, 64> DeclSAMapTy; 91276479Sdim typedef llvm::SmallDenseMap<VarDecl *, DeclRefExpr *, 64> AlignedMapTy; 92296417Sdim typedef llvm::DenseMap<VarDecl *, unsigned> LoopControlVariablesMapTy; 93296417Sdim typedef llvm::SmallDenseMap<VarDecl *, MapInfo, 64> MappedDeclsTy; 94296417Sdim typedef llvm::StringMap<std::pair<OMPCriticalDirective *, llvm::APSInt>> 95296417Sdim CriticalsWithHintsTy; 96261991Sdim 97261991Sdim struct SharingMapTy { 98261991Sdim DeclSAMapTy SharingMap; 99276479Sdim AlignedMapTy AlignedMap; 100296417Sdim MappedDeclsTy MappedDecls; 101296417Sdim LoopControlVariablesMapTy LCVMap; 102261991Sdim DefaultDataSharingAttributes DefaultAttr; 103276479Sdim SourceLocation DefaultAttrLoc; 104261991Sdim OpenMPDirectiveKind Directive; 105261991Sdim DeclarationNameInfo DirectiveName; 106261991Sdim Scope *CurScope; 107276479Sdim SourceLocation ConstructLoc; 108296417Sdim /// \brief first argument (Expr *) contains optional argument of the 109296417Sdim /// 'ordered' clause, the second one is true if the regions has 'ordered' 110296417Sdim /// clause, false otherwise. 111296417Sdim llvm::PointerIntPair<Expr *, 1, bool> OrderedRegion; 112288943Sdim bool NowaitRegion; 113296417Sdim bool CancelRegion; 114296417Sdim unsigned AssociatedLoops; 115280031Sdim SourceLocation InnerTeamsRegionLoc; 116276479Sdim SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name, 117276479Sdim Scope *CurScope, SourceLocation Loc) 118296417Sdim : SharingMap(), AlignedMap(), LCVMap(), DefaultAttr(DSA_unspecified), 119276479Sdim Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope), 120296417Sdim ConstructLoc(Loc), OrderedRegion(), NowaitRegion(false), 121296417Sdim CancelRegion(false), AssociatedLoops(1), InnerTeamsRegionLoc() {} 122261991Sdim SharingMapTy() 123296417Sdim : SharingMap(), AlignedMap(), LCVMap(), DefaultAttr(DSA_unspecified), 124276479Sdim Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr), 125296417Sdim ConstructLoc(), OrderedRegion(), NowaitRegion(false), 126296417Sdim CancelRegion(false), AssociatedLoops(1), InnerTeamsRegionLoc() {} 127261991Sdim }; 128261991Sdim 129261991Sdim typedef SmallVector<SharingMapTy, 64> StackTy; 130261991Sdim 131261991Sdim /// \brief Stack of used declaration and their data-sharing attributes. 132261991Sdim StackTy Stack; 133288943Sdim /// \brief true, if check for DSA must be from parent directive, false, if 134288943Sdim /// from current directive. 135288943Sdim OpenMPClauseKind ClauseKindMode; 136276479Sdim Sema &SemaRef; 137288943Sdim bool ForceCapturing; 138296417Sdim CriticalsWithHintsTy Criticals; 139261991Sdim 140261991Sdim typedef SmallVector<SharingMapTy, 8>::reverse_iterator reverse_iterator; 141261991Sdim 142261991Sdim DSAVarData getDSA(StackTy::reverse_iterator Iter, VarDecl *D); 143276479Sdim 144276479Sdim /// \brief Checks if the variable is a local for OpenMP region. 145276479Sdim bool isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter); 146276479Sdim 147261991Sdimpublic: 148288943Sdim explicit DSAStackTy(Sema &S) 149288943Sdim : Stack(1), ClauseKindMode(OMPC_unknown), SemaRef(S), 150288943Sdim ForceCapturing(false) {} 151261991Sdim 152288943Sdim bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; } 153288943Sdim void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; } 154288943Sdim 155288943Sdim bool isForceVarCapturing() const { return ForceCapturing; } 156288943Sdim void setForceVarCapturing(bool V) { ForceCapturing = V; } 157288943Sdim 158261991Sdim void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName, 159276479Sdim Scope *CurScope, SourceLocation Loc) { 160276479Sdim Stack.push_back(SharingMapTy(DKind, DirName, CurScope, Loc)); 161276479Sdim Stack.back().DefaultAttrLoc = Loc; 162261991Sdim } 163261991Sdim 164261991Sdim void pop() { 165261991Sdim assert(Stack.size() > 1 && "Data-sharing attributes stack is empty!"); 166261991Sdim Stack.pop_back(); 167261991Sdim } 168261991Sdim 169296417Sdim void addCriticalWithHint(OMPCriticalDirective *D, llvm::APSInt Hint) { 170296417Sdim Criticals[D->getDirectiveName().getAsString()] = std::make_pair(D, Hint); 171296417Sdim } 172296417Sdim const std::pair<OMPCriticalDirective *, llvm::APSInt> 173296417Sdim getCriticalWithHint(const DeclarationNameInfo &Name) const { 174296417Sdim auto I = Criticals.find(Name.getAsString()); 175296417Sdim if (I != Criticals.end()) 176296417Sdim return I->second; 177296417Sdim return std::make_pair(nullptr, llvm::APSInt()); 178296417Sdim } 179276479Sdim /// \brief If 'aligned' declaration for given variable \a D was not seen yet, 180276479Sdim /// add it and return NULL; otherwise return previous occurrence's expression 181276479Sdim /// for diagnostics. 182276479Sdim DeclRefExpr *addUniqueAligned(VarDecl *D, DeclRefExpr *NewDE); 183276479Sdim 184288943Sdim /// \brief Register specified variable as loop control variable. 185288943Sdim void addLoopControlVariable(VarDecl *D); 186288943Sdim /// \brief Check if the specified variable is a loop control variable for 187288943Sdim /// current region. 188296417Sdim /// \return The index of the loop control variable in the list of associated 189296417Sdim /// for-loops (from outer to inner). 190296417Sdim unsigned isLoopControlVariable(VarDecl *D); 191296417Sdim /// \brief Check if the specified variable is a loop control variable for 192296417Sdim /// parent region. 193296417Sdim /// \return The index of the loop control variable in the list of associated 194296417Sdim /// for-loops (from outer to inner). 195296417Sdim unsigned isParentLoopControlVariable(VarDecl *D); 196296417Sdim /// \brief Get the loop control variable for the I-th loop (or nullptr) in 197296417Sdim /// parent directive. 198296417Sdim VarDecl *getParentLoopControlVariable(unsigned I); 199288943Sdim 200261991Sdim /// \brief Adds explicit data sharing attribute to the specified declaration. 201261991Sdim void addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A); 202261991Sdim 203261991Sdim /// \brief Returns data sharing attributes from top of the stack for the 204261991Sdim /// specified declaration. 205276479Sdim DSAVarData getTopDSA(VarDecl *D, bool FromParent); 206261991Sdim /// \brief Returns data-sharing attributes for the specified declaration. 207276479Sdim DSAVarData getImplicitDSA(VarDecl *D, bool FromParent); 208276479Sdim /// \brief Checks if the specified variables has data-sharing attributes which 209276479Sdim /// match specified \a CPred predicate in any directive which matches \a DPred 210276479Sdim /// predicate. 211276479Sdim template <class ClausesPredicate, class DirectivesPredicate> 212276479Sdim DSAVarData hasDSA(VarDecl *D, ClausesPredicate CPred, 213276479Sdim DirectivesPredicate DPred, bool FromParent); 214276479Sdim /// \brief Checks if the specified variables has data-sharing attributes which 215276479Sdim /// match specified \a CPred predicate in any innermost directive which 216276479Sdim /// matches \a DPred predicate. 217276479Sdim template <class ClausesPredicate, class DirectivesPredicate> 218276479Sdim DSAVarData hasInnermostDSA(VarDecl *D, ClausesPredicate CPred, 219276479Sdim DirectivesPredicate DPred, 220276479Sdim bool FromParent); 221288943Sdim /// \brief Checks if the specified variables has explicit data-sharing 222288943Sdim /// attributes which match specified \a CPred predicate at the specified 223288943Sdim /// OpenMP region. 224288943Sdim bool hasExplicitDSA(VarDecl *D, 225288943Sdim const llvm::function_ref<bool(OpenMPClauseKind)> &CPred, 226288943Sdim unsigned Level); 227296417Sdim 228296417Sdim /// \brief Returns true if the directive at level \Level matches in the 229296417Sdim /// specified \a DPred predicate. 230296417Sdim bool hasExplicitDirective( 231296417Sdim const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred, 232296417Sdim unsigned Level); 233296417Sdim 234276479Sdim /// \brief Finds a directive which matches specified \a DPred predicate. 235276479Sdim template <class NamedDirectivesPredicate> 236276479Sdim bool hasDirective(NamedDirectivesPredicate DPred, bool FromParent); 237261991Sdim 238261991Sdim /// \brief Returns currently analyzed directive. 239261991Sdim OpenMPDirectiveKind getCurrentDirective() const { 240261991Sdim return Stack.back().Directive; 241261991Sdim } 242276479Sdim /// \brief Returns parent directive. 243276479Sdim OpenMPDirectiveKind getParentDirective() const { 244276479Sdim if (Stack.size() > 2) 245276479Sdim return Stack[Stack.size() - 2].Directive; 246276479Sdim return OMPD_unknown; 247276479Sdim } 248296417Sdim /// \brief Return the directive associated with the provided scope. 249296417Sdim OpenMPDirectiveKind getDirectiveForScope(const Scope *S) const; 250261991Sdim 251261991Sdim /// \brief Set default data sharing attribute to none. 252276479Sdim void setDefaultDSANone(SourceLocation Loc) { 253276479Sdim Stack.back().DefaultAttr = DSA_none; 254276479Sdim Stack.back().DefaultAttrLoc = Loc; 255276479Sdim } 256261991Sdim /// \brief Set default data sharing attribute to shared. 257276479Sdim void setDefaultDSAShared(SourceLocation Loc) { 258276479Sdim Stack.back().DefaultAttr = DSA_shared; 259276479Sdim Stack.back().DefaultAttrLoc = Loc; 260276479Sdim } 261261991Sdim 262261991Sdim DefaultDataSharingAttributes getDefaultDSA() const { 263261991Sdim return Stack.back().DefaultAttr; 264261991Sdim } 265276479Sdim SourceLocation getDefaultDSALocation() const { 266276479Sdim return Stack.back().DefaultAttrLoc; 267276479Sdim } 268261991Sdim 269276479Sdim /// \brief Checks if the specified variable is a threadprivate. 270276479Sdim bool isThreadPrivate(VarDecl *D) { 271276479Sdim DSAVarData DVar = getTopDSA(D, false); 272276479Sdim return isOpenMPThreadPrivate(DVar.CKind); 273276479Sdim } 274276479Sdim 275280031Sdim /// \brief Marks current region as ordered (it has an 'ordered' clause). 276296417Sdim void setOrderedRegion(bool IsOrdered, Expr *Param) { 277296417Sdim Stack.back().OrderedRegion.setInt(IsOrdered); 278296417Sdim Stack.back().OrderedRegion.setPointer(Param); 279280031Sdim } 280280031Sdim /// \brief Returns true, if parent region is ordered (has associated 281280031Sdim /// 'ordered' clause), false - otherwise. 282280031Sdim bool isParentOrderedRegion() const { 283280031Sdim if (Stack.size() > 2) 284296417Sdim return Stack[Stack.size() - 2].OrderedRegion.getInt(); 285280031Sdim return false; 286280031Sdim } 287296417Sdim /// \brief Returns optional parameter for the ordered region. 288296417Sdim Expr *getParentOrderedRegionParam() const { 289296417Sdim if (Stack.size() > 2) 290296417Sdim return Stack[Stack.size() - 2].OrderedRegion.getPointer(); 291296417Sdim return nullptr; 292296417Sdim } 293288943Sdim /// \brief Marks current region as nowait (it has a 'nowait' clause). 294288943Sdim void setNowaitRegion(bool IsNowait = true) { 295288943Sdim Stack.back().NowaitRegion = IsNowait; 296288943Sdim } 297288943Sdim /// \brief Returns true, if parent region is nowait (has associated 298288943Sdim /// 'nowait' clause), false - otherwise. 299288943Sdim bool isParentNowaitRegion() const { 300288943Sdim if (Stack.size() > 2) 301288943Sdim return Stack[Stack.size() - 2].NowaitRegion; 302288943Sdim return false; 303288943Sdim } 304296417Sdim /// \brief Marks parent region as cancel region. 305296417Sdim void setParentCancelRegion(bool Cancel = true) { 306296417Sdim if (Stack.size() > 2) 307296417Sdim Stack[Stack.size() - 2].CancelRegion = 308296417Sdim Stack[Stack.size() - 2].CancelRegion || Cancel; 309296417Sdim } 310296417Sdim /// \brief Return true if current region has inner cancel construct. 311296417Sdim bool isCancelRegion() const { 312296417Sdim return Stack.back().CancelRegion; 313296417Sdim } 314280031Sdim 315288943Sdim /// \brief Set collapse value for the region. 316296417Sdim void setAssociatedLoops(unsigned Val) { Stack.back().AssociatedLoops = Val; } 317288943Sdim /// \brief Return collapse value for region. 318296417Sdim unsigned getAssociatedLoops() const { return Stack.back().AssociatedLoops; } 319288943Sdim 320280031Sdim /// \brief Marks current target region as one with closely nested teams 321280031Sdim /// region. 322280031Sdim void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) { 323280031Sdim if (Stack.size() > 2) 324280031Sdim Stack[Stack.size() - 2].InnerTeamsRegionLoc = TeamsRegionLoc; 325280031Sdim } 326280031Sdim /// \brief Returns true, if current region has closely nested teams region. 327280031Sdim bool hasInnerTeamsRegion() const { 328280031Sdim return getInnerTeamsRegionLoc().isValid(); 329280031Sdim } 330280031Sdim /// \brief Returns location of the nested teams region (if any). 331280031Sdim SourceLocation getInnerTeamsRegionLoc() const { 332280031Sdim if (Stack.size() > 1) 333280031Sdim return Stack.back().InnerTeamsRegionLoc; 334280031Sdim return SourceLocation(); 335280031Sdim } 336280031Sdim 337276479Sdim Scope *getCurScope() const { return Stack.back().CurScope; } 338261991Sdim Scope *getCurScope() { return Stack.back().CurScope; } 339276479Sdim SourceLocation getConstructLoc() { return Stack.back().ConstructLoc; } 340296417Sdim 341296417Sdim MapInfo getMapInfoForVar(VarDecl *VD) { 342296417Sdim MapInfo VarMI = {0}; 343296417Sdim for (auto Cnt = Stack.size() - 1; Cnt > 0; --Cnt) { 344296417Sdim if (Stack[Cnt].MappedDecls.count(VD)) { 345296417Sdim VarMI = Stack[Cnt].MappedDecls[VD]; 346296417Sdim break; 347296417Sdim } 348296417Sdim } 349296417Sdim return VarMI; 350296417Sdim } 351296417Sdim 352296417Sdim void addMapInfoForVar(VarDecl *VD, MapInfo MI) { 353296417Sdim if (Stack.size() > 1) { 354296417Sdim Stack.back().MappedDecls[VD] = MI; 355296417Sdim } 356296417Sdim } 357296417Sdim 358296417Sdim MapInfo IsMappedInCurrentRegion(VarDecl *VD) { 359296417Sdim assert(Stack.size() > 1 && "Target level is 0"); 360296417Sdim MapInfo VarMI = {0}; 361296417Sdim if (Stack.size() > 1 && Stack.back().MappedDecls.count(VD)) { 362296417Sdim VarMI = Stack.back().MappedDecls[VD]; 363296417Sdim } 364296417Sdim return VarMI; 365296417Sdim } 366261991Sdim}; 367276479Sdimbool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) { 368276479Sdim return isOpenMPParallelDirective(DKind) || DKind == OMPD_task || 369296417Sdim isOpenMPTeamsDirective(DKind) || DKind == OMPD_unknown || 370296417Sdim isOpenMPTaskLoopDirective(DKind); 371276479Sdim} 372276479Sdim} // namespace 373261991Sdim 374261991SdimDSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter, 375261991Sdim VarDecl *D) { 376288943Sdim D = D->getCanonicalDecl(); 377261991Sdim DSAVarData DVar; 378276479Sdim if (Iter == std::prev(Stack.rend())) { 379261991Sdim // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 380261991Sdim // in a region but not in construct] 381261991Sdim // File-scope or namespace-scope variables referenced in called routines 382261991Sdim // in the region are shared unless they appear in a threadprivate 383261991Sdim // directive. 384280031Sdim if (!D->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(D)) 385261991Sdim DVar.CKind = OMPC_shared; 386261991Sdim 387261991Sdim // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced 388261991Sdim // in a region but not in construct] 389261991Sdim // Variables with static storage duration that are declared in called 390261991Sdim // routines in the region are shared. 391261991Sdim if (D->hasGlobalStorage()) 392261991Sdim DVar.CKind = OMPC_shared; 393261991Sdim 394261991Sdim return DVar; 395261991Sdim } 396276479Sdim 397261991Sdim DVar.DKind = Iter->Directive; 398276479Sdim // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 399276479Sdim // in a Construct, C/C++, predetermined, p.1] 400276479Sdim // Variables with automatic storage duration that are declared in a scope 401276479Sdim // inside the construct are private. 402276479Sdim if (isOpenMPLocal(D, Iter) && D->isLocalVarDecl() && 403276479Sdim (D->getStorageClass() == SC_Auto || D->getStorageClass() == SC_None)) { 404276479Sdim DVar.CKind = OMPC_private; 405276479Sdim return DVar; 406276479Sdim } 407276479Sdim 408261991Sdim // Explicitly specified attributes and local variables with predetermined 409261991Sdim // attributes. 410261991Sdim if (Iter->SharingMap.count(D)) { 411261991Sdim DVar.RefExpr = Iter->SharingMap[D].RefExpr; 412261991Sdim DVar.CKind = Iter->SharingMap[D].Attributes; 413276479Sdim DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; 414261991Sdim return DVar; 415261991Sdim } 416261991Sdim 417261991Sdim // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 418261991Sdim // in a Construct, C/C++, implicitly determined, p.1] 419261991Sdim // In a parallel or task construct, the data-sharing attributes of these 420261991Sdim // variables are determined by the default clause, if present. 421261991Sdim switch (Iter->DefaultAttr) { 422261991Sdim case DSA_shared: 423261991Sdim DVar.CKind = OMPC_shared; 424276479Sdim DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; 425261991Sdim return DVar; 426261991Sdim case DSA_none: 427261991Sdim return DVar; 428261991Sdim case DSA_unspecified: 429261991Sdim // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 430261991Sdim // in a Construct, implicitly determined, p.2] 431261991Sdim // In a parallel construct, if no default clause is present, these 432261991Sdim // variables are shared. 433276479Sdim DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; 434280031Sdim if (isOpenMPParallelDirective(DVar.DKind) || 435280031Sdim isOpenMPTeamsDirective(DVar.DKind)) { 436261991Sdim DVar.CKind = OMPC_shared; 437261991Sdim return DVar; 438261991Sdim } 439261991Sdim 440261991Sdim // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 441261991Sdim // in a Construct, implicitly determined, p.4] 442261991Sdim // In a task construct, if no default clause is present, a variable that in 443261991Sdim // the enclosing context is determined to be shared by all implicit tasks 444261991Sdim // bound to the current team is shared. 445261991Sdim if (DVar.DKind == OMPD_task) { 446261991Sdim DSAVarData DVarTemp; 447288943Sdim for (StackTy::reverse_iterator I = std::next(Iter), EE = Stack.rend(); 448261991Sdim I != EE; ++I) { 449276479Sdim // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables 450276479Sdim // Referenced 451261991Sdim // in a Construct, implicitly determined, p.6] 452261991Sdim // In a task construct, if no default clause is present, a variable 453261991Sdim // whose data-sharing attribute is not determined by the rules above is 454261991Sdim // firstprivate. 455261991Sdim DVarTemp = getDSA(I, D); 456261991Sdim if (DVarTemp.CKind != OMPC_shared) { 457276479Sdim DVar.RefExpr = nullptr; 458261991Sdim DVar.DKind = OMPD_task; 459261991Sdim DVar.CKind = OMPC_firstprivate; 460261991Sdim return DVar; 461249261Sdim } 462276479Sdim if (isParallelOrTaskRegion(I->Directive)) 463276479Sdim break; 464249261Sdim } 465261991Sdim DVar.DKind = OMPD_task; 466261991Sdim DVar.CKind = 467276479Sdim (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared; 468261991Sdim return DVar; 469261991Sdim } 470261991Sdim } 471261991Sdim // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 472261991Sdim // in a Construct, implicitly determined, p.3] 473261991Sdim // For constructs other than task, if no default clause is present, these 474261991Sdim // variables inherit their data-sharing attributes from the enclosing 475261991Sdim // context. 476276479Sdim return getDSA(std::next(Iter), D); 477249261Sdim} 478261991Sdim 479276479SdimDeclRefExpr *DSAStackTy::addUniqueAligned(VarDecl *D, DeclRefExpr *NewDE) { 480276479Sdim assert(Stack.size() > 1 && "Data sharing attributes stack is empty"); 481288943Sdim D = D->getCanonicalDecl(); 482276479Sdim auto It = Stack.back().AlignedMap.find(D); 483276479Sdim if (It == Stack.back().AlignedMap.end()) { 484276479Sdim assert(NewDE && "Unexpected nullptr expr to be added into aligned map"); 485276479Sdim Stack.back().AlignedMap[D] = NewDE; 486276479Sdim return nullptr; 487276479Sdim } else { 488276479Sdim assert(It->second && "Unexpected nullptr expr in the aligned map"); 489276479Sdim return It->second; 490276479Sdim } 491276479Sdim return nullptr; 492276479Sdim} 493276479Sdim 494288943Sdimvoid DSAStackTy::addLoopControlVariable(VarDecl *D) { 495288943Sdim assert(Stack.size() > 1 && "Data-sharing attributes stack is empty"); 496288943Sdim D = D->getCanonicalDecl(); 497296417Sdim Stack.back().LCVMap.insert(std::make_pair(D, Stack.back().LCVMap.size() + 1)); 498288943Sdim} 499288943Sdim 500296417Sdimunsigned DSAStackTy::isLoopControlVariable(VarDecl *D) { 501288943Sdim assert(Stack.size() > 1 && "Data-sharing attributes stack is empty"); 502288943Sdim D = D->getCanonicalDecl(); 503296417Sdim return Stack.back().LCVMap.count(D) > 0 ? Stack.back().LCVMap[D] : 0; 504288943Sdim} 505288943Sdim 506296417Sdimunsigned DSAStackTy::isParentLoopControlVariable(VarDecl *D) { 507296417Sdim assert(Stack.size() > 2 && "Data-sharing attributes stack is empty"); 508296417Sdim D = D->getCanonicalDecl(); 509296417Sdim return Stack[Stack.size() - 2].LCVMap.count(D) > 0 510296417Sdim ? Stack[Stack.size() - 2].LCVMap[D] 511296417Sdim : 0; 512296417Sdim} 513296417Sdim 514296417SdimVarDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) { 515296417Sdim assert(Stack.size() > 2 && "Data-sharing attributes stack is empty"); 516296417Sdim if (Stack[Stack.size() - 2].LCVMap.size() < I) 517296417Sdim return nullptr; 518296417Sdim for (auto &Pair : Stack[Stack.size() - 2].LCVMap) { 519296417Sdim if (Pair.second == I) 520296417Sdim return Pair.first; 521296417Sdim } 522296417Sdim return nullptr; 523296417Sdim} 524296417Sdim 525261991Sdimvoid DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) { 526288943Sdim D = D->getCanonicalDecl(); 527261991Sdim if (A == OMPC_threadprivate) { 528261991Sdim Stack[0].SharingMap[D].Attributes = A; 529261991Sdim Stack[0].SharingMap[D].RefExpr = E; 530261991Sdim } else { 531261991Sdim assert(Stack.size() > 1 && "Data-sharing attributes stack is empty"); 532261991Sdim Stack.back().SharingMap[D].Attributes = A; 533261991Sdim Stack.back().SharingMap[D].RefExpr = E; 534261991Sdim } 535261991Sdim} 536261991Sdim 537276479Sdimbool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) { 538288943Sdim D = D->getCanonicalDecl(); 539276479Sdim if (Stack.size() > 2) { 540276479Sdim reverse_iterator I = Iter, E = std::prev(Stack.rend()); 541276479Sdim Scope *TopScope = nullptr; 542276479Sdim while (I != E && !isParallelOrTaskRegion(I->Directive)) { 543276479Sdim ++I; 544276479Sdim } 545276479Sdim if (I == E) 546276479Sdim return false; 547276479Sdim TopScope = I->CurScope ? I->CurScope->getParent() : nullptr; 548276479Sdim Scope *CurScope = getCurScope(); 549276479Sdim while (CurScope != TopScope && !CurScope->isDeclScope(D)) { 550261991Sdim CurScope = CurScope->getParent(); 551276479Sdim } 552276479Sdim return CurScope != TopScope; 553261991Sdim } 554276479Sdim return false; 555261991Sdim} 556261991Sdim 557288943Sdim/// \brief Build a variable declaration for OpenMP loop iteration variable. 558288943Sdimstatic VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type, 559296417Sdim StringRef Name, const AttrVec *Attrs = nullptr) { 560288943Sdim DeclContext *DC = SemaRef.CurContext; 561288943Sdim IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name); 562288943Sdim TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc); 563288943Sdim VarDecl *Decl = 564288943Sdim VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None); 565296417Sdim if (Attrs) { 566296417Sdim for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end()); 567296417Sdim I != E; ++I) 568296417Sdim Decl->addAttr(*I); 569296417Sdim } 570288943Sdim Decl->setImplicit(); 571288943Sdim return Decl; 572288943Sdim} 573288943Sdim 574288943Sdimstatic DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty, 575288943Sdim SourceLocation Loc, 576288943Sdim bool RefersToCapture = false) { 577288943Sdim D->setReferenced(); 578288943Sdim D->markUsed(S.Context); 579288943Sdim return DeclRefExpr::Create(S.getASTContext(), NestedNameSpecifierLoc(), 580288943Sdim SourceLocation(), D, RefersToCapture, Loc, Ty, 581288943Sdim VK_LValue); 582288943Sdim} 583288943Sdim 584276479SdimDSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) { 585288943Sdim D = D->getCanonicalDecl(); 586261991Sdim DSAVarData DVar; 587261991Sdim 588261991Sdim // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 589261991Sdim // in a Construct, C/C++, predetermined, p.1] 590261991Sdim // Variables appearing in threadprivate directives are threadprivate. 591288943Sdim if ((D->getTLSKind() != VarDecl::TLS_None && 592288943Sdim !(D->hasAttr<OMPThreadPrivateDeclAttr>() && 593288943Sdim SemaRef.getLangOpts().OpenMPUseTLS && 594288943Sdim SemaRef.getASTContext().getTargetInfo().isTLSSupported())) || 595288943Sdim (D->getStorageClass() == SC_Register && D->hasAttr<AsmLabelAttr>() && 596288943Sdim !D->isLocalVarDecl())) { 597288943Sdim addDSA(D, buildDeclRefExpr(SemaRef, D, D->getType().getNonReferenceType(), 598288943Sdim D->getLocation()), 599288943Sdim OMPC_threadprivate); 600261991Sdim } 601261991Sdim if (Stack[0].SharingMap.count(D)) { 602261991Sdim DVar.RefExpr = Stack[0].SharingMap[D].RefExpr; 603261991Sdim DVar.CKind = OMPC_threadprivate; 604261991Sdim return DVar; 605261991Sdim } 606261991Sdim 607261991Sdim // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 608296417Sdim // in a Construct, C/C++, predetermined, p.4] 609296417Sdim // Static data members are shared. 610296417Sdim // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 611296417Sdim // in a Construct, C/C++, predetermined, p.7] 612296417Sdim // Variables with static storage duration that are declared in a scope 613296417Sdim // inside the construct are shared. 614296417Sdim if (D->isStaticDataMember()) { 615296417Sdim DSAVarData DVarTemp = 616296417Sdim hasDSA(D, isOpenMPPrivate, MatchesAlways(), FromParent); 617296417Sdim if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr) 618276479Sdim return DVar; 619261991Sdim 620296417Sdim DVar.CKind = OMPC_shared; 621296417Sdim return DVar; 622261991Sdim } 623261991Sdim 624261991Sdim QualType Type = D->getType().getNonReferenceType().getCanonicalType(); 625276479Sdim bool IsConstant = Type.isConstant(SemaRef.getASTContext()); 626288943Sdim Type = SemaRef.getASTContext().getBaseElementType(Type); 627261991Sdim // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 628261991Sdim // in a Construct, C/C++, predetermined, p.6] 629261991Sdim // Variables with const qualified type having no mutable member are 630261991Sdim // shared. 631276479Sdim CXXRecordDecl *RD = 632276479Sdim SemaRef.getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr; 633296417Sdim if (auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD)) 634296417Sdim if (auto *CTD = CTSD->getSpecializedTemplate()) 635296417Sdim RD = CTD->getTemplatedDecl(); 636261991Sdim if (IsConstant && 637296417Sdim !(SemaRef.getLangOpts().CPlusPlus && RD && RD->hasDefinition() && 638296417Sdim RD->hasMutableFields())) { 639261991Sdim // Variables with const-qualified type having no mutable member may be 640261991Sdim // listed in a firstprivate clause, even if they are static data members. 641276479Sdim DSAVarData DVarTemp = hasDSA(D, MatchesAnyClause(OMPC_firstprivate), 642276479Sdim MatchesAlways(), FromParent); 643261991Sdim if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr) 644261991Sdim return DVar; 645261991Sdim 646261991Sdim DVar.CKind = OMPC_shared; 647261991Sdim return DVar; 648261991Sdim } 649261991Sdim 650261991Sdim // Explicitly specified attributes and local variables with predetermined 651261991Sdim // attributes. 652296417Sdim auto StartI = std::next(Stack.rbegin()); 653296417Sdim auto EndI = std::prev(Stack.rend()); 654296417Sdim if (FromParent && StartI != EndI) { 655296417Sdim StartI = std::next(StartI); 656296417Sdim } 657276479Sdim auto I = std::prev(StartI); 658276479Sdim if (I->SharingMap.count(D)) { 659276479Sdim DVar.RefExpr = I->SharingMap[D].RefExpr; 660276479Sdim DVar.CKind = I->SharingMap[D].Attributes; 661276479Sdim DVar.ImplicitDSALoc = I->DefaultAttrLoc; 662261991Sdim } 663261991Sdim 664261991Sdim return DVar; 665261991Sdim} 666261991Sdim 667276479SdimDSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(VarDecl *D, bool FromParent) { 668288943Sdim D = D->getCanonicalDecl(); 669276479Sdim auto StartI = Stack.rbegin(); 670276479Sdim auto EndI = std::prev(Stack.rend()); 671276479Sdim if (FromParent && StartI != EndI) { 672276479Sdim StartI = std::next(StartI); 673276479Sdim } 674276479Sdim return getDSA(StartI, D); 675261991Sdim} 676261991Sdim 677276479Sdimtemplate <class ClausesPredicate, class DirectivesPredicate> 678276479SdimDSAStackTy::DSAVarData DSAStackTy::hasDSA(VarDecl *D, ClausesPredicate CPred, 679276479Sdim DirectivesPredicate DPred, 680276479Sdim bool FromParent) { 681288943Sdim D = D->getCanonicalDecl(); 682276479Sdim auto StartI = std::next(Stack.rbegin()); 683276479Sdim auto EndI = std::prev(Stack.rend()); 684276479Sdim if (FromParent && StartI != EndI) { 685276479Sdim StartI = std::next(StartI); 686276479Sdim } 687276479Sdim for (auto I = StartI, EE = EndI; I != EE; ++I) { 688276479Sdim if (!DPred(I->Directive) && !isParallelOrTaskRegion(I->Directive)) 689276479Sdim continue; 690261991Sdim DSAVarData DVar = getDSA(I, D); 691276479Sdim if (CPred(DVar.CKind)) 692261991Sdim return DVar; 693261991Sdim } 694261991Sdim return DSAVarData(); 695261991Sdim} 696249261Sdim 697276479Sdimtemplate <class ClausesPredicate, class DirectivesPredicate> 698276479SdimDSAStackTy::DSAVarData 699276479SdimDSAStackTy::hasInnermostDSA(VarDecl *D, ClausesPredicate CPred, 700276479Sdim DirectivesPredicate DPred, bool FromParent) { 701288943Sdim D = D->getCanonicalDecl(); 702276479Sdim auto StartI = std::next(Stack.rbegin()); 703276479Sdim auto EndI = std::prev(Stack.rend()); 704276479Sdim if (FromParent && StartI != EndI) { 705276479Sdim StartI = std::next(StartI); 706276479Sdim } 707276479Sdim for (auto I = StartI, EE = EndI; I != EE; ++I) { 708276479Sdim if (!DPred(I->Directive)) 709276479Sdim break; 710276479Sdim DSAVarData DVar = getDSA(I, D); 711276479Sdim if (CPred(DVar.CKind)) 712276479Sdim return DVar; 713276479Sdim return DSAVarData(); 714276479Sdim } 715276479Sdim return DSAVarData(); 716276479Sdim} 717276479Sdim 718288943Sdimbool DSAStackTy::hasExplicitDSA( 719288943Sdim VarDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> &CPred, 720288943Sdim unsigned Level) { 721288943Sdim if (CPred(ClauseKindMode)) 722288943Sdim return true; 723288943Sdim if (isClauseParsingMode()) 724288943Sdim ++Level; 725288943Sdim D = D->getCanonicalDecl(); 726288943Sdim auto StartI = Stack.rbegin(); 727288943Sdim auto EndI = std::prev(Stack.rend()); 728288943Sdim if (std::distance(StartI, EndI) <= (int)Level) 729288943Sdim return false; 730288943Sdim std::advance(StartI, Level); 731288943Sdim return (StartI->SharingMap.count(D) > 0) && StartI->SharingMap[D].RefExpr && 732288943Sdim CPred(StartI->SharingMap[D].Attributes); 733288943Sdim} 734288943Sdim 735296417Sdimbool DSAStackTy::hasExplicitDirective( 736296417Sdim const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred, 737296417Sdim unsigned Level) { 738296417Sdim if (isClauseParsingMode()) 739296417Sdim ++Level; 740296417Sdim auto StartI = Stack.rbegin(); 741296417Sdim auto EndI = std::prev(Stack.rend()); 742296417Sdim if (std::distance(StartI, EndI) <= (int)Level) 743296417Sdim return false; 744296417Sdim std::advance(StartI, Level); 745296417Sdim return DPred(StartI->Directive); 746296417Sdim} 747296417Sdim 748276479Sdimtemplate <class NamedDirectivesPredicate> 749276479Sdimbool DSAStackTy::hasDirective(NamedDirectivesPredicate DPred, bool FromParent) { 750276479Sdim auto StartI = std::next(Stack.rbegin()); 751276479Sdim auto EndI = std::prev(Stack.rend()); 752276479Sdim if (FromParent && StartI != EndI) { 753276479Sdim StartI = std::next(StartI); 754276479Sdim } 755276479Sdim for (auto I = StartI, EE = EndI; I != EE; ++I) { 756276479Sdim if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc)) 757276479Sdim return true; 758276479Sdim } 759276479Sdim return false; 760276479Sdim} 761276479Sdim 762296417SdimOpenMPDirectiveKind DSAStackTy::getDirectiveForScope(const Scope *S) const { 763296417Sdim for (auto I = Stack.rbegin(), EE = Stack.rend(); I != EE; ++I) 764296417Sdim if (I->CurScope == S) 765296417Sdim return I->Directive; 766296417Sdim return OMPD_unknown; 767296417Sdim} 768296417Sdim 769261991Sdimvoid Sema::InitDataSharingAttributesStack() { 770261991Sdim VarDataSharingAttributesStack = new DSAStackTy(*this); 771261991Sdim} 772249261Sdim 773261991Sdim#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack) 774261991Sdim 775296417Sdimbool Sema::IsOpenMPCapturedByRef(VarDecl *VD, 776296417Sdim const CapturedRegionScopeInfo *RSI) { 777296417Sdim assert(LangOpts.OpenMP && "OpenMP is not allowed"); 778296417Sdim 779296417Sdim auto &Ctx = getASTContext(); 780296417Sdim bool IsByRef = true; 781296417Sdim 782296417Sdim // Find the directive that is associated with the provided scope. 783296417Sdim auto DKind = DSAStack->getDirectiveForScope(RSI->TheScope); 784296417Sdim auto Ty = VD->getType(); 785296417Sdim 786296417Sdim if (isOpenMPTargetDirective(DKind)) { 787296417Sdim // This table summarizes how a given variable should be passed to the device 788296417Sdim // given its type and the clauses where it appears. This table is based on 789296417Sdim // the description in OpenMP 4.5 [2.10.4, target Construct] and 790296417Sdim // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses]. 791296417Sdim // 792296417Sdim // ========================================================================= 793296417Sdim // | type | defaultmap | pvt | first | is_device_ptr | map | res. | 794296417Sdim // | |(tofrom:scalar)| | pvt | | | | 795296417Sdim // ========================================================================= 796296417Sdim // | scl | | | | - | | bycopy| 797296417Sdim // | scl | | - | x | - | - | bycopy| 798296417Sdim // | scl | | x | - | - | - | null | 799296417Sdim // | scl | x | | | - | | byref | 800296417Sdim // | scl | x | - | x | - | - | bycopy| 801296417Sdim // | scl | x | x | - | - | - | null | 802296417Sdim // | scl | | - | - | - | x | byref | 803296417Sdim // | scl | x | - | - | - | x | byref | 804296417Sdim // 805296417Sdim // | agg | n.a. | | | - | | byref | 806296417Sdim // | agg | n.a. | - | x | - | - | byref | 807296417Sdim // | agg | n.a. | x | - | - | - | null | 808296417Sdim // | agg | n.a. | - | - | - | x | byref | 809296417Sdim // | agg | n.a. | - | - | - | x[] | byref | 810296417Sdim // 811296417Sdim // | ptr | n.a. | | | - | | bycopy| 812296417Sdim // | ptr | n.a. | - | x | - | - | bycopy| 813296417Sdim // | ptr | n.a. | x | - | - | - | null | 814296417Sdim // | ptr | n.a. | - | - | - | x | byref | 815296417Sdim // | ptr | n.a. | - | - | - | x[] | bycopy| 816296417Sdim // | ptr | n.a. | - | - | x | | bycopy| 817296417Sdim // | ptr | n.a. | - | - | x | x | bycopy| 818296417Sdim // | ptr | n.a. | - | - | x | x[] | bycopy| 819296417Sdim // ========================================================================= 820296417Sdim // Legend: 821296417Sdim // scl - scalar 822296417Sdim // ptr - pointer 823296417Sdim // agg - aggregate 824296417Sdim // x - applies 825296417Sdim // - - invalid in this combination 826296417Sdim // [] - mapped with an array section 827296417Sdim // byref - should be mapped by reference 828296417Sdim // byval - should be mapped by value 829296417Sdim // null - initialize a local variable to null on the device 830296417Sdim // 831296417Sdim // Observations: 832296417Sdim // - All scalar declarations that show up in a map clause have to be passed 833296417Sdim // by reference, because they may have been mapped in the enclosing data 834296417Sdim // environment. 835296417Sdim // - If the scalar value does not fit the size of uintptr, it has to be 836296417Sdim // passed by reference, regardless the result in the table above. 837296417Sdim // - For pointers mapped by value that have either an implicit map or an 838296417Sdim // array section, the runtime library may pass the NULL value to the 839296417Sdim // device instead of the value passed to it by the compiler. 840296417Sdim 841296417Sdim // FIXME: Right now, only implicit maps are implemented. Properly mapping 842296417Sdim // values requires having the map, private, and firstprivate clauses SEMA 843296417Sdim // and parsing in place, which we don't yet. 844296417Sdim 845296417Sdim if (Ty->isReferenceType()) 846296417Sdim Ty = Ty->castAs<ReferenceType>()->getPointeeType(); 847296417Sdim IsByRef = !Ty->isScalarType(); 848296417Sdim } 849296417Sdim 850296417Sdim // When passing data by value, we need to make sure it fits the uintptr size 851296417Sdim // and alignment, because the runtime library only deals with uintptr types. 852296417Sdim // If it does not fit the uintptr size, we need to pass the data by reference 853296417Sdim // instead. 854296417Sdim if (!IsByRef && 855296417Sdim (Ctx.getTypeSizeInChars(Ty) > 856296417Sdim Ctx.getTypeSizeInChars(Ctx.getUIntPtrType()) || 857296417Sdim Ctx.getDeclAlign(VD) > Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) 858296417Sdim IsByRef = true; 859296417Sdim 860296417Sdim return IsByRef; 861296417Sdim} 862296417Sdim 863280031Sdimbool Sema::IsOpenMPCapturedVar(VarDecl *VD) { 864280031Sdim assert(LangOpts.OpenMP && "OpenMP is not allowed"); 865288943Sdim VD = VD->getCanonicalDecl(); 866296417Sdim 867296417Sdim // If we are attempting to capture a global variable in a directive with 868296417Sdim // 'target' we return true so that this global is also mapped to the device. 869296417Sdim // 870296417Sdim // FIXME: If the declaration is enclosed in a 'declare target' directive, 871296417Sdim // then it should not be captured. Therefore, an extra check has to be 872296417Sdim // inserted here once support for 'declare target' is added. 873296417Sdim // 874296417Sdim if (!VD->hasLocalStorage()) { 875296417Sdim if (DSAStack->getCurrentDirective() == OMPD_target && 876296417Sdim !DSAStack->isClauseParsingMode()) { 877296417Sdim return true; 878296417Sdim } 879296417Sdim if (DSAStack->getCurScope() && 880296417Sdim DSAStack->hasDirective( 881296417Sdim [](OpenMPDirectiveKind K, const DeclarationNameInfo &DNI, 882296417Sdim SourceLocation Loc) -> bool { 883296417Sdim return isOpenMPTargetDirective(K); 884296417Sdim }, 885296417Sdim false)) { 886296417Sdim return true; 887296417Sdim } 888296417Sdim } 889296417Sdim 890288943Sdim if (DSAStack->getCurrentDirective() != OMPD_unknown && 891288943Sdim (!DSAStack->isClauseParsingMode() || 892288943Sdim DSAStack->getParentDirective() != OMPD_unknown)) { 893288943Sdim if (DSAStack->isLoopControlVariable(VD) || 894288943Sdim (VD->hasLocalStorage() && 895288943Sdim isParallelOrTaskRegion(DSAStack->getCurrentDirective())) || 896288943Sdim DSAStack->isForceVarCapturing()) 897288943Sdim return true; 898288943Sdim auto DVarPrivate = DSAStack->getTopDSA(VD, DSAStack->isClauseParsingMode()); 899280031Sdim if (DVarPrivate.CKind != OMPC_unknown && isOpenMPPrivate(DVarPrivate.CKind)) 900280031Sdim return true; 901280031Sdim DVarPrivate = DSAStack->hasDSA(VD, isOpenMPPrivate, MatchesAlways(), 902288943Sdim DSAStack->isClauseParsingMode()); 903280031Sdim return DVarPrivate.CKind != OMPC_unknown; 904280031Sdim } 905280031Sdim return false; 906280031Sdim} 907280031Sdim 908288943Sdimbool Sema::isOpenMPPrivateVar(VarDecl *VD, unsigned Level) { 909288943Sdim assert(LangOpts.OpenMP && "OpenMP is not allowed"); 910288943Sdim return DSAStack->hasExplicitDSA( 911288943Sdim VD, [](OpenMPClauseKind K) -> bool { return K == OMPC_private; }, Level); 912288943Sdim} 913288943Sdim 914296417Sdimbool Sema::isOpenMPTargetCapturedVar(VarDecl *VD, unsigned Level) { 915296417Sdim assert(LangOpts.OpenMP && "OpenMP is not allowed"); 916296417Sdim // Return true if the current level is no longer enclosed in a target region. 917296417Sdim 918296417Sdim return !VD->hasLocalStorage() && 919296417Sdim DSAStack->hasExplicitDirective(isOpenMPTargetDirective, Level); 920296417Sdim} 921296417Sdim 922276479Sdimvoid Sema::DestroyDataSharingAttributesStack() { delete DSAStack; } 923261991Sdim 924261991Sdimvoid Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind, 925261991Sdim const DeclarationNameInfo &DirName, 926276479Sdim Scope *CurScope, SourceLocation Loc) { 927276479Sdim DSAStack->push(DKind, DirName, CurScope, Loc); 928261991Sdim PushExpressionEvaluationContext(PotentiallyEvaluated); 929261991Sdim} 930261991Sdim 931288943Sdimvoid Sema::StartOpenMPClause(OpenMPClauseKind K) { 932288943Sdim DSAStack->setClauseParsingMode(K); 933288943Sdim} 934288943Sdim 935288943Sdimvoid Sema::EndOpenMPClause() { 936288943Sdim DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown); 937288943Sdim} 938288943Sdim 939261991Sdimvoid Sema::EndOpenMPDSABlock(Stmt *CurDirective) { 940276479Sdim // OpenMP [2.14.3.5, Restrictions, C/C++, p.1] 941276479Sdim // A variable of class type (or array thereof) that appears in a lastprivate 942276479Sdim // clause requires an accessible, unambiguous default constructor for the 943276479Sdim // class type, unless the list item is also specified in a firstprivate 944276479Sdim // clause. 945276479Sdim if (auto D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) { 946288943Sdim for (auto *C : D->clauses()) { 947288943Sdim if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) { 948288943Sdim SmallVector<Expr *, 8> PrivateCopies; 949288943Sdim for (auto *DE : Clause->varlists()) { 950288943Sdim if (DE->isValueDependent() || DE->isTypeDependent()) { 951288943Sdim PrivateCopies.push_back(nullptr); 952276479Sdim continue; 953288943Sdim } 954288943Sdim auto *VD = cast<VarDecl>(cast<DeclRefExpr>(DE)->getDecl()); 955296417Sdim QualType Type = VD->getType().getNonReferenceType(); 956276479Sdim auto DVar = DSAStack->getTopDSA(VD, false); 957276479Sdim if (DVar.CKind == OMPC_lastprivate) { 958288943Sdim // Generate helper private variable and initialize it with the 959288943Sdim // default value. The address of the original variable is replaced 960288943Sdim // by the address of the new private variable in CodeGen. This new 961288943Sdim // variable is not added to IdResolver, so the code in the OpenMP 962288943Sdim // region uses original variable for proper diagnostics. 963296417Sdim auto *VDPrivate = buildVarDecl( 964296417Sdim *this, DE->getExprLoc(), Type.getUnqualifiedType(), 965296417Sdim VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr); 966288943Sdim ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false); 967288943Sdim if (VDPrivate->isInvalidDecl()) 968288943Sdim continue; 969288943Sdim PrivateCopies.push_back(buildDeclRefExpr( 970288943Sdim *this, VDPrivate, DE->getType(), DE->getExprLoc())); 971288943Sdim } else { 972288943Sdim // The variable is also a firstprivate, so initialization sequence 973288943Sdim // for private copy is generated already. 974288943Sdim PrivateCopies.push_back(nullptr); 975276479Sdim } 976276479Sdim } 977288943Sdim // Set initializers to private copies if no errors were found. 978288943Sdim if (PrivateCopies.size() == Clause->varlist_size()) { 979288943Sdim Clause->setPrivateCopies(PrivateCopies); 980288943Sdim } 981276479Sdim } 982276479Sdim } 983276479Sdim } 984276479Sdim 985261991Sdim DSAStack->pop(); 986261991Sdim DiscardCleanupsInEvaluationContext(); 987261991Sdim PopExpressionEvaluationContext(); 988261991Sdim} 989261991Sdim 990288943Sdimstatic bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, 991288943Sdim Expr *NumIterations, Sema &SemaRef, 992288943Sdim Scope *S); 993288943Sdim 994261991Sdimnamespace { 995261991Sdim 996261991Sdimclass VarDeclFilterCCC : public CorrectionCandidateCallback { 997261991Sdimprivate: 998276479Sdim Sema &SemaRef; 999276479Sdim 1000261991Sdimpublic: 1001276479Sdim explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {} 1002276479Sdim bool ValidateCandidate(const TypoCorrection &Candidate) override { 1003261991Sdim NamedDecl *ND = Candidate.getCorrectionDecl(); 1004261991Sdim if (VarDecl *VD = dyn_cast_or_null<VarDecl>(ND)) { 1005261991Sdim return VD->hasGlobalStorage() && 1006276479Sdim SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(), 1007276479Sdim SemaRef.getCurScope()); 1008261991Sdim } 1009261991Sdim return false; 1010261991Sdim } 1011261991Sdim}; 1012276479Sdim} // namespace 1013261991Sdim 1014261991SdimExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope, 1015261991Sdim CXXScopeSpec &ScopeSpec, 1016261991Sdim const DeclarationNameInfo &Id) { 1017261991Sdim LookupResult Lookup(*this, Id, LookupOrdinaryName); 1018261991Sdim LookupParsedName(Lookup, CurScope, &ScopeSpec, true); 1019261991Sdim 1020261991Sdim if (Lookup.isAmbiguous()) 1021261991Sdim return ExprError(); 1022261991Sdim 1023261991Sdim VarDecl *VD; 1024261991Sdim if (!Lookup.isSingleResult()) { 1025280031Sdim if (TypoCorrection Corrected = CorrectTypo( 1026280031Sdim Id, LookupOrdinaryName, CurScope, nullptr, 1027280031Sdim llvm::make_unique<VarDeclFilterCCC>(*this), CTK_ErrorRecovery)) { 1028261991Sdim diagnoseTypo(Corrected, 1029276479Sdim PDiag(Lookup.empty() 1030276479Sdim ? diag::err_undeclared_var_use_suggest 1031276479Sdim : diag::err_omp_expected_var_arg_suggest) 1032276479Sdim << Id.getName()); 1033249261Sdim VD = Corrected.getCorrectionDeclAs<VarDecl>(); 1034249261Sdim } else { 1035261991Sdim Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use 1036261991Sdim : diag::err_omp_expected_var_arg) 1037261991Sdim << Id.getName(); 1038261991Sdim return ExprError(); 1039249261Sdim } 1040261991Sdim } else { 1041261991Sdim if (!(VD = Lookup.getAsSingle<VarDecl>())) { 1042276479Sdim Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName(); 1043261991Sdim Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at); 1044261991Sdim return ExprError(); 1045249261Sdim } 1046261991Sdim } 1047261991Sdim Lookup.suppressDiagnostics(); 1048249261Sdim 1049261991Sdim // OpenMP [2.9.2, Syntax, C/C++] 1050261991Sdim // Variables must be file-scope, namespace-scope, or static block-scope. 1051261991Sdim if (!VD->hasGlobalStorage()) { 1052261991Sdim Diag(Id.getLoc(), diag::err_omp_global_var_arg) 1053276479Sdim << getOpenMPDirectiveName(OMPD_threadprivate) << !VD->isStaticLocal(); 1054276479Sdim bool IsDecl = 1055276479Sdim VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 1056261991Sdim Diag(VD->getLocation(), 1057276479Sdim IsDecl ? diag::note_previous_decl : diag::note_defined_here) 1058276479Sdim << VD; 1059261991Sdim return ExprError(); 1060261991Sdim } 1061249261Sdim 1062261991Sdim VarDecl *CanonicalVD = VD->getCanonicalDecl(); 1063261991Sdim NamedDecl *ND = cast<NamedDecl>(CanonicalVD); 1064261991Sdim // OpenMP [2.9.2, Restrictions, C/C++, p.2] 1065261991Sdim // A threadprivate directive for file-scope variables must appear outside 1066261991Sdim // any definition or declaration. 1067261991Sdim if (CanonicalVD->getDeclContext()->isTranslationUnit() && 1068261991Sdim !getCurLexicalContext()->isTranslationUnit()) { 1069261991Sdim Diag(Id.getLoc(), diag::err_omp_var_scope) 1070276479Sdim << getOpenMPDirectiveName(OMPD_threadprivate) << VD; 1071276479Sdim bool IsDecl = 1072276479Sdim VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 1073276479Sdim Diag(VD->getLocation(), 1074276479Sdim IsDecl ? diag::note_previous_decl : diag::note_defined_here) 1075276479Sdim << VD; 1076261991Sdim return ExprError(); 1077261991Sdim } 1078261991Sdim // OpenMP [2.9.2, Restrictions, C/C++, p.3] 1079261991Sdim // A threadprivate directive for static class member variables must appear 1080261991Sdim // in the class definition, in the same scope in which the member 1081261991Sdim // variables are declared. 1082261991Sdim if (CanonicalVD->isStaticDataMember() && 1083261991Sdim !CanonicalVD->getDeclContext()->Equals(getCurLexicalContext())) { 1084261991Sdim Diag(Id.getLoc(), diag::err_omp_var_scope) 1085276479Sdim << getOpenMPDirectiveName(OMPD_threadprivate) << VD; 1086276479Sdim bool IsDecl = 1087276479Sdim VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 1088276479Sdim Diag(VD->getLocation(), 1089276479Sdim IsDecl ? diag::note_previous_decl : diag::note_defined_here) 1090276479Sdim << VD; 1091261991Sdim return ExprError(); 1092261991Sdim } 1093261991Sdim // OpenMP [2.9.2, Restrictions, C/C++, p.4] 1094261991Sdim // A threadprivate directive for namespace-scope variables must appear 1095261991Sdim // outside any definition or declaration other than the namespace 1096261991Sdim // definition itself. 1097261991Sdim if (CanonicalVD->getDeclContext()->isNamespace() && 1098261991Sdim (!getCurLexicalContext()->isFileContext() || 1099261991Sdim !getCurLexicalContext()->Encloses(CanonicalVD->getDeclContext()))) { 1100261991Sdim Diag(Id.getLoc(), diag::err_omp_var_scope) 1101276479Sdim << getOpenMPDirectiveName(OMPD_threadprivate) << VD; 1102276479Sdim bool IsDecl = 1103276479Sdim VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 1104276479Sdim Diag(VD->getLocation(), 1105276479Sdim IsDecl ? diag::note_previous_decl : diag::note_defined_here) 1106276479Sdim << VD; 1107261991Sdim return ExprError(); 1108261991Sdim } 1109261991Sdim // OpenMP [2.9.2, Restrictions, C/C++, p.6] 1110261991Sdim // A threadprivate directive for static block-scope variables must appear 1111261991Sdim // in the scope of the variable and not in a nested scope. 1112261991Sdim if (CanonicalVD->isStaticLocal() && CurScope && 1113261991Sdim !isDeclInScope(ND, getCurLexicalContext(), CurScope)) { 1114261991Sdim Diag(Id.getLoc(), diag::err_omp_var_scope) 1115276479Sdim << getOpenMPDirectiveName(OMPD_threadprivate) << VD; 1116276479Sdim bool IsDecl = 1117276479Sdim VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 1118276479Sdim Diag(VD->getLocation(), 1119276479Sdim IsDecl ? diag::note_previous_decl : diag::note_defined_here) 1120276479Sdim << VD; 1121261991Sdim return ExprError(); 1122261991Sdim } 1123249261Sdim 1124261991Sdim // OpenMP [2.9.2, Restrictions, C/C++, p.2-6] 1125261991Sdim // A threadprivate directive must lexically precede all references to any 1126261991Sdim // of the variables in its list. 1127288943Sdim if (VD->isUsed() && !DSAStack->isThreadPrivate(VD)) { 1128261991Sdim Diag(Id.getLoc(), diag::err_omp_var_used) 1129276479Sdim << getOpenMPDirectiveName(OMPD_threadprivate) << VD; 1130261991Sdim return ExprError(); 1131249261Sdim } 1132261991Sdim 1133261991Sdim QualType ExprType = VD->getType().getNonReferenceType(); 1134288943Sdim ExprResult DE = buildDeclRefExpr(*this, VD, ExprType, Id.getLoc()); 1135261991Sdim return DE; 1136261991Sdim} 1137261991Sdim 1138276479SdimSema::DeclGroupPtrTy 1139276479SdimSema::ActOnOpenMPThreadprivateDirective(SourceLocation Loc, 1140276479Sdim ArrayRef<Expr *> VarList) { 1141261991Sdim if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) { 1142249261Sdim CurContext->addDecl(D); 1143249261Sdim return DeclGroupPtrTy::make(DeclGroupRef(D)); 1144249261Sdim } 1145249261Sdim return DeclGroupPtrTy(); 1146249261Sdim} 1147249261Sdim 1148276479Sdimnamespace { 1149276479Sdimclass LocalVarRefChecker : public ConstStmtVisitor<LocalVarRefChecker, bool> { 1150276479Sdim Sema &SemaRef; 1151276479Sdim 1152276479Sdimpublic: 1153276479Sdim bool VisitDeclRefExpr(const DeclRefExpr *E) { 1154276479Sdim if (auto VD = dyn_cast<VarDecl>(E->getDecl())) { 1155276479Sdim if (VD->hasLocalStorage()) { 1156276479Sdim SemaRef.Diag(E->getLocStart(), 1157276479Sdim diag::err_omp_local_var_in_threadprivate_init) 1158276479Sdim << E->getSourceRange(); 1159276479Sdim SemaRef.Diag(VD->getLocation(), diag::note_defined_here) 1160276479Sdim << VD << VD->getSourceRange(); 1161276479Sdim return true; 1162276479Sdim } 1163276479Sdim } 1164276479Sdim return false; 1165276479Sdim } 1166276479Sdim bool VisitStmt(const Stmt *S) { 1167276479Sdim for (auto Child : S->children()) { 1168276479Sdim if (Child && Visit(Child)) 1169276479Sdim return true; 1170276479Sdim } 1171276479Sdim return false; 1172276479Sdim } 1173276479Sdim explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {} 1174276479Sdim}; 1175276479Sdim} // namespace 1176276479Sdim 1177276479SdimOMPThreadPrivateDecl * 1178276479SdimSema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) { 1179261991Sdim SmallVector<Expr *, 8> Vars; 1180276479Sdim for (auto &RefExpr : VarList) { 1181276479Sdim DeclRefExpr *DE = cast<DeclRefExpr>(RefExpr); 1182261991Sdim VarDecl *VD = cast<VarDecl>(DE->getDecl()); 1183261991Sdim SourceLocation ILoc = DE->getExprLoc(); 1184249261Sdim 1185288943Sdim QualType QType = VD->getType(); 1186288943Sdim if (QType->isDependentType() || QType->isInstantiationDependentType()) { 1187288943Sdim // It will be analyzed later. 1188288943Sdim Vars.push_back(DE); 1189288943Sdim continue; 1190288943Sdim } 1191288943Sdim 1192249261Sdim // OpenMP [2.9.2, Restrictions, C/C++, p.10] 1193249261Sdim // A threadprivate variable must not have an incomplete type. 1194249261Sdim if (RequireCompleteType(ILoc, VD->getType(), 1195261991Sdim diag::err_omp_threadprivate_incomplete_type)) { 1196249261Sdim continue; 1197249261Sdim } 1198249261Sdim 1199249261Sdim // OpenMP [2.9.2, Restrictions, C/C++, p.10] 1200249261Sdim // A threadprivate variable must not have a reference type. 1201249261Sdim if (VD->getType()->isReferenceType()) { 1202249261Sdim Diag(ILoc, diag::err_omp_ref_type_arg) 1203276479Sdim << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType(); 1204276479Sdim bool IsDecl = 1205276479Sdim VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 1206276479Sdim Diag(VD->getLocation(), 1207276479Sdim IsDecl ? diag::note_previous_decl : diag::note_defined_here) 1208276479Sdim << VD; 1209249261Sdim continue; 1210249261Sdim } 1211249261Sdim 1212288943Sdim // Check if this is a TLS variable. If TLS is not being supported, produce 1213288943Sdim // the corresponding diagnostic. 1214288943Sdim if ((VD->getTLSKind() != VarDecl::TLS_None && 1215288943Sdim !(VD->hasAttr<OMPThreadPrivateDeclAttr>() && 1216288943Sdim getLangOpts().OpenMPUseTLS && 1217288943Sdim getASTContext().getTargetInfo().isTLSSupported())) || 1218288943Sdim (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() && 1219288943Sdim !VD->isLocalVarDecl())) { 1220280031Sdim Diag(ILoc, diag::err_omp_var_thread_local) 1221280031Sdim << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1); 1222276479Sdim bool IsDecl = 1223276479Sdim VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 1224276479Sdim Diag(VD->getLocation(), 1225276479Sdim IsDecl ? diag::note_previous_decl : diag::note_defined_here) 1226276479Sdim << VD; 1227249261Sdim continue; 1228249261Sdim } 1229249261Sdim 1230276479Sdim // Check if initial value of threadprivate variable reference variable with 1231276479Sdim // local storage (it is not supported by runtime). 1232276479Sdim if (auto Init = VD->getAnyInitializer()) { 1233276479Sdim LocalVarRefChecker Checker(*this); 1234276479Sdim if (Checker.Visit(Init)) 1235276479Sdim continue; 1236276479Sdim } 1237276479Sdim 1238276479Sdim Vars.push_back(RefExpr); 1239276479Sdim DSAStack->addDSA(VD, DE, OMPC_threadprivate); 1240280031Sdim VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit( 1241280031Sdim Context, SourceRange(Loc, Loc))); 1242280031Sdim if (auto *ML = Context.getASTMutationListener()) 1243280031Sdim ML->DeclarationMarkedOpenMPThreadPrivate(VD); 1244249261Sdim } 1245276479Sdim OMPThreadPrivateDecl *D = nullptr; 1246276479Sdim if (!Vars.empty()) { 1247276479Sdim D = OMPThreadPrivateDecl::Create(Context, getCurLexicalContext(), Loc, 1248276479Sdim Vars); 1249276479Sdim D->setAccess(AS_public); 1250276479Sdim } 1251276479Sdim return D; 1252249261Sdim} 1253261991Sdim 1254276479Sdimstatic void ReportOriginalDSA(Sema &SemaRef, DSAStackTy *Stack, 1255276479Sdim const VarDecl *VD, DSAStackTy::DSAVarData DVar, 1256276479Sdim bool IsLoopIterVar = false) { 1257276479Sdim if (DVar.RefExpr) { 1258276479Sdim SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa) 1259276479Sdim << getOpenMPClauseName(DVar.CKind); 1260276479Sdim return; 1261276479Sdim } 1262276479Sdim enum { 1263276479Sdim PDSA_StaticMemberShared, 1264276479Sdim PDSA_StaticLocalVarShared, 1265276479Sdim PDSA_LoopIterVarPrivate, 1266276479Sdim PDSA_LoopIterVarLinear, 1267276479Sdim PDSA_LoopIterVarLastprivate, 1268276479Sdim PDSA_ConstVarShared, 1269276479Sdim PDSA_GlobalVarShared, 1270276479Sdim PDSA_TaskVarFirstprivate, 1271276479Sdim PDSA_LocalVarPrivate, 1272276479Sdim PDSA_Implicit 1273276479Sdim } Reason = PDSA_Implicit; 1274276479Sdim bool ReportHint = false; 1275276479Sdim auto ReportLoc = VD->getLocation(); 1276276479Sdim if (IsLoopIterVar) { 1277276479Sdim if (DVar.CKind == OMPC_private) 1278276479Sdim Reason = PDSA_LoopIterVarPrivate; 1279276479Sdim else if (DVar.CKind == OMPC_lastprivate) 1280276479Sdim Reason = PDSA_LoopIterVarLastprivate; 1281276479Sdim else 1282276479Sdim Reason = PDSA_LoopIterVarLinear; 1283276479Sdim } else if (DVar.DKind == OMPD_task && DVar.CKind == OMPC_firstprivate) { 1284276479Sdim Reason = PDSA_TaskVarFirstprivate; 1285276479Sdim ReportLoc = DVar.ImplicitDSALoc; 1286276479Sdim } else if (VD->isStaticLocal()) 1287276479Sdim Reason = PDSA_StaticLocalVarShared; 1288276479Sdim else if (VD->isStaticDataMember()) 1289276479Sdim Reason = PDSA_StaticMemberShared; 1290276479Sdim else if (VD->isFileVarDecl()) 1291276479Sdim Reason = PDSA_GlobalVarShared; 1292276479Sdim else if (VD->getType().isConstant(SemaRef.getASTContext())) 1293276479Sdim Reason = PDSA_ConstVarShared; 1294276479Sdim else if (VD->isLocalVarDecl() && DVar.CKind == OMPC_private) { 1295276479Sdim ReportHint = true; 1296276479Sdim Reason = PDSA_LocalVarPrivate; 1297276479Sdim } 1298276479Sdim if (Reason != PDSA_Implicit) { 1299276479Sdim SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa) 1300276479Sdim << Reason << ReportHint 1301276479Sdim << getOpenMPDirectiveName(Stack->getCurrentDirective()); 1302276479Sdim } else if (DVar.ImplicitDSALoc.isValid()) { 1303276479Sdim SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa) 1304276479Sdim << getOpenMPClauseName(DVar.CKind); 1305276479Sdim } 1306276479Sdim} 1307276479Sdim 1308261991Sdimnamespace { 1309261991Sdimclass DSAAttrChecker : public StmtVisitor<DSAAttrChecker, void> { 1310261991Sdim DSAStackTy *Stack; 1311276479Sdim Sema &SemaRef; 1312261991Sdim bool ErrorFound; 1313261991Sdim CapturedStmt *CS; 1314261991Sdim llvm::SmallVector<Expr *, 8> ImplicitFirstprivate; 1315276479Sdim llvm::DenseMap<VarDecl *, Expr *> VarsWithInheritedDSA; 1316276479Sdim 1317261991Sdimpublic: 1318261991Sdim void VisitDeclRefExpr(DeclRefExpr *E) { 1319276479Sdim if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) { 1320261991Sdim // Skip internally declared variables. 1321276479Sdim if (VD->isLocalVarDecl() && !CS->capturesVariable(VD)) 1322276479Sdim return; 1323261991Sdim 1324276479Sdim auto DVar = Stack->getTopDSA(VD, false); 1325276479Sdim // Check if the variable has explicit DSA set and stop analysis if it so. 1326276479Sdim if (DVar.RefExpr) return; 1327261991Sdim 1328276479Sdim auto ELoc = E->getExprLoc(); 1329276479Sdim auto DKind = Stack->getCurrentDirective(); 1330261991Sdim // The default(none) clause requires that each variable that is referenced 1331261991Sdim // in the construct, and does not have a predetermined data-sharing 1332261991Sdim // attribute, must have its data-sharing attribute explicitly determined 1333261991Sdim // by being listed in a data-sharing attribute clause. 1334261991Sdim if (DVar.CKind == OMPC_unknown && Stack->getDefaultDSA() == DSA_none && 1335276479Sdim isParallelOrTaskRegion(DKind) && 1336276479Sdim VarsWithInheritedDSA.count(VD) == 0) { 1337276479Sdim VarsWithInheritedDSA[VD] = E; 1338261991Sdim return; 1339261991Sdim } 1340261991Sdim 1341261991Sdim // OpenMP [2.9.3.6, Restrictions, p.2] 1342261991Sdim // A list item that appears in a reduction clause of the innermost 1343261991Sdim // enclosing worksharing or parallel construct may not be accessed in an 1344261991Sdim // explicit task. 1345276479Sdim DVar = Stack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_reduction), 1346276479Sdim [](OpenMPDirectiveKind K) -> bool { 1347276479Sdim return isOpenMPParallelDirective(K) || 1348280031Sdim isOpenMPWorksharingDirective(K) || 1349280031Sdim isOpenMPTeamsDirective(K); 1350276479Sdim }, 1351276479Sdim false); 1352276479Sdim if (DKind == OMPD_task && DVar.CKind == OMPC_reduction) { 1353276479Sdim ErrorFound = true; 1354276479Sdim SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task); 1355276479Sdim ReportOriginalDSA(SemaRef, Stack, VD, DVar); 1356276479Sdim return; 1357276479Sdim } 1358261991Sdim 1359261991Sdim // Define implicit data-sharing attributes for task. 1360276479Sdim DVar = Stack->getImplicitDSA(VD, false); 1361261991Sdim if (DKind == OMPD_task && DVar.CKind != OMPC_shared) 1362276479Sdim ImplicitFirstprivate.push_back(E); 1363261991Sdim } 1364261991Sdim } 1365261991Sdim void VisitOMPExecutableDirective(OMPExecutableDirective *S) { 1366276479Sdim for (auto *C : S->clauses()) { 1367276479Sdim // Skip analysis of arguments of implicitly defined firstprivate clause 1368276479Sdim // for task directives. 1369276479Sdim if (C && (!isa<OMPFirstprivateClause>(C) || C->getLocStart().isValid())) 1370276479Sdim for (auto *CC : C->children()) { 1371276479Sdim if (CC) 1372276479Sdim Visit(CC); 1373276479Sdim } 1374276479Sdim } 1375261991Sdim } 1376261991Sdim void VisitStmt(Stmt *S) { 1377276479Sdim for (auto *C : S->children()) { 1378276479Sdim if (C && !isa<OMPExecutableDirective>(C)) 1379276479Sdim Visit(C); 1380261991Sdim } 1381276479Sdim } 1382261991Sdim 1383261991Sdim bool isErrorFound() { return ErrorFound; } 1384261991Sdim ArrayRef<Expr *> getImplicitFirstprivate() { return ImplicitFirstprivate; } 1385276479Sdim llvm::DenseMap<VarDecl *, Expr *> &getVarsWithInheritedDSA() { 1386276479Sdim return VarsWithInheritedDSA; 1387276479Sdim } 1388261991Sdim 1389276479Sdim DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS) 1390276479Sdim : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {} 1391261991Sdim}; 1392276479Sdim} // namespace 1393276479Sdim 1394276479Sdimvoid Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { 1395276479Sdim switch (DKind) { 1396276479Sdim case OMPD_parallel: { 1397276479Sdim QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); 1398296417Sdim QualType KmpInt32PtrTy = 1399296417Sdim Context.getPointerType(KmpInt32Ty).withConst().withRestrict(); 1400276479Sdim Sema::CapturedParamNameType Params[] = { 1401276479Sdim std::make_pair(".global_tid.", KmpInt32PtrTy), 1402276479Sdim std::make_pair(".bound_tid.", KmpInt32PtrTy), 1403276479Sdim std::make_pair(StringRef(), QualType()) // __context with shared vars 1404276479Sdim }; 1405276479Sdim ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, 1406276479Sdim Params); 1407276479Sdim break; 1408276479Sdim } 1409276479Sdim case OMPD_simd: { 1410276479Sdim Sema::CapturedParamNameType Params[] = { 1411276479Sdim std::make_pair(StringRef(), QualType()) // __context with shared vars 1412276479Sdim }; 1413276479Sdim ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, 1414276479Sdim Params); 1415276479Sdim break; 1416276479Sdim } 1417276479Sdim case OMPD_for: { 1418276479Sdim Sema::CapturedParamNameType Params[] = { 1419276479Sdim std::make_pair(StringRef(), QualType()) // __context with shared vars 1420276479Sdim }; 1421276479Sdim ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, 1422276479Sdim Params); 1423276479Sdim break; 1424276479Sdim } 1425280031Sdim case OMPD_for_simd: { 1426280031Sdim Sema::CapturedParamNameType Params[] = { 1427280031Sdim std::make_pair(StringRef(), QualType()) // __context with shared vars 1428280031Sdim }; 1429280031Sdim ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, 1430280031Sdim Params); 1431280031Sdim break; 1432280031Sdim } 1433276479Sdim case OMPD_sections: { 1434276479Sdim Sema::CapturedParamNameType Params[] = { 1435276479Sdim std::make_pair(StringRef(), QualType()) // __context with shared vars 1436276479Sdim }; 1437276479Sdim ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, 1438276479Sdim Params); 1439276479Sdim break; 1440276479Sdim } 1441276479Sdim case OMPD_section: { 1442276479Sdim Sema::CapturedParamNameType Params[] = { 1443276479Sdim std::make_pair(StringRef(), QualType()) // __context with shared vars 1444276479Sdim }; 1445276479Sdim ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, 1446276479Sdim Params); 1447276479Sdim break; 1448276479Sdim } 1449276479Sdim case OMPD_single: { 1450276479Sdim Sema::CapturedParamNameType Params[] = { 1451276479Sdim std::make_pair(StringRef(), QualType()) // __context with shared vars 1452276479Sdim }; 1453276479Sdim ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, 1454276479Sdim Params); 1455276479Sdim break; 1456276479Sdim } 1457276479Sdim case OMPD_master: { 1458276479Sdim Sema::CapturedParamNameType Params[] = { 1459276479Sdim std::make_pair(StringRef(), QualType()) // __context with shared vars 1460276479Sdim }; 1461276479Sdim ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, 1462276479Sdim Params); 1463276479Sdim break; 1464276479Sdim } 1465276479Sdim case OMPD_critical: { 1466276479Sdim Sema::CapturedParamNameType Params[] = { 1467276479Sdim std::make_pair(StringRef(), QualType()) // __context with shared vars 1468276479Sdim }; 1469276479Sdim ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, 1470276479Sdim Params); 1471276479Sdim break; 1472276479Sdim } 1473276479Sdim case OMPD_parallel_for: { 1474276479Sdim QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); 1475296417Sdim QualType KmpInt32PtrTy = 1476296417Sdim Context.getPointerType(KmpInt32Ty).withConst().withRestrict(); 1477276479Sdim Sema::CapturedParamNameType Params[] = { 1478276479Sdim std::make_pair(".global_tid.", KmpInt32PtrTy), 1479276479Sdim std::make_pair(".bound_tid.", KmpInt32PtrTy), 1480276479Sdim std::make_pair(StringRef(), QualType()) // __context with shared vars 1481276479Sdim }; 1482276479Sdim ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, 1483276479Sdim Params); 1484276479Sdim break; 1485276479Sdim } 1486280031Sdim case OMPD_parallel_for_simd: { 1487280031Sdim QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); 1488296417Sdim QualType KmpInt32PtrTy = 1489296417Sdim Context.getPointerType(KmpInt32Ty).withConst().withRestrict(); 1490280031Sdim Sema::CapturedParamNameType Params[] = { 1491280031Sdim std::make_pair(".global_tid.", KmpInt32PtrTy), 1492280031Sdim std::make_pair(".bound_tid.", KmpInt32PtrTy), 1493280031Sdim std::make_pair(StringRef(), QualType()) // __context with shared vars 1494280031Sdim }; 1495280031Sdim ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, 1496280031Sdim Params); 1497280031Sdim break; 1498280031Sdim } 1499276479Sdim case OMPD_parallel_sections: { 1500288943Sdim QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); 1501296417Sdim QualType KmpInt32PtrTy = 1502296417Sdim Context.getPointerType(KmpInt32Ty).withConst().withRestrict(); 1503276479Sdim Sema::CapturedParamNameType Params[] = { 1504288943Sdim std::make_pair(".global_tid.", KmpInt32PtrTy), 1505288943Sdim std::make_pair(".bound_tid.", KmpInt32PtrTy), 1506276479Sdim std::make_pair(StringRef(), QualType()) // __context with shared vars 1507276479Sdim }; 1508276479Sdim ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, 1509276479Sdim Params); 1510276479Sdim break; 1511276479Sdim } 1512276479Sdim case OMPD_task: { 1513288943Sdim QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); 1514288943Sdim QualType Args[] = {Context.VoidPtrTy.withConst().withRestrict()}; 1515288943Sdim FunctionProtoType::ExtProtoInfo EPI; 1516288943Sdim EPI.Variadic = true; 1517288943Sdim QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI); 1518276479Sdim Sema::CapturedParamNameType Params[] = { 1519288943Sdim std::make_pair(".global_tid.", KmpInt32Ty), 1520288943Sdim std::make_pair(".part_id.", KmpInt32Ty), 1521288943Sdim std::make_pair(".privates.", 1522288943Sdim Context.VoidPtrTy.withConst().withRestrict()), 1523288943Sdim std::make_pair( 1524288943Sdim ".copy_fn.", 1525288943Sdim Context.getPointerType(CopyFnType).withConst().withRestrict()), 1526276479Sdim std::make_pair(StringRef(), QualType()) // __context with shared vars 1527276479Sdim }; 1528276479Sdim ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, 1529276479Sdim Params); 1530288943Sdim // Mark this captured region as inlined, because we don't use outlined 1531288943Sdim // function directly. 1532288943Sdim getCurCapturedRegion()->TheCapturedDecl->addAttr( 1533288943Sdim AlwaysInlineAttr::CreateImplicit( 1534288943Sdim Context, AlwaysInlineAttr::Keyword_forceinline, SourceRange())); 1535276479Sdim break; 1536276479Sdim } 1537280031Sdim case OMPD_ordered: { 1538276479Sdim Sema::CapturedParamNameType Params[] = { 1539276479Sdim std::make_pair(StringRef(), QualType()) // __context with shared vars 1540276479Sdim }; 1541276479Sdim ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, 1542276479Sdim Params); 1543276479Sdim break; 1544276479Sdim } 1545280031Sdim case OMPD_atomic: { 1546276479Sdim Sema::CapturedParamNameType Params[] = { 1547276479Sdim std::make_pair(StringRef(), QualType()) // __context with shared vars 1548276479Sdim }; 1549276479Sdim ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, 1550276479Sdim Params); 1551276479Sdim break; 1552276479Sdim } 1553296417Sdim case OMPD_target_data: 1554280031Sdim case OMPD_target: { 1555276479Sdim Sema::CapturedParamNameType Params[] = { 1556276479Sdim std::make_pair(StringRef(), QualType()) // __context with shared vars 1557276479Sdim }; 1558276479Sdim ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, 1559276479Sdim Params); 1560276479Sdim break; 1561276479Sdim } 1562280031Sdim case OMPD_teams: { 1563280031Sdim QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); 1564296417Sdim QualType KmpInt32PtrTy = 1565296417Sdim Context.getPointerType(KmpInt32Ty).withConst().withRestrict(); 1566276479Sdim Sema::CapturedParamNameType Params[] = { 1567280031Sdim std::make_pair(".global_tid.", KmpInt32PtrTy), 1568280031Sdim std::make_pair(".bound_tid.", KmpInt32PtrTy), 1569276479Sdim std::make_pair(StringRef(), QualType()) // __context with shared vars 1570276479Sdim }; 1571276479Sdim ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, 1572276479Sdim Params); 1573276479Sdim break; 1574276479Sdim } 1575288943Sdim case OMPD_taskgroup: { 1576288943Sdim Sema::CapturedParamNameType Params[] = { 1577288943Sdim std::make_pair(StringRef(), QualType()) // __context with shared vars 1578288943Sdim }; 1579288943Sdim ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, 1580288943Sdim Params); 1581288943Sdim break; 1582288943Sdim } 1583296417Sdim case OMPD_taskloop: { 1584296417Sdim Sema::CapturedParamNameType Params[] = { 1585296417Sdim std::make_pair(StringRef(), QualType()) // __context with shared vars 1586296417Sdim }; 1587296417Sdim ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, 1588296417Sdim Params); 1589296417Sdim break; 1590296417Sdim } 1591296417Sdim case OMPD_taskloop_simd: { 1592296417Sdim Sema::CapturedParamNameType Params[] = { 1593296417Sdim std::make_pair(StringRef(), QualType()) // __context with shared vars 1594296417Sdim }; 1595296417Sdim ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, 1596296417Sdim Params); 1597296417Sdim break; 1598296417Sdim } 1599296417Sdim case OMPD_distribute: { 1600296417Sdim Sema::CapturedParamNameType Params[] = { 1601296417Sdim std::make_pair(StringRef(), QualType()) // __context with shared vars 1602296417Sdim }; 1603296417Sdim ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, 1604296417Sdim Params); 1605296417Sdim break; 1606296417Sdim } 1607276479Sdim case OMPD_threadprivate: 1608280031Sdim case OMPD_taskyield: 1609280031Sdim case OMPD_barrier: 1610280031Sdim case OMPD_taskwait: 1611288943Sdim case OMPD_cancellation_point: 1612288943Sdim case OMPD_cancel: 1613280031Sdim case OMPD_flush: 1614276479Sdim llvm_unreachable("OpenMP Directive is not allowed"); 1615276479Sdim case OMPD_unknown: 1616276479Sdim llvm_unreachable("Unknown OpenMP directive"); 1617276479Sdim } 1618261991Sdim} 1619261991Sdim 1620288943SdimStmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S, 1621288943Sdim ArrayRef<OMPClause *> Clauses) { 1622288943Sdim if (!S.isUsable()) { 1623288943Sdim ActOnCapturedRegionError(); 1624288943Sdim return StmtError(); 1625288943Sdim } 1626296417Sdim 1627296417Sdim OMPOrderedClause *OC = nullptr; 1628296417Sdim OMPScheduleClause *SC = nullptr; 1629296417Sdim SmallVector<OMPLinearClause *, 4> LCs; 1630288943Sdim // This is required for proper codegen. 1631288943Sdim for (auto *Clause : Clauses) { 1632288943Sdim if (isOpenMPPrivate(Clause->getClauseKind()) || 1633288943Sdim Clause->getClauseKind() == OMPC_copyprivate || 1634288943Sdim (getLangOpts().OpenMPUseTLS && 1635288943Sdim getASTContext().getTargetInfo().isTLSSupported() && 1636288943Sdim Clause->getClauseKind() == OMPC_copyin)) { 1637288943Sdim DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin); 1638288943Sdim // Mark all variables in private list clauses as used in inner region. 1639288943Sdim for (auto *VarRef : Clause->children()) { 1640288943Sdim if (auto *E = cast_or_null<Expr>(VarRef)) { 1641288943Sdim MarkDeclarationsReferencedInExpr(E); 1642288943Sdim } 1643288943Sdim } 1644288943Sdim DSAStack->setForceVarCapturing(/*V=*/false); 1645288943Sdim } else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective()) && 1646288943Sdim Clause->getClauseKind() == OMPC_schedule) { 1647288943Sdim // Mark all variables in private list clauses as used in inner region. 1648288943Sdim // Required for proper codegen of combined directives. 1649288943Sdim // TODO: add processing for other clauses. 1650288943Sdim if (auto *E = cast_or_null<Expr>( 1651296417Sdim cast<OMPScheduleClause>(Clause)->getHelperChunkSize())) 1652296417Sdim MarkDeclarationsReferencedInExpr(E); 1653288943Sdim } 1654296417Sdim if (Clause->getClauseKind() == OMPC_schedule) 1655296417Sdim SC = cast<OMPScheduleClause>(Clause); 1656296417Sdim else if (Clause->getClauseKind() == OMPC_ordered) 1657296417Sdim OC = cast<OMPOrderedClause>(Clause); 1658296417Sdim else if (Clause->getClauseKind() == OMPC_linear) 1659296417Sdim LCs.push_back(cast<OMPLinearClause>(Clause)); 1660288943Sdim } 1661296417Sdim bool ErrorFound = false; 1662296417Sdim // OpenMP, 2.7.1 Loop Construct, Restrictions 1663296417Sdim // The nonmonotonic modifier cannot be specified if an ordered clause is 1664296417Sdim // specified. 1665296417Sdim if (SC && 1666296417Sdim (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic || 1667296417Sdim SC->getSecondScheduleModifier() == 1668296417Sdim OMPC_SCHEDULE_MODIFIER_nonmonotonic) && 1669296417Sdim OC) { 1670296417Sdim Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic 1671296417Sdim ? SC->getFirstScheduleModifierLoc() 1672296417Sdim : SC->getSecondScheduleModifierLoc(), 1673296417Sdim diag::err_omp_schedule_nonmonotonic_ordered) 1674296417Sdim << SourceRange(OC->getLocStart(), OC->getLocEnd()); 1675296417Sdim ErrorFound = true; 1676296417Sdim } 1677296417Sdim if (!LCs.empty() && OC && OC->getNumForLoops()) { 1678296417Sdim for (auto *C : LCs) { 1679296417Sdim Diag(C->getLocStart(), diag::err_omp_linear_ordered) 1680296417Sdim << SourceRange(OC->getLocStart(), OC->getLocEnd()); 1681296417Sdim } 1682296417Sdim ErrorFound = true; 1683296417Sdim } 1684296417Sdim if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) && 1685296417Sdim isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC && 1686296417Sdim OC->getNumForLoops()) { 1687296417Sdim Diag(OC->getLocStart(), diag::err_omp_ordered_simd) 1688296417Sdim << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); 1689296417Sdim ErrorFound = true; 1690296417Sdim } 1691296417Sdim if (ErrorFound) { 1692296417Sdim ActOnCapturedRegionError(); 1693296417Sdim return StmtError(); 1694296417Sdim } 1695288943Sdim return ActOnCapturedRegionEnd(S.get()); 1696288943Sdim} 1697288943Sdim 1698276479Sdimstatic bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, 1699276479Sdim OpenMPDirectiveKind CurrentRegion, 1700276479Sdim const DeclarationNameInfo &CurrentName, 1701288943Sdim OpenMPDirectiveKind CancelRegion, 1702276479Sdim SourceLocation StartLoc) { 1703276479Sdim // Allowed nesting of constructs 1704276479Sdim // +------------------+-----------------+------------------------------------+ 1705276479Sdim // | Parent directive | Child directive | Closely (!), No-Closely(+), Both(*)| 1706276479Sdim // +------------------+-----------------+------------------------------------+ 1707276479Sdim // | parallel | parallel | * | 1708276479Sdim // | parallel | for | * | 1709280031Sdim // | parallel | for simd | * | 1710276479Sdim // | parallel | master | * | 1711276479Sdim // | parallel | critical | * | 1712276479Sdim // | parallel | simd | * | 1713276479Sdim // | parallel | sections | * | 1714276479Sdim // | parallel | section | + | 1715276479Sdim // | parallel | single | * | 1716276479Sdim // | parallel | parallel for | * | 1717280031Sdim // | parallel |parallel for simd| * | 1718276479Sdim // | parallel |parallel sections| * | 1719276479Sdim // | parallel | task | * | 1720276479Sdim // | parallel | taskyield | * | 1721276479Sdim // | parallel | barrier | * | 1722276479Sdim // | parallel | taskwait | * | 1723288943Sdim // | parallel | taskgroup | * | 1724276479Sdim // | parallel | flush | * | 1725280031Sdim // | parallel | ordered | + | 1726280031Sdim // | parallel | atomic | * | 1727280031Sdim // | parallel | target | * | 1728280031Sdim // | parallel | teams | + | 1729288943Sdim // | parallel | cancellation | | 1730288943Sdim // | | point | ! | 1731288943Sdim // | parallel | cancel | ! | 1732296417Sdim // | parallel | taskloop | * | 1733296417Sdim // | parallel | taskloop simd | * | 1734296417Sdim // | parallel | distribute | | 1735276479Sdim // +------------------+-----------------+------------------------------------+ 1736276479Sdim // | for | parallel | * | 1737276479Sdim // | for | for | + | 1738280031Sdim // | for | for simd | + | 1739276479Sdim // | for | master | + | 1740276479Sdim // | for | critical | * | 1741276479Sdim // | for | simd | * | 1742276479Sdim // | for | sections | + | 1743276479Sdim // | for | section | + | 1744276479Sdim // | for | single | + | 1745276479Sdim // | for | parallel for | * | 1746280031Sdim // | for |parallel for simd| * | 1747276479Sdim // | for |parallel sections| * | 1748276479Sdim // | for | task | * | 1749276479Sdim // | for | taskyield | * | 1750276479Sdim // | for | barrier | + | 1751276479Sdim // | for | taskwait | * | 1752288943Sdim // | for | taskgroup | * | 1753276479Sdim // | for | flush | * | 1754280031Sdim // | for | ordered | * (if construct is ordered) | 1755280031Sdim // | for | atomic | * | 1756280031Sdim // | for | target | * | 1757280031Sdim // | for | teams | + | 1758288943Sdim // | for | cancellation | | 1759288943Sdim // | | point | ! | 1760288943Sdim // | for | cancel | ! | 1761296417Sdim // | for | taskloop | * | 1762296417Sdim // | for | taskloop simd | * | 1763296417Sdim // | for | distribute | | 1764276479Sdim // +------------------+-----------------+------------------------------------+ 1765276479Sdim // | master | parallel | * | 1766276479Sdim // | master | for | + | 1767280031Sdim // | master | for simd | + | 1768276479Sdim // | master | master | * | 1769276479Sdim // | master | critical | * | 1770276479Sdim // | master | simd | * | 1771276479Sdim // | master | sections | + | 1772276479Sdim // | master | section | + | 1773276479Sdim // | master | single | + | 1774276479Sdim // | master | parallel for | * | 1775280031Sdim // | master |parallel for simd| * | 1776276479Sdim // | master |parallel sections| * | 1777276479Sdim // | master | task | * | 1778276479Sdim // | master | taskyield | * | 1779276479Sdim // | master | barrier | + | 1780276479Sdim // | master | taskwait | * | 1781288943Sdim // | master | taskgroup | * | 1782276479Sdim // | master | flush | * | 1783280031Sdim // | master | ordered | + | 1784280031Sdim // | master | atomic | * | 1785280031Sdim // | master | target | * | 1786280031Sdim // | master | teams | + | 1787288943Sdim // | master | cancellation | | 1788288943Sdim // | | point | | 1789288943Sdim // | master | cancel | | 1790296417Sdim // | master | taskloop | * | 1791296417Sdim // | master | taskloop simd | * | 1792296417Sdim // | master | distribute | | 1793276479Sdim // +------------------+-----------------+------------------------------------+ 1794276479Sdim // | critical | parallel | * | 1795276479Sdim // | critical | for | + | 1796280031Sdim // | critical | for simd | + | 1797276479Sdim // | critical | master | * | 1798280031Sdim // | critical | critical | * (should have different names) | 1799276479Sdim // | critical | simd | * | 1800276479Sdim // | critical | sections | + | 1801276479Sdim // | critical | section | + | 1802276479Sdim // | critical | single | + | 1803276479Sdim // | critical | parallel for | * | 1804280031Sdim // | critical |parallel for simd| * | 1805276479Sdim // | critical |parallel sections| * | 1806276479Sdim // | critical | task | * | 1807276479Sdim // | critical | taskyield | * | 1808276479Sdim // | critical | barrier | + | 1809276479Sdim // | critical | taskwait | * | 1810288943Sdim // | critical | taskgroup | * | 1811280031Sdim // | critical | ordered | + | 1812280031Sdim // | critical | atomic | * | 1813280031Sdim // | critical | target | * | 1814280031Sdim // | critical | teams | + | 1815288943Sdim // | critical | cancellation | | 1816288943Sdim // | | point | | 1817288943Sdim // | critical | cancel | | 1818296417Sdim // | critical | taskloop | * | 1819296417Sdim // | critical | taskloop simd | * | 1820296417Sdim // | critical | distribute | | 1821276479Sdim // +------------------+-----------------+------------------------------------+ 1822276479Sdim // | simd | parallel | | 1823276479Sdim // | simd | for | | 1824280031Sdim // | simd | for simd | | 1825276479Sdim // | simd | master | | 1826276479Sdim // | simd | critical | | 1827276479Sdim // | simd | simd | | 1828276479Sdim // | simd | sections | | 1829276479Sdim // | simd | section | | 1830276479Sdim // | simd | single | | 1831276479Sdim // | simd | parallel for | | 1832280031Sdim // | simd |parallel for simd| | 1833276479Sdim // | simd |parallel sections| | 1834276479Sdim // | simd | task | | 1835276479Sdim // | simd | taskyield | | 1836276479Sdim // | simd | barrier | | 1837276479Sdim // | simd | taskwait | | 1838288943Sdim // | simd | taskgroup | | 1839276479Sdim // | simd | flush | | 1840296417Sdim // | simd | ordered | + (with simd clause) | 1841280031Sdim // | simd | atomic | | 1842280031Sdim // | simd | target | | 1843280031Sdim // | simd | teams | | 1844288943Sdim // | simd | cancellation | | 1845288943Sdim // | | point | | 1846288943Sdim // | simd | cancel | | 1847296417Sdim // | simd | taskloop | | 1848296417Sdim // | simd | taskloop simd | | 1849296417Sdim // | simd | distribute | | 1850276479Sdim // +------------------+-----------------+------------------------------------+ 1851280031Sdim // | for simd | parallel | | 1852280031Sdim // | for simd | for | | 1853280031Sdim // | for simd | for simd | | 1854280031Sdim // | for simd | master | | 1855280031Sdim // | for simd | critical | | 1856280031Sdim // | for simd | simd | | 1857280031Sdim // | for simd | sections | | 1858280031Sdim // | for simd | section | | 1859280031Sdim // | for simd | single | | 1860280031Sdim // | for simd | parallel for | | 1861280031Sdim // | for simd |parallel for simd| | 1862280031Sdim // | for simd |parallel sections| | 1863280031Sdim // | for simd | task | | 1864280031Sdim // | for simd | taskyield | | 1865280031Sdim // | for simd | barrier | | 1866280031Sdim // | for simd | taskwait | | 1867288943Sdim // | for simd | taskgroup | | 1868280031Sdim // | for simd | flush | | 1869296417Sdim // | for simd | ordered | + (with simd clause) | 1870280031Sdim // | for simd | atomic | | 1871280031Sdim // | for simd | target | | 1872280031Sdim // | for simd | teams | | 1873288943Sdim // | for simd | cancellation | | 1874288943Sdim // | | point | | 1875288943Sdim // | for simd | cancel | | 1876296417Sdim // | for simd | taskloop | | 1877296417Sdim // | for simd | taskloop simd | | 1878296417Sdim // | for simd | distribute | | 1879280031Sdim // +------------------+-----------------+------------------------------------+ 1880280031Sdim // | parallel for simd| parallel | | 1881280031Sdim // | parallel for simd| for | | 1882280031Sdim // | parallel for simd| for simd | | 1883280031Sdim // | parallel for simd| master | | 1884280031Sdim // | parallel for simd| critical | | 1885280031Sdim // | parallel for simd| simd | | 1886280031Sdim // | parallel for simd| sections | | 1887280031Sdim // | parallel for simd| section | | 1888280031Sdim // | parallel for simd| single | | 1889280031Sdim // | parallel for simd| parallel for | | 1890280031Sdim // | parallel for simd|parallel for simd| | 1891280031Sdim // | parallel for simd|parallel sections| | 1892280031Sdim // | parallel for simd| task | | 1893280031Sdim // | parallel for simd| taskyield | | 1894280031Sdim // | parallel for simd| barrier | | 1895280031Sdim // | parallel for simd| taskwait | | 1896288943Sdim // | parallel for simd| taskgroup | | 1897280031Sdim // | parallel for simd| flush | | 1898296417Sdim // | parallel for simd| ordered | + (with simd clause) | 1899280031Sdim // | parallel for simd| atomic | | 1900280031Sdim // | parallel for simd| target | | 1901280031Sdim // | parallel for simd| teams | | 1902288943Sdim // | parallel for simd| cancellation | | 1903288943Sdim // | | point | | 1904288943Sdim // | parallel for simd| cancel | | 1905296417Sdim // | parallel for simd| taskloop | | 1906296417Sdim // | parallel for simd| taskloop simd | | 1907296417Sdim // | parallel for simd| distribute | | 1908280031Sdim // +------------------+-----------------+------------------------------------+ 1909276479Sdim // | sections | parallel | * | 1910276479Sdim // | sections | for | + | 1911280031Sdim // | sections | for simd | + | 1912276479Sdim // | sections | master | + | 1913276479Sdim // | sections | critical | * | 1914276479Sdim // | sections | simd | * | 1915276479Sdim // | sections | sections | + | 1916276479Sdim // | sections | section | * | 1917276479Sdim // | sections | single | + | 1918276479Sdim // | sections | parallel for | * | 1919280031Sdim // | sections |parallel for simd| * | 1920276479Sdim // | sections |parallel sections| * | 1921276479Sdim // | sections | task | * | 1922276479Sdim // | sections | taskyield | * | 1923276479Sdim // | sections | barrier | + | 1924276479Sdim // | sections | taskwait | * | 1925288943Sdim // | sections | taskgroup | * | 1926276479Sdim // | sections | flush | * | 1927280031Sdim // | sections | ordered | + | 1928280031Sdim // | sections | atomic | * | 1929280031Sdim // | sections | target | * | 1930280031Sdim // | sections | teams | + | 1931288943Sdim // | sections | cancellation | | 1932288943Sdim // | | point | ! | 1933288943Sdim // | sections | cancel | ! | 1934296417Sdim // | sections | taskloop | * | 1935296417Sdim // | sections | taskloop simd | * | 1936296417Sdim // | sections | distribute | | 1937276479Sdim // +------------------+-----------------+------------------------------------+ 1938276479Sdim // | section | parallel | * | 1939276479Sdim // | section | for | + | 1940280031Sdim // | section | for simd | + | 1941276479Sdim // | section | master | + | 1942276479Sdim // | section | critical | * | 1943276479Sdim // | section | simd | * | 1944276479Sdim // | section | sections | + | 1945276479Sdim // | section | section | + | 1946276479Sdim // | section | single | + | 1947276479Sdim // | section | parallel for | * | 1948280031Sdim // | section |parallel for simd| * | 1949276479Sdim // | section |parallel sections| * | 1950276479Sdim // | section | task | * | 1951276479Sdim // | section | taskyield | * | 1952276479Sdim // | section | barrier | + | 1953276479Sdim // | section | taskwait | * | 1954288943Sdim // | section | taskgroup | * | 1955276479Sdim // | section | flush | * | 1956280031Sdim // | section | ordered | + | 1957280031Sdim // | section | atomic | * | 1958280031Sdim // | section | target | * | 1959280031Sdim // | section | teams | + | 1960288943Sdim // | section | cancellation | | 1961288943Sdim // | | point | ! | 1962288943Sdim // | section | cancel | ! | 1963296417Sdim // | section | taskloop | * | 1964296417Sdim // | section | taskloop simd | * | 1965296417Sdim // | section | distribute | | 1966276479Sdim // +------------------+-----------------+------------------------------------+ 1967276479Sdim // | single | parallel | * | 1968276479Sdim // | single | for | + | 1969280031Sdim // | single | for simd | + | 1970276479Sdim // | single | master | + | 1971276479Sdim // | single | critical | * | 1972276479Sdim // | single | simd | * | 1973276479Sdim // | single | sections | + | 1974276479Sdim // | single | section | + | 1975276479Sdim // | single | single | + | 1976276479Sdim // | single | parallel for | * | 1977280031Sdim // | single |parallel for simd| * | 1978276479Sdim // | single |parallel sections| * | 1979276479Sdim // | single | task | * | 1980276479Sdim // | single | taskyield | * | 1981276479Sdim // | single | barrier | + | 1982276479Sdim // | single | taskwait | * | 1983288943Sdim // | single | taskgroup | * | 1984276479Sdim // | single | flush | * | 1985280031Sdim // | single | ordered | + | 1986280031Sdim // | single | atomic | * | 1987280031Sdim // | single | target | * | 1988280031Sdim // | single | teams | + | 1989288943Sdim // | single | cancellation | | 1990288943Sdim // | | point | | 1991288943Sdim // | single | cancel | | 1992296417Sdim // | single | taskloop | * | 1993296417Sdim // | single | taskloop simd | * | 1994296417Sdim // | single | distribute | | 1995276479Sdim // +------------------+-----------------+------------------------------------+ 1996276479Sdim // | parallel for | parallel | * | 1997276479Sdim // | parallel for | for | + | 1998280031Sdim // | parallel for | for simd | + | 1999276479Sdim // | parallel for | master | + | 2000276479Sdim // | parallel for | critical | * | 2001276479Sdim // | parallel for | simd | * | 2002276479Sdim // | parallel for | sections | + | 2003276479Sdim // | parallel for | section | + | 2004276479Sdim // | parallel for | single | + | 2005276479Sdim // | parallel for | parallel for | * | 2006280031Sdim // | parallel for |parallel for simd| * | 2007276479Sdim // | parallel for |parallel sections| * | 2008276479Sdim // | parallel for | task | * | 2009276479Sdim // | parallel for | taskyield | * | 2010276479Sdim // | parallel for | barrier | + | 2011276479Sdim // | parallel for | taskwait | * | 2012288943Sdim // | parallel for | taskgroup | * | 2013276479Sdim // | parallel for | flush | * | 2014280031Sdim // | parallel for | ordered | * (if construct is ordered) | 2015280031Sdim // | parallel for | atomic | * | 2016280031Sdim // | parallel for | target | * | 2017280031Sdim // | parallel for | teams | + | 2018288943Sdim // | parallel for | cancellation | | 2019288943Sdim // | | point | ! | 2020288943Sdim // | parallel for | cancel | ! | 2021296417Sdim // | parallel for | taskloop | * | 2022296417Sdim // | parallel for | taskloop simd | * | 2023296417Sdim // | parallel for | distribute | | 2024276479Sdim // +------------------+-----------------+------------------------------------+ 2025276479Sdim // | parallel sections| parallel | * | 2026276479Sdim // | parallel sections| for | + | 2027280031Sdim // | parallel sections| for simd | + | 2028276479Sdim // | parallel sections| master | + | 2029276479Sdim // | parallel sections| critical | + | 2030276479Sdim // | parallel sections| simd | * | 2031276479Sdim // | parallel sections| sections | + | 2032276479Sdim // | parallel sections| section | * | 2033276479Sdim // | parallel sections| single | + | 2034276479Sdim // | parallel sections| parallel for | * | 2035280031Sdim // | parallel sections|parallel for simd| * | 2036276479Sdim // | parallel sections|parallel sections| * | 2037276479Sdim // | parallel sections| task | * | 2038276479Sdim // | parallel sections| taskyield | * | 2039276479Sdim // | parallel sections| barrier | + | 2040276479Sdim // | parallel sections| taskwait | * | 2041288943Sdim // | parallel sections| taskgroup | * | 2042276479Sdim // | parallel sections| flush | * | 2043280031Sdim // | parallel sections| ordered | + | 2044280031Sdim // | parallel sections| atomic | * | 2045280031Sdim // | parallel sections| target | * | 2046280031Sdim // | parallel sections| teams | + | 2047288943Sdim // | parallel sections| cancellation | | 2048288943Sdim // | | point | ! | 2049288943Sdim // | parallel sections| cancel | ! | 2050296417Sdim // | parallel sections| taskloop | * | 2051296417Sdim // | parallel sections| taskloop simd | * | 2052296417Sdim // | parallel sections| distribute | | 2053276479Sdim // +------------------+-----------------+------------------------------------+ 2054276479Sdim // | task | parallel | * | 2055276479Sdim // | task | for | + | 2056280031Sdim // | task | for simd | + | 2057276479Sdim // | task | master | + | 2058276479Sdim // | task | critical | * | 2059276479Sdim // | task | simd | * | 2060276479Sdim // | task | sections | + | 2061276479Sdim // | task | section | + | 2062276479Sdim // | task | single | + | 2063276479Sdim // | task | parallel for | * | 2064280031Sdim // | task |parallel for simd| * | 2065276479Sdim // | task |parallel sections| * | 2066276479Sdim // | task | task | * | 2067276479Sdim // | task | taskyield | * | 2068276479Sdim // | task | barrier | + | 2069276479Sdim // | task | taskwait | * | 2070288943Sdim // | task | taskgroup | * | 2071276479Sdim // | task | flush | * | 2072280031Sdim // | task | ordered | + | 2073280031Sdim // | task | atomic | * | 2074280031Sdim // | task | target | * | 2075280031Sdim // | task | teams | + | 2076288943Sdim // | task | cancellation | | 2077288943Sdim // | | point | ! | 2078288943Sdim // | task | cancel | ! | 2079296417Sdim // | task | taskloop | * | 2080296417Sdim // | task | taskloop simd | * | 2081296417Sdim // | task | distribute | | 2082276479Sdim // +------------------+-----------------+------------------------------------+ 2083280031Sdim // | ordered | parallel | * | 2084280031Sdim // | ordered | for | + | 2085280031Sdim // | ordered | for simd | + | 2086280031Sdim // | ordered | master | * | 2087280031Sdim // | ordered | critical | * | 2088280031Sdim // | ordered | simd | * | 2089280031Sdim // | ordered | sections | + | 2090280031Sdim // | ordered | section | + | 2091280031Sdim // | ordered | single | + | 2092280031Sdim // | ordered | parallel for | * | 2093280031Sdim // | ordered |parallel for simd| * | 2094280031Sdim // | ordered |parallel sections| * | 2095280031Sdim // | ordered | task | * | 2096280031Sdim // | ordered | taskyield | * | 2097280031Sdim // | ordered | barrier | + | 2098280031Sdim // | ordered | taskwait | * | 2099288943Sdim // | ordered | taskgroup | * | 2100280031Sdim // | ordered | flush | * | 2101280031Sdim // | ordered | ordered | + | 2102280031Sdim // | ordered | atomic | * | 2103280031Sdim // | ordered | target | * | 2104280031Sdim // | ordered | teams | + | 2105288943Sdim // | ordered | cancellation | | 2106288943Sdim // | | point | | 2107288943Sdim // | ordered | cancel | | 2108296417Sdim // | ordered | taskloop | * | 2109296417Sdim // | ordered | taskloop simd | * | 2110296417Sdim // | ordered | distribute | | 2111280031Sdim // +------------------+-----------------+------------------------------------+ 2112280031Sdim // | atomic | parallel | | 2113280031Sdim // | atomic | for | | 2114280031Sdim // | atomic | for simd | | 2115280031Sdim // | atomic | master | | 2116280031Sdim // | atomic | critical | | 2117280031Sdim // | atomic | simd | | 2118280031Sdim // | atomic | sections | | 2119280031Sdim // | atomic | section | | 2120280031Sdim // | atomic | single | | 2121280031Sdim // | atomic | parallel for | | 2122280031Sdim // | atomic |parallel for simd| | 2123280031Sdim // | atomic |parallel sections| | 2124280031Sdim // | atomic | task | | 2125280031Sdim // | atomic | taskyield | | 2126280031Sdim // | atomic | barrier | | 2127280031Sdim // | atomic | taskwait | | 2128288943Sdim // | atomic | taskgroup | | 2129280031Sdim // | atomic | flush | | 2130280031Sdim // | atomic | ordered | | 2131280031Sdim // | atomic | atomic | | 2132280031Sdim // | atomic | target | | 2133280031Sdim // | atomic | teams | | 2134288943Sdim // | atomic | cancellation | | 2135288943Sdim // | | point | | 2136288943Sdim // | atomic | cancel | | 2137296417Sdim // | atomic | taskloop | | 2138296417Sdim // | atomic | taskloop simd | | 2139296417Sdim // | atomic | distribute | | 2140280031Sdim // +------------------+-----------------+------------------------------------+ 2141280031Sdim // | target | parallel | * | 2142280031Sdim // | target | for | * | 2143280031Sdim // | target | for simd | * | 2144280031Sdim // | target | master | * | 2145280031Sdim // | target | critical | * | 2146280031Sdim // | target | simd | * | 2147280031Sdim // | target | sections | * | 2148280031Sdim // | target | section | * | 2149280031Sdim // | target | single | * | 2150280031Sdim // | target | parallel for | * | 2151280031Sdim // | target |parallel for simd| * | 2152280031Sdim // | target |parallel sections| * | 2153280031Sdim // | target | task | * | 2154280031Sdim // | target | taskyield | * | 2155280031Sdim // | target | barrier | * | 2156280031Sdim // | target | taskwait | * | 2157288943Sdim // | target | taskgroup | * | 2158280031Sdim // | target | flush | * | 2159280031Sdim // | target | ordered | * | 2160280031Sdim // | target | atomic | * | 2161280031Sdim // | target | target | * | 2162280031Sdim // | target | teams | * | 2163288943Sdim // | target | cancellation | | 2164288943Sdim // | | point | | 2165288943Sdim // | target | cancel | | 2166296417Sdim // | target | taskloop | * | 2167296417Sdim // | target | taskloop simd | * | 2168296417Sdim // | target | distribute | | 2169280031Sdim // +------------------+-----------------+------------------------------------+ 2170280031Sdim // | teams | parallel | * | 2171280031Sdim // | teams | for | + | 2172280031Sdim // | teams | for simd | + | 2173280031Sdim // | teams | master | + | 2174280031Sdim // | teams | critical | + | 2175280031Sdim // | teams | simd | + | 2176280031Sdim // | teams | sections | + | 2177280031Sdim // | teams | section | + | 2178280031Sdim // | teams | single | + | 2179280031Sdim // | teams | parallel for | * | 2180280031Sdim // | teams |parallel for simd| * | 2181280031Sdim // | teams |parallel sections| * | 2182280031Sdim // | teams | task | + | 2183280031Sdim // | teams | taskyield | + | 2184280031Sdim // | teams | barrier | + | 2185280031Sdim // | teams | taskwait | + | 2186288943Sdim // | teams | taskgroup | + | 2187280031Sdim // | teams | flush | + | 2188280031Sdim // | teams | ordered | + | 2189280031Sdim // | teams | atomic | + | 2190280031Sdim // | teams | target | + | 2191280031Sdim // | teams | teams | + | 2192288943Sdim // | teams | cancellation | | 2193288943Sdim // | | point | | 2194288943Sdim // | teams | cancel | | 2195296417Sdim // | teams | taskloop | + | 2196296417Sdim // | teams | taskloop simd | + | 2197296417Sdim // | teams | distribute | ! | 2198280031Sdim // +------------------+-----------------+------------------------------------+ 2199296417Sdim // | taskloop | parallel | * | 2200296417Sdim // | taskloop | for | + | 2201296417Sdim // | taskloop | for simd | + | 2202296417Sdim // | taskloop | master | + | 2203296417Sdim // | taskloop | critical | * | 2204296417Sdim // | taskloop | simd | * | 2205296417Sdim // | taskloop | sections | + | 2206296417Sdim // | taskloop | section | + | 2207296417Sdim // | taskloop | single | + | 2208296417Sdim // | taskloop | parallel for | * | 2209296417Sdim // | taskloop |parallel for simd| * | 2210296417Sdim // | taskloop |parallel sections| * | 2211296417Sdim // | taskloop | task | * | 2212296417Sdim // | taskloop | taskyield | * | 2213296417Sdim // | taskloop | barrier | + | 2214296417Sdim // | taskloop | taskwait | * | 2215296417Sdim // | taskloop | taskgroup | * | 2216296417Sdim // | taskloop | flush | * | 2217296417Sdim // | taskloop | ordered | + | 2218296417Sdim // | taskloop | atomic | * | 2219296417Sdim // | taskloop | target | * | 2220296417Sdim // | taskloop | teams | + | 2221296417Sdim // | taskloop | cancellation | | 2222296417Sdim // | | point | | 2223296417Sdim // | taskloop | cancel | | 2224296417Sdim // | taskloop | taskloop | * | 2225296417Sdim // | taskloop | distribute | | 2226296417Sdim // +------------------+-----------------+------------------------------------+ 2227296417Sdim // | taskloop simd | parallel | | 2228296417Sdim // | taskloop simd | for | | 2229296417Sdim // | taskloop simd | for simd | | 2230296417Sdim // | taskloop simd | master | | 2231296417Sdim // | taskloop simd | critical | | 2232296417Sdim // | taskloop simd | simd | | 2233296417Sdim // | taskloop simd | sections | | 2234296417Sdim // | taskloop simd | section | | 2235296417Sdim // | taskloop simd | single | | 2236296417Sdim // | taskloop simd | parallel for | | 2237296417Sdim // | taskloop simd |parallel for simd| | 2238296417Sdim // | taskloop simd |parallel sections| | 2239296417Sdim // | taskloop simd | task | | 2240296417Sdim // | taskloop simd | taskyield | | 2241296417Sdim // | taskloop simd | barrier | | 2242296417Sdim // | taskloop simd | taskwait | | 2243296417Sdim // | taskloop simd | taskgroup | | 2244296417Sdim // | taskloop simd | flush | | 2245296417Sdim // | taskloop simd | ordered | + (with simd clause) | 2246296417Sdim // | taskloop simd | atomic | | 2247296417Sdim // | taskloop simd | target | | 2248296417Sdim // | taskloop simd | teams | | 2249296417Sdim // | taskloop simd | cancellation | | 2250296417Sdim // | | point | | 2251296417Sdim // | taskloop simd | cancel | | 2252296417Sdim // | taskloop simd | taskloop | | 2253296417Sdim // | taskloop simd | taskloop simd | | 2254296417Sdim // | taskloop simd | distribute | | 2255296417Sdim // +------------------+-----------------+------------------------------------+ 2256296417Sdim // | distribute | parallel | * | 2257296417Sdim // | distribute | for | * | 2258296417Sdim // | distribute | for simd | * | 2259296417Sdim // | distribute | master | * | 2260296417Sdim // | distribute | critical | * | 2261296417Sdim // | distribute | simd | * | 2262296417Sdim // | distribute | sections | * | 2263296417Sdim // | distribute | section | * | 2264296417Sdim // | distribute | single | * | 2265296417Sdim // | distribute | parallel for | * | 2266296417Sdim // | distribute |parallel for simd| * | 2267296417Sdim // | distribute |parallel sections| * | 2268296417Sdim // | distribute | task | * | 2269296417Sdim // | distribute | taskyield | * | 2270296417Sdim // | distribute | barrier | * | 2271296417Sdim // | distribute | taskwait | * | 2272296417Sdim // | distribute | taskgroup | * | 2273296417Sdim // | distribute | flush | * | 2274296417Sdim // | distribute | ordered | + | 2275296417Sdim // | distribute | atomic | * | 2276296417Sdim // | distribute | target | | 2277296417Sdim // | distribute | teams | | 2278296417Sdim // | distribute | cancellation | + | 2279296417Sdim // | | point | | 2280296417Sdim // | distribute | cancel | + | 2281296417Sdim // | distribute | taskloop | * | 2282296417Sdim // | distribute | taskloop simd | * | 2283296417Sdim // | distribute | distribute | | 2284296417Sdim // +------------------+-----------------+------------------------------------+ 2285276479Sdim if (Stack->getCurScope()) { 2286276479Sdim auto ParentRegion = Stack->getParentDirective(); 2287276479Sdim bool NestingProhibited = false; 2288276479Sdim bool CloseNesting = true; 2289280031Sdim enum { 2290280031Sdim NoRecommend, 2291280031Sdim ShouldBeInParallelRegion, 2292280031Sdim ShouldBeInOrderedRegion, 2293296417Sdim ShouldBeInTargetRegion, 2294296417Sdim ShouldBeInTeamsRegion 2295280031Sdim } Recommend = NoRecommend; 2296296417Sdim if (isOpenMPSimdDirective(ParentRegion) && CurrentRegion != OMPD_ordered) { 2297276479Sdim // OpenMP [2.16, Nesting of Regions] 2298276479Sdim // OpenMP constructs may not be nested inside a simd region. 2299296417Sdim // OpenMP [2.8.1,simd Construct, Restrictions] 2300296417Sdim // An ordered construct with the simd clause is the only OpenMP construct 2301296417Sdim // that can appear in the simd region. 2302276479Sdim SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_simd); 2303276479Sdim return true; 2304276479Sdim } 2305280031Sdim if (ParentRegion == OMPD_atomic) { 2306280031Sdim // OpenMP [2.16, Nesting of Regions] 2307280031Sdim // OpenMP constructs may not be nested inside an atomic region. 2308280031Sdim SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic); 2309280031Sdim return true; 2310280031Sdim } 2311276479Sdim if (CurrentRegion == OMPD_section) { 2312276479Sdim // OpenMP [2.7.2, sections Construct, Restrictions] 2313276479Sdim // Orphaned section directives are prohibited. That is, the section 2314276479Sdim // directives must appear within the sections construct and must not be 2315276479Sdim // encountered elsewhere in the sections region. 2316276479Sdim if (ParentRegion != OMPD_sections && 2317276479Sdim ParentRegion != OMPD_parallel_sections) { 2318276479Sdim SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive) 2319276479Sdim << (ParentRegion != OMPD_unknown) 2320276479Sdim << getOpenMPDirectiveName(ParentRegion); 2321276479Sdim return true; 2322276479Sdim } 2323276479Sdim return false; 2324276479Sdim } 2325280031Sdim // Allow some constructs to be orphaned (they could be used in functions, 2326280031Sdim // called from OpenMP regions with the required preconditions). 2327280031Sdim if (ParentRegion == OMPD_unknown) 2328280031Sdim return false; 2329288943Sdim if (CurrentRegion == OMPD_cancellation_point || 2330288943Sdim CurrentRegion == OMPD_cancel) { 2331276479Sdim // OpenMP [2.16, Nesting of Regions] 2332288943Sdim // A cancellation point construct for which construct-type-clause is 2333288943Sdim // taskgroup must be nested inside a task construct. A cancellation 2334288943Sdim // point construct for which construct-type-clause is not taskgroup must 2335288943Sdim // be closely nested inside an OpenMP construct that matches the type 2336288943Sdim // specified in construct-type-clause. 2337288943Sdim // A cancel construct for which construct-type-clause is taskgroup must be 2338288943Sdim // nested inside a task construct. A cancel construct for which 2339288943Sdim // construct-type-clause is not taskgroup must be closely nested inside an 2340288943Sdim // OpenMP construct that matches the type specified in 2341288943Sdim // construct-type-clause. 2342288943Sdim NestingProhibited = 2343288943Sdim !((CancelRegion == OMPD_parallel && ParentRegion == OMPD_parallel) || 2344296417Sdim (CancelRegion == OMPD_for && 2345296417Sdim (ParentRegion == OMPD_for || ParentRegion == OMPD_parallel_for)) || 2346288943Sdim (CancelRegion == OMPD_taskgroup && ParentRegion == OMPD_task) || 2347288943Sdim (CancelRegion == OMPD_sections && 2348296417Sdim (ParentRegion == OMPD_section || ParentRegion == OMPD_sections || 2349296417Sdim ParentRegion == OMPD_parallel_sections))); 2350288943Sdim } else if (CurrentRegion == OMPD_master) { 2351288943Sdim // OpenMP [2.16, Nesting of Regions] 2352276479Sdim // A master region may not be closely nested inside a worksharing, 2353280031Sdim // atomic, or explicit task region. 2354276479Sdim NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) || 2355296417Sdim ParentRegion == OMPD_task || 2356296417Sdim isOpenMPTaskLoopDirective(ParentRegion); 2357276479Sdim } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) { 2358276479Sdim // OpenMP [2.16, Nesting of Regions] 2359276479Sdim // A critical region may not be nested (closely or otherwise) inside a 2360276479Sdim // critical region with the same name. Note that this restriction is not 2361276479Sdim // sufficient to prevent deadlock. 2362276479Sdim SourceLocation PreviousCriticalLoc; 2363276479Sdim bool DeadLock = 2364276479Sdim Stack->hasDirective([CurrentName, &PreviousCriticalLoc]( 2365276479Sdim OpenMPDirectiveKind K, 2366276479Sdim const DeclarationNameInfo &DNI, 2367276479Sdim SourceLocation Loc) 2368276479Sdim ->bool { 2369276479Sdim if (K == OMPD_critical && 2370276479Sdim DNI.getName() == CurrentName.getName()) { 2371276479Sdim PreviousCriticalLoc = Loc; 2372276479Sdim return true; 2373276479Sdim } else 2374276479Sdim return false; 2375276479Sdim }, 2376276479Sdim false /* skip top directive */); 2377276479Sdim if (DeadLock) { 2378276479Sdim SemaRef.Diag(StartLoc, 2379276479Sdim diag::err_omp_prohibited_region_critical_same_name) 2380276479Sdim << CurrentName.getName(); 2381276479Sdim if (PreviousCriticalLoc.isValid()) 2382276479Sdim SemaRef.Diag(PreviousCriticalLoc, 2383276479Sdim diag::note_omp_previous_critical_region); 2384276479Sdim return true; 2385276479Sdim } 2386276479Sdim } else if (CurrentRegion == OMPD_barrier) { 2387276479Sdim // OpenMP [2.16, Nesting of Regions] 2388276479Sdim // A barrier region may not be closely nested inside a worksharing, 2389280031Sdim // explicit task, critical, ordered, atomic, or master region. 2390280031Sdim NestingProhibited = 2391280031Sdim isOpenMPWorksharingDirective(ParentRegion) || 2392280031Sdim ParentRegion == OMPD_task || ParentRegion == OMPD_master || 2393296417Sdim ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered || 2394296417Sdim isOpenMPTaskLoopDirective(ParentRegion); 2395276479Sdim } else if (isOpenMPWorksharingDirective(CurrentRegion) && 2396280031Sdim !isOpenMPParallelDirective(CurrentRegion)) { 2397276479Sdim // OpenMP [2.16, Nesting of Regions] 2398276479Sdim // A worksharing region may not be closely nested inside a worksharing, 2399276479Sdim // explicit task, critical, ordered, atomic, or master region. 2400280031Sdim NestingProhibited = 2401280031Sdim isOpenMPWorksharingDirective(ParentRegion) || 2402280031Sdim ParentRegion == OMPD_task || ParentRegion == OMPD_master || 2403296417Sdim ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered || 2404296417Sdim isOpenMPTaskLoopDirective(ParentRegion); 2405280031Sdim Recommend = ShouldBeInParallelRegion; 2406280031Sdim } else if (CurrentRegion == OMPD_ordered) { 2407280031Sdim // OpenMP [2.16, Nesting of Regions] 2408280031Sdim // An ordered region may not be closely nested inside a critical, 2409280031Sdim // atomic, or explicit task region. 2410280031Sdim // An ordered region must be closely nested inside a loop region (or 2411280031Sdim // parallel loop region) with an ordered clause. 2412296417Sdim // OpenMP [2.8.1,simd Construct, Restrictions] 2413296417Sdim // An ordered construct with the simd clause is the only OpenMP construct 2414296417Sdim // that can appear in the simd region. 2415280031Sdim NestingProhibited = ParentRegion == OMPD_critical || 2416276479Sdim ParentRegion == OMPD_task || 2417296417Sdim isOpenMPTaskLoopDirective(ParentRegion) || 2418296417Sdim !(isOpenMPSimdDirective(ParentRegion) || 2419296417Sdim Stack->isParentOrderedRegion()); 2420280031Sdim Recommend = ShouldBeInOrderedRegion; 2421280031Sdim } else if (isOpenMPTeamsDirective(CurrentRegion)) { 2422280031Sdim // OpenMP [2.16, Nesting of Regions] 2423280031Sdim // If specified, a teams construct must be contained within a target 2424280031Sdim // construct. 2425280031Sdim NestingProhibited = ParentRegion != OMPD_target; 2426280031Sdim Recommend = ShouldBeInTargetRegion; 2427280031Sdim Stack->setParentTeamsRegionLoc(Stack->getConstructLoc()); 2428276479Sdim } 2429280031Sdim if (!NestingProhibited && isOpenMPTeamsDirective(ParentRegion)) { 2430280031Sdim // OpenMP [2.16, Nesting of Regions] 2431280031Sdim // distribute, parallel, parallel sections, parallel workshare, and the 2432280031Sdim // parallel loop and parallel loop SIMD constructs are the only OpenMP 2433280031Sdim // constructs that can be closely nested in the teams region. 2434296417Sdim NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) && 2435296417Sdim !isOpenMPDistributeDirective(CurrentRegion); 2436280031Sdim Recommend = ShouldBeInParallelRegion; 2437280031Sdim } 2438296417Sdim if (!NestingProhibited && isOpenMPDistributeDirective(CurrentRegion)) { 2439296417Sdim // OpenMP 4.5 [2.17 Nesting of Regions] 2440296417Sdim // The region associated with the distribute construct must be strictly 2441296417Sdim // nested inside a teams region 2442296417Sdim NestingProhibited = !isOpenMPTeamsDirective(ParentRegion); 2443296417Sdim Recommend = ShouldBeInTeamsRegion; 2444296417Sdim } 2445276479Sdim if (NestingProhibited) { 2446276479Sdim SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region) 2447280031Sdim << CloseNesting << getOpenMPDirectiveName(ParentRegion) << Recommend 2448280031Sdim << getOpenMPDirectiveName(CurrentRegion); 2449276479Sdim return true; 2450276479Sdim } 2451276479Sdim } 2452276479Sdim return false; 2453276479Sdim} 2454276479Sdim 2455296417Sdimstatic bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, 2456296417Sdim ArrayRef<OMPClause *> Clauses, 2457296417Sdim ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) { 2458296417Sdim bool ErrorFound = false; 2459296417Sdim unsigned NamedModifiersNumber = 0; 2460296417Sdim SmallVector<const OMPIfClause *, OMPC_unknown + 1> FoundNameModifiers( 2461296417Sdim OMPD_unknown + 1); 2462296417Sdim SmallVector<SourceLocation, 4> NameModifierLoc; 2463296417Sdim for (const auto *C : Clauses) { 2464296417Sdim if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) { 2465296417Sdim // At most one if clause without a directive-name-modifier can appear on 2466296417Sdim // the directive. 2467296417Sdim OpenMPDirectiveKind CurNM = IC->getNameModifier(); 2468296417Sdim if (FoundNameModifiers[CurNM]) { 2469296417Sdim S.Diag(C->getLocStart(), diag::err_omp_more_one_clause) 2470296417Sdim << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if) 2471296417Sdim << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM); 2472296417Sdim ErrorFound = true; 2473296417Sdim } else if (CurNM != OMPD_unknown) { 2474296417Sdim NameModifierLoc.push_back(IC->getNameModifierLoc()); 2475296417Sdim ++NamedModifiersNumber; 2476296417Sdim } 2477296417Sdim FoundNameModifiers[CurNM] = IC; 2478296417Sdim if (CurNM == OMPD_unknown) 2479296417Sdim continue; 2480296417Sdim // Check if the specified name modifier is allowed for the current 2481296417Sdim // directive. 2482296417Sdim // At most one if clause with the particular directive-name-modifier can 2483296417Sdim // appear on the directive. 2484296417Sdim bool MatchFound = false; 2485296417Sdim for (auto NM : AllowedNameModifiers) { 2486296417Sdim if (CurNM == NM) { 2487296417Sdim MatchFound = true; 2488296417Sdim break; 2489296417Sdim } 2490296417Sdim } 2491296417Sdim if (!MatchFound) { 2492296417Sdim S.Diag(IC->getNameModifierLoc(), 2493296417Sdim diag::err_omp_wrong_if_directive_name_modifier) 2494296417Sdim << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind); 2495296417Sdim ErrorFound = true; 2496296417Sdim } 2497296417Sdim } 2498296417Sdim } 2499296417Sdim // If any if clause on the directive includes a directive-name-modifier then 2500296417Sdim // all if clauses on the directive must include a directive-name-modifier. 2501296417Sdim if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) { 2502296417Sdim if (NamedModifiersNumber == AllowedNameModifiers.size()) { 2503296417Sdim S.Diag(FoundNameModifiers[OMPD_unknown]->getLocStart(), 2504296417Sdim diag::err_omp_no_more_if_clause); 2505296417Sdim } else { 2506296417Sdim std::string Values; 2507296417Sdim std::string Sep(", "); 2508296417Sdim unsigned AllowedCnt = 0; 2509296417Sdim unsigned TotalAllowedNum = 2510296417Sdim AllowedNameModifiers.size() - NamedModifiersNumber; 2511296417Sdim for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End; 2512296417Sdim ++Cnt) { 2513296417Sdim OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt]; 2514296417Sdim if (!FoundNameModifiers[NM]) { 2515296417Sdim Values += "'"; 2516296417Sdim Values += getOpenMPDirectiveName(NM); 2517296417Sdim Values += "'"; 2518296417Sdim if (AllowedCnt + 2 == TotalAllowedNum) 2519296417Sdim Values += " or "; 2520296417Sdim else if (AllowedCnt + 1 != TotalAllowedNum) 2521296417Sdim Values += Sep; 2522296417Sdim ++AllowedCnt; 2523296417Sdim } 2524296417Sdim } 2525296417Sdim S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getLocStart(), 2526296417Sdim diag::err_omp_unnamed_if_clause) 2527296417Sdim << (TotalAllowedNum > 1) << Values; 2528296417Sdim } 2529296417Sdim for (auto Loc : NameModifierLoc) { 2530296417Sdim S.Diag(Loc, diag::note_omp_previous_named_if_clause); 2531296417Sdim } 2532296417Sdim ErrorFound = true; 2533296417Sdim } 2534296417Sdim return ErrorFound; 2535296417Sdim} 2536296417Sdim 2537288943SdimStmtResult Sema::ActOnOpenMPExecutableDirective( 2538288943Sdim OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, 2539288943Sdim OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses, 2540288943Sdim Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { 2541261991Sdim StmtResult Res = StmtError(); 2542288943Sdim if (CheckNestingOfRegions(*this, DSAStack, Kind, DirName, CancelRegion, 2543288943Sdim StartLoc)) 2544276479Sdim return StmtError(); 2545261991Sdim 2546261991Sdim llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit; 2547276479Sdim llvm::DenseMap<VarDecl *, Expr *> VarsWithInheritedDSA; 2548276479Sdim bool ErrorFound = false; 2549261991Sdim ClausesWithImplicit.append(Clauses.begin(), Clauses.end()); 2550276479Sdim if (AStmt) { 2551276479Sdim assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 2552261991Sdim 2553276479Sdim // Check default data sharing attributes for referenced variables. 2554276479Sdim DSAAttrChecker DSAChecker(DSAStack, *this, cast<CapturedStmt>(AStmt)); 2555276479Sdim DSAChecker.Visit(cast<CapturedStmt>(AStmt)->getCapturedStmt()); 2556276479Sdim if (DSAChecker.isErrorFound()) 2557276479Sdim return StmtError(); 2558276479Sdim // Generate list of implicitly defined firstprivate variables. 2559276479Sdim VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA(); 2560276479Sdim 2561276479Sdim if (!DSAChecker.getImplicitFirstprivate().empty()) { 2562276479Sdim if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause( 2563276479Sdim DSAChecker.getImplicitFirstprivate(), SourceLocation(), 2564276479Sdim SourceLocation(), SourceLocation())) { 2565276479Sdim ClausesWithImplicit.push_back(Implicit); 2566276479Sdim ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() != 2567276479Sdim DSAChecker.getImplicitFirstprivate().size(); 2568276479Sdim } else 2569276479Sdim ErrorFound = true; 2570276479Sdim } 2571261991Sdim } 2572261991Sdim 2573296417Sdim llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers; 2574261991Sdim switch (Kind) { 2575261991Sdim case OMPD_parallel: 2576276479Sdim Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc, 2577276479Sdim EndLoc); 2578296417Sdim AllowedNameModifiers.push_back(OMPD_parallel); 2579261991Sdim break; 2580276479Sdim case OMPD_simd: 2581276479Sdim Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, 2582276479Sdim VarsWithInheritedDSA); 2583276479Sdim break; 2584276479Sdim case OMPD_for: 2585276479Sdim Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, 2586276479Sdim VarsWithInheritedDSA); 2587276479Sdim break; 2588280031Sdim case OMPD_for_simd: 2589280031Sdim Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc, 2590280031Sdim EndLoc, VarsWithInheritedDSA); 2591280031Sdim break; 2592276479Sdim case OMPD_sections: 2593276479Sdim Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc, 2594276479Sdim EndLoc); 2595276479Sdim break; 2596276479Sdim case OMPD_section: 2597276479Sdim assert(ClausesWithImplicit.empty() && 2598276479Sdim "No clauses are allowed for 'omp section' directive"); 2599276479Sdim Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc); 2600276479Sdim break; 2601276479Sdim case OMPD_single: 2602276479Sdim Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc, 2603276479Sdim EndLoc); 2604276479Sdim break; 2605276479Sdim case OMPD_master: 2606276479Sdim assert(ClausesWithImplicit.empty() && 2607276479Sdim "No clauses are allowed for 'omp master' directive"); 2608276479Sdim Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc); 2609276479Sdim break; 2610276479Sdim case OMPD_critical: 2611296417Sdim Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt, 2612296417Sdim StartLoc, EndLoc); 2613276479Sdim break; 2614276479Sdim case OMPD_parallel_for: 2615276479Sdim Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc, 2616276479Sdim EndLoc, VarsWithInheritedDSA); 2617296417Sdim AllowedNameModifiers.push_back(OMPD_parallel); 2618276479Sdim break; 2619280031Sdim case OMPD_parallel_for_simd: 2620280031Sdim Res = ActOnOpenMPParallelForSimdDirective( 2621280031Sdim ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); 2622296417Sdim AllowedNameModifiers.push_back(OMPD_parallel); 2623280031Sdim break; 2624276479Sdim case OMPD_parallel_sections: 2625276479Sdim Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt, 2626276479Sdim StartLoc, EndLoc); 2627296417Sdim AllowedNameModifiers.push_back(OMPD_parallel); 2628276479Sdim break; 2629276479Sdim case OMPD_task: 2630276479Sdim Res = 2631276479Sdim ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); 2632296417Sdim AllowedNameModifiers.push_back(OMPD_task); 2633276479Sdim break; 2634276479Sdim case OMPD_taskyield: 2635276479Sdim assert(ClausesWithImplicit.empty() && 2636276479Sdim "No clauses are allowed for 'omp taskyield' directive"); 2637276479Sdim assert(AStmt == nullptr && 2638276479Sdim "No associated statement allowed for 'omp taskyield' directive"); 2639276479Sdim Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc); 2640276479Sdim break; 2641276479Sdim case OMPD_barrier: 2642276479Sdim assert(ClausesWithImplicit.empty() && 2643276479Sdim "No clauses are allowed for 'omp barrier' directive"); 2644276479Sdim assert(AStmt == nullptr && 2645276479Sdim "No associated statement allowed for 'omp barrier' directive"); 2646276479Sdim Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc); 2647276479Sdim break; 2648276479Sdim case OMPD_taskwait: 2649276479Sdim assert(ClausesWithImplicit.empty() && 2650276479Sdim "No clauses are allowed for 'omp taskwait' directive"); 2651276479Sdim assert(AStmt == nullptr && 2652276479Sdim "No associated statement allowed for 'omp taskwait' directive"); 2653276479Sdim Res = ActOnOpenMPTaskwaitDirective(StartLoc, EndLoc); 2654276479Sdim break; 2655288943Sdim case OMPD_taskgroup: 2656288943Sdim assert(ClausesWithImplicit.empty() && 2657288943Sdim "No clauses are allowed for 'omp taskgroup' directive"); 2658288943Sdim Res = ActOnOpenMPTaskgroupDirective(AStmt, StartLoc, EndLoc); 2659288943Sdim break; 2660276479Sdim case OMPD_flush: 2661276479Sdim assert(AStmt == nullptr && 2662276479Sdim "No associated statement allowed for 'omp flush' directive"); 2663276479Sdim Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc); 2664276479Sdim break; 2665280031Sdim case OMPD_ordered: 2666296417Sdim Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc, 2667296417Sdim EndLoc); 2668280031Sdim break; 2669280031Sdim case OMPD_atomic: 2670280031Sdim Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc, 2671280031Sdim EndLoc); 2672280031Sdim break; 2673280031Sdim case OMPD_teams: 2674280031Sdim Res = 2675280031Sdim ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); 2676280031Sdim break; 2677280031Sdim case OMPD_target: 2678280031Sdim Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc, 2679280031Sdim EndLoc); 2680296417Sdim AllowedNameModifiers.push_back(OMPD_target); 2681280031Sdim break; 2682288943Sdim case OMPD_cancellation_point: 2683288943Sdim assert(ClausesWithImplicit.empty() && 2684288943Sdim "No clauses are allowed for 'omp cancellation point' directive"); 2685288943Sdim assert(AStmt == nullptr && "No associated statement allowed for 'omp " 2686288943Sdim "cancellation point' directive"); 2687288943Sdim Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion); 2688288943Sdim break; 2689288943Sdim case OMPD_cancel: 2690288943Sdim assert(AStmt == nullptr && 2691288943Sdim "No associated statement allowed for 'omp cancel' directive"); 2692296417Sdim Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc, 2693296417Sdim CancelRegion); 2694296417Sdim AllowedNameModifiers.push_back(OMPD_cancel); 2695288943Sdim break; 2696296417Sdim case OMPD_target_data: 2697296417Sdim Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc, 2698296417Sdim EndLoc); 2699296417Sdim AllowedNameModifiers.push_back(OMPD_target_data); 2700296417Sdim break; 2701296417Sdim case OMPD_taskloop: 2702296417Sdim Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc, 2703296417Sdim EndLoc, VarsWithInheritedDSA); 2704296417Sdim AllowedNameModifiers.push_back(OMPD_taskloop); 2705296417Sdim break; 2706296417Sdim case OMPD_taskloop_simd: 2707296417Sdim Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc, 2708296417Sdim EndLoc, VarsWithInheritedDSA); 2709296417Sdim AllowedNameModifiers.push_back(OMPD_taskloop); 2710296417Sdim break; 2711296417Sdim case OMPD_distribute: 2712296417Sdim Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc, 2713296417Sdim EndLoc, VarsWithInheritedDSA); 2714296417Sdim break; 2715261991Sdim case OMPD_threadprivate: 2716261991Sdim llvm_unreachable("OpenMP Directive is not allowed"); 2717261991Sdim case OMPD_unknown: 2718261991Sdim llvm_unreachable("Unknown OpenMP directive"); 2719261991Sdim } 2720261991Sdim 2721276479Sdim for (auto P : VarsWithInheritedDSA) { 2722276479Sdim Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable) 2723276479Sdim << P.first << P.second->getSourceRange(); 2724276479Sdim } 2725296417Sdim ErrorFound = !VarsWithInheritedDSA.empty() || ErrorFound; 2726276479Sdim 2727296417Sdim if (!AllowedNameModifiers.empty()) 2728296417Sdim ErrorFound = checkIfClauses(*this, Kind, Clauses, AllowedNameModifiers) || 2729296417Sdim ErrorFound; 2730296417Sdim 2731276479Sdim if (ErrorFound) 2732276479Sdim return StmtError(); 2733261991Sdim return Res; 2734261991Sdim} 2735261991Sdim 2736261991SdimStmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses, 2737261991Sdim Stmt *AStmt, 2738261991Sdim SourceLocation StartLoc, 2739261991Sdim SourceLocation EndLoc) { 2740296417Sdim if (!AStmt) 2741296417Sdim return StmtError(); 2742296417Sdim 2743276479Sdim CapturedStmt *CS = cast<CapturedStmt>(AStmt); 2744276479Sdim // 1.2.2 OpenMP Language Terminology 2745276479Sdim // Structured block - An executable statement with a single entry at the 2746276479Sdim // top and a single exit at the bottom. 2747276479Sdim // The point of exit cannot be a branch out of the structured block. 2748276479Sdim // longjmp() and throw() must not violate the entry/exit criteria. 2749276479Sdim CS->getCapturedDecl()->setNothrow(); 2750276479Sdim 2751261991Sdim getCurFunction()->setHasBranchProtectedScope(); 2752261991Sdim 2753296417Sdim return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, 2754296417Sdim DSAStack->isCancelRegion()); 2755261991Sdim} 2756261991Sdim 2757276479Sdimnamespace { 2758276479Sdim/// \brief Helper class for checking canonical form of the OpenMP loops and 2759276479Sdim/// extracting iteration space of each loop in the loop nest, that will be used 2760276479Sdim/// for IR generation. 2761276479Sdimclass OpenMPIterationSpaceChecker { 2762276479Sdim /// \brief Reference to Sema. 2763276479Sdim Sema &SemaRef; 2764276479Sdim /// \brief A location for diagnostics (when there is no some better location). 2765276479Sdim SourceLocation DefaultLoc; 2766276479Sdim /// \brief A location for diagnostics (when increment is not compatible). 2767276479Sdim SourceLocation ConditionLoc; 2768280031Sdim /// \brief A source location for referring to loop init later. 2769280031Sdim SourceRange InitSrcRange; 2770276479Sdim /// \brief A source location for referring to condition later. 2771276479Sdim SourceRange ConditionSrcRange; 2772280031Sdim /// \brief A source location for referring to increment later. 2773280031Sdim SourceRange IncrementSrcRange; 2774276479Sdim /// \brief Loop variable. 2775276479Sdim VarDecl *Var; 2776280031Sdim /// \brief Reference to loop variable. 2777280031Sdim DeclRefExpr *VarRef; 2778276479Sdim /// \brief Lower bound (initializer for the var). 2779276479Sdim Expr *LB; 2780276479Sdim /// \brief Upper bound. 2781276479Sdim Expr *UB; 2782276479Sdim /// \brief Loop step (increment). 2783276479Sdim Expr *Step; 2784276479Sdim /// \brief This flag is true when condition is one of: 2785276479Sdim /// Var < UB 2786276479Sdim /// Var <= UB 2787276479Sdim /// UB > Var 2788276479Sdim /// UB >= Var 2789276479Sdim bool TestIsLessOp; 2790276479Sdim /// \brief This flag is true when condition is strict ( < or > ). 2791276479Sdim bool TestIsStrictOp; 2792276479Sdim /// \brief This flag is true when step is subtracted on each iteration. 2793276479Sdim bool SubtractStep; 2794276479Sdim 2795276479Sdimpublic: 2796276479Sdim OpenMPIterationSpaceChecker(Sema &SemaRef, SourceLocation DefaultLoc) 2797276479Sdim : SemaRef(SemaRef), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc), 2798280031Sdim InitSrcRange(SourceRange()), ConditionSrcRange(SourceRange()), 2799280031Sdim IncrementSrcRange(SourceRange()), Var(nullptr), VarRef(nullptr), 2800280031Sdim LB(nullptr), UB(nullptr), Step(nullptr), TestIsLessOp(false), 2801280031Sdim TestIsStrictOp(false), SubtractStep(false) {} 2802276479Sdim /// \brief Check init-expr for canonical loop form and save loop counter 2803276479Sdim /// variable - #Var and its initialization value - #LB. 2804288943Sdim bool CheckInit(Stmt *S, bool EmitDiags = true); 2805276479Sdim /// \brief Check test-expr for canonical form, save upper-bound (#UB), flags 2806276479Sdim /// for less/greater and for strict/non-strict comparison. 2807276479Sdim bool CheckCond(Expr *S); 2808276479Sdim /// \brief Check incr-expr for canonical loop form and return true if it 2809276479Sdim /// does not conform, otherwise save loop step (#Step). 2810276479Sdim bool CheckInc(Expr *S); 2811276479Sdim /// \brief Return the loop counter variable. 2812276479Sdim VarDecl *GetLoopVar() const { return Var; } 2813280031Sdim /// \brief Return the reference expression to loop counter variable. 2814280031Sdim DeclRefExpr *GetLoopVarRefExpr() const { return VarRef; } 2815280031Sdim /// \brief Source range of the loop init. 2816280031Sdim SourceRange GetInitSrcRange() const { return InitSrcRange; } 2817280031Sdim /// \brief Source range of the loop condition. 2818280031Sdim SourceRange GetConditionSrcRange() const { return ConditionSrcRange; } 2819280031Sdim /// \brief Source range of the loop increment. 2820280031Sdim SourceRange GetIncrementSrcRange() const { return IncrementSrcRange; } 2821280031Sdim /// \brief True if the step should be subtracted. 2822280031Sdim bool ShouldSubtractStep() const { return SubtractStep; } 2823280031Sdim /// \brief Build the expression to calculate the number of iterations. 2824280031Sdim Expr *BuildNumIterations(Scope *S, const bool LimitedType) const; 2825288943Sdim /// \brief Build the precondition expression for the loops. 2826288943Sdim Expr *BuildPreCond(Scope *S, Expr *Cond) const; 2827280031Sdim /// \brief Build reference expression to the counter be used for codegen. 2828280031Sdim Expr *BuildCounterVar() const; 2829296417Sdim /// \brief Build reference expression to the private counter be used for 2830296417Sdim /// codegen. 2831296417Sdim Expr *BuildPrivateCounterVar() const; 2832280031Sdim /// \brief Build initization of the counter be used for codegen. 2833280031Sdim Expr *BuildCounterInit() const; 2834280031Sdim /// \brief Build step of the counter be used for codegen. 2835280031Sdim Expr *BuildCounterStep() const; 2836276479Sdim /// \brief Return true if any expression is dependent. 2837276479Sdim bool Dependent() const; 2838276479Sdim 2839276479Sdimprivate: 2840276479Sdim /// \brief Check the right-hand side of an assignment in the increment 2841276479Sdim /// expression. 2842276479Sdim bool CheckIncRHS(Expr *RHS); 2843276479Sdim /// \brief Helper to set loop counter variable and its initializer. 2844280031Sdim bool SetVarAndLB(VarDecl *NewVar, DeclRefExpr *NewVarRefExpr, Expr *NewLB); 2845276479Sdim /// \brief Helper to set upper bound. 2846296417Sdim bool SetUB(Expr *NewUB, bool LessOp, bool StrictOp, SourceRange SR, 2847296417Sdim SourceLocation SL); 2848276479Sdim /// \brief Helper to set loop increment. 2849276479Sdim bool SetStep(Expr *NewStep, bool Subtract); 2850276479Sdim}; 2851276479Sdim 2852276479Sdimbool OpenMPIterationSpaceChecker::Dependent() const { 2853276479Sdim if (!Var) { 2854276479Sdim assert(!LB && !UB && !Step); 2855276479Sdim return false; 2856276479Sdim } 2857276479Sdim return Var->getType()->isDependentType() || (LB && LB->isValueDependent()) || 2858276479Sdim (UB && UB->isValueDependent()) || (Step && Step->isValueDependent()); 2859276479Sdim} 2860276479Sdim 2861288943Sdimtemplate <typename T> 2862288943Sdimstatic T *getExprAsWritten(T *E) { 2863288943Sdim if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(E)) 2864288943Sdim E = ExprTemp->getSubExpr(); 2865288943Sdim 2866288943Sdim if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) 2867288943Sdim E = MTE->GetTemporaryExpr(); 2868288943Sdim 2869288943Sdim while (auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E)) 2870288943Sdim E = Binder->getSubExpr(); 2871288943Sdim 2872288943Sdim if (auto *ICE = dyn_cast<ImplicitCastExpr>(E)) 2873288943Sdim E = ICE->getSubExprAsWritten(); 2874288943Sdim return E->IgnoreParens(); 2875288943Sdim} 2876288943Sdim 2877280031Sdimbool OpenMPIterationSpaceChecker::SetVarAndLB(VarDecl *NewVar, 2878280031Sdim DeclRefExpr *NewVarRefExpr, 2879280031Sdim Expr *NewLB) { 2880276479Sdim // State consistency checking to ensure correct usage. 2881280031Sdim assert(Var == nullptr && LB == nullptr && VarRef == nullptr && 2882280031Sdim UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp); 2883276479Sdim if (!NewVar || !NewLB) 2884276479Sdim return true; 2885276479Sdim Var = NewVar; 2886280031Sdim VarRef = NewVarRefExpr; 2887288943Sdim if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB)) 2888288943Sdim if (const CXXConstructorDecl *Ctor = CE->getConstructor()) 2889288943Sdim if ((Ctor->isCopyOrMoveConstructor() || 2890288943Sdim Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) && 2891288943Sdim CE->getNumArgs() > 0 && CE->getArg(0) != nullptr) 2892288943Sdim NewLB = CE->getArg(0)->IgnoreParenImpCasts(); 2893276479Sdim LB = NewLB; 2894276479Sdim return false; 2895276479Sdim} 2896276479Sdim 2897276479Sdimbool OpenMPIterationSpaceChecker::SetUB(Expr *NewUB, bool LessOp, bool StrictOp, 2898296417Sdim SourceRange SR, SourceLocation SL) { 2899276479Sdim // State consistency checking to ensure correct usage. 2900276479Sdim assert(Var != nullptr && LB != nullptr && UB == nullptr && Step == nullptr && 2901276479Sdim !TestIsLessOp && !TestIsStrictOp); 2902276479Sdim if (!NewUB) 2903276479Sdim return true; 2904276479Sdim UB = NewUB; 2905276479Sdim TestIsLessOp = LessOp; 2906276479Sdim TestIsStrictOp = StrictOp; 2907276479Sdim ConditionSrcRange = SR; 2908276479Sdim ConditionLoc = SL; 2909276479Sdim return false; 2910276479Sdim} 2911276479Sdim 2912276479Sdimbool OpenMPIterationSpaceChecker::SetStep(Expr *NewStep, bool Subtract) { 2913276479Sdim // State consistency checking to ensure correct usage. 2914276479Sdim assert(Var != nullptr && LB != nullptr && Step == nullptr); 2915276479Sdim if (!NewStep) 2916276479Sdim return true; 2917276479Sdim if (!NewStep->isValueDependent()) { 2918276479Sdim // Check that the step is integer expression. 2919276479Sdim SourceLocation StepLoc = NewStep->getLocStart(); 2920276479Sdim ExprResult Val = 2921276479Sdim SemaRef.PerformOpenMPImplicitIntegerConversion(StepLoc, NewStep); 2922276479Sdim if (Val.isInvalid()) 2923276479Sdim return true; 2924276479Sdim NewStep = Val.get(); 2925276479Sdim 2926276479Sdim // OpenMP [2.6, Canonical Loop Form, Restrictions] 2927276479Sdim // If test-expr is of form var relational-op b and relational-op is < or 2928276479Sdim // <= then incr-expr must cause var to increase on each iteration of the 2929276479Sdim // loop. If test-expr is of form var relational-op b and relational-op is 2930276479Sdim // > or >= then incr-expr must cause var to decrease on each iteration of 2931276479Sdim // the loop. 2932276479Sdim // If test-expr is of form b relational-op var and relational-op is < or 2933276479Sdim // <= then incr-expr must cause var to decrease on each iteration of the 2934276479Sdim // loop. If test-expr is of form b relational-op var and relational-op is 2935276479Sdim // > or >= then incr-expr must cause var to increase on each iteration of 2936276479Sdim // the loop. 2937276479Sdim llvm::APSInt Result; 2938276479Sdim bool IsConstant = NewStep->isIntegerConstantExpr(Result, SemaRef.Context); 2939276479Sdim bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation(); 2940276479Sdim bool IsConstNeg = 2941276479Sdim IsConstant && Result.isSigned() && (Subtract != Result.isNegative()); 2942280031Sdim bool IsConstPos = 2943280031Sdim IsConstant && Result.isSigned() && (Subtract == Result.isNegative()); 2944276479Sdim bool IsConstZero = IsConstant && !Result.getBoolValue(); 2945276479Sdim if (UB && (IsConstZero || 2946276479Sdim (TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract)) 2947280031Sdim : (IsConstPos || (IsUnsigned && !Subtract))))) { 2948276479Sdim SemaRef.Diag(NewStep->getExprLoc(), 2949276479Sdim diag::err_omp_loop_incr_not_compatible) 2950276479Sdim << Var << TestIsLessOp << NewStep->getSourceRange(); 2951276479Sdim SemaRef.Diag(ConditionLoc, 2952276479Sdim diag::note_omp_loop_cond_requres_compatible_incr) 2953276479Sdim << TestIsLessOp << ConditionSrcRange; 2954276479Sdim return true; 2955276479Sdim } 2956280031Sdim if (TestIsLessOp == Subtract) { 2957280031Sdim NewStep = SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, 2958280031Sdim NewStep).get(); 2959280031Sdim Subtract = !Subtract; 2960280031Sdim } 2961276479Sdim } 2962276479Sdim 2963276479Sdim Step = NewStep; 2964276479Sdim SubtractStep = Subtract; 2965276479Sdim return false; 2966276479Sdim} 2967276479Sdim 2968288943Sdimbool OpenMPIterationSpaceChecker::CheckInit(Stmt *S, bool EmitDiags) { 2969276479Sdim // Check init-expr for canonical loop form and save loop counter 2970276479Sdim // variable - #Var and its initialization value - #LB. 2971276479Sdim // OpenMP [2.6] Canonical loop form. init-expr may be one of the following: 2972276479Sdim // var = lb 2973276479Sdim // integer-type var = lb 2974276479Sdim // random-access-iterator-type var = lb 2975276479Sdim // pointer-type var = lb 2976276479Sdim // 2977276479Sdim if (!S) { 2978288943Sdim if (EmitDiags) { 2979288943Sdim SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init); 2980288943Sdim } 2981276479Sdim return true; 2982276479Sdim } 2983280031Sdim InitSrcRange = S->getSourceRange(); 2984276479Sdim if (Expr *E = dyn_cast<Expr>(S)) 2985276479Sdim S = E->IgnoreParens(); 2986276479Sdim if (auto BO = dyn_cast<BinaryOperator>(S)) { 2987276479Sdim if (BO->getOpcode() == BO_Assign) 2988276479Sdim if (auto DRE = dyn_cast<DeclRefExpr>(BO->getLHS()->IgnoreParens())) 2989280031Sdim return SetVarAndLB(dyn_cast<VarDecl>(DRE->getDecl()), DRE, 2990280031Sdim BO->getRHS()); 2991276479Sdim } else if (auto DS = dyn_cast<DeclStmt>(S)) { 2992276479Sdim if (DS->isSingleDecl()) { 2993276479Sdim if (auto Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) { 2994296417Sdim if (Var->hasInit() && !Var->getType()->isReferenceType()) { 2995276479Sdim // Accept non-canonical init form here but emit ext. warning. 2996288943Sdim if (Var->getInitStyle() != VarDecl::CInit && EmitDiags) 2997276479Sdim SemaRef.Diag(S->getLocStart(), 2998276479Sdim diag::ext_omp_loop_not_canonical_init) 2999276479Sdim << S->getSourceRange(); 3000280031Sdim return SetVarAndLB(Var, nullptr, Var->getInit()); 3001276479Sdim } 3002276479Sdim } 3003276479Sdim } 3004276479Sdim } else if (auto CE = dyn_cast<CXXOperatorCallExpr>(S)) 3005276479Sdim if (CE->getOperator() == OO_Equal) 3006276479Sdim if (auto DRE = dyn_cast<DeclRefExpr>(CE->getArg(0))) 3007280031Sdim return SetVarAndLB(dyn_cast<VarDecl>(DRE->getDecl()), DRE, 3008280031Sdim CE->getArg(1)); 3009276479Sdim 3010288943Sdim if (EmitDiags) { 3011288943Sdim SemaRef.Diag(S->getLocStart(), diag::err_omp_loop_not_canonical_init) 3012288943Sdim << S->getSourceRange(); 3013288943Sdim } 3014276479Sdim return true; 3015276479Sdim} 3016276479Sdim 3017276479Sdim/// \brief Ignore parenthesizes, implicit casts, copy constructor and return the 3018276479Sdim/// variable (which may be the loop variable) if possible. 3019276479Sdimstatic const VarDecl *GetInitVarDecl(const Expr *E) { 3020276479Sdim if (!E) 3021276479Sdim return nullptr; 3022288943Sdim E = getExprAsWritten(E); 3023276479Sdim if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(E)) 3024276479Sdim if (const CXXConstructorDecl *Ctor = CE->getConstructor()) 3025288943Sdim if ((Ctor->isCopyOrMoveConstructor() || 3026288943Sdim Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) && 3027288943Sdim CE->getNumArgs() > 0 && CE->getArg(0) != nullptr) 3028276479Sdim E = CE->getArg(0)->IgnoreParenImpCasts(); 3029276479Sdim auto DRE = dyn_cast_or_null<DeclRefExpr>(E); 3030276479Sdim if (!DRE) 3031276479Sdim return nullptr; 3032276479Sdim return dyn_cast<VarDecl>(DRE->getDecl()); 3033276479Sdim} 3034276479Sdim 3035276479Sdimbool OpenMPIterationSpaceChecker::CheckCond(Expr *S) { 3036276479Sdim // Check test-expr for canonical form, save upper-bound UB, flags for 3037276479Sdim // less/greater and for strict/non-strict comparison. 3038276479Sdim // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following: 3039276479Sdim // var relational-op b 3040276479Sdim // b relational-op var 3041276479Sdim // 3042276479Sdim if (!S) { 3043276479Sdim SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond) << Var; 3044276479Sdim return true; 3045276479Sdim } 3046288943Sdim S = getExprAsWritten(S); 3047276479Sdim SourceLocation CondLoc = S->getLocStart(); 3048276479Sdim if (auto BO = dyn_cast<BinaryOperator>(S)) { 3049276479Sdim if (BO->isRelationalOp()) { 3050276479Sdim if (GetInitVarDecl(BO->getLHS()) == Var) 3051276479Sdim return SetUB(BO->getRHS(), 3052276479Sdim (BO->getOpcode() == BO_LT || BO->getOpcode() == BO_LE), 3053276479Sdim (BO->getOpcode() == BO_LT || BO->getOpcode() == BO_GT), 3054276479Sdim BO->getSourceRange(), BO->getOperatorLoc()); 3055276479Sdim if (GetInitVarDecl(BO->getRHS()) == Var) 3056276479Sdim return SetUB(BO->getLHS(), 3057276479Sdim (BO->getOpcode() == BO_GT || BO->getOpcode() == BO_GE), 3058276479Sdim (BO->getOpcode() == BO_LT || BO->getOpcode() == BO_GT), 3059276479Sdim BO->getSourceRange(), BO->getOperatorLoc()); 3060276479Sdim } 3061276479Sdim } else if (auto CE = dyn_cast<CXXOperatorCallExpr>(S)) { 3062276479Sdim if (CE->getNumArgs() == 2) { 3063276479Sdim auto Op = CE->getOperator(); 3064276479Sdim switch (Op) { 3065276479Sdim case OO_Greater: 3066276479Sdim case OO_GreaterEqual: 3067276479Sdim case OO_Less: 3068276479Sdim case OO_LessEqual: 3069276479Sdim if (GetInitVarDecl(CE->getArg(0)) == Var) 3070276479Sdim return SetUB(CE->getArg(1), Op == OO_Less || Op == OO_LessEqual, 3071276479Sdim Op == OO_Less || Op == OO_Greater, CE->getSourceRange(), 3072276479Sdim CE->getOperatorLoc()); 3073276479Sdim if (GetInitVarDecl(CE->getArg(1)) == Var) 3074276479Sdim return SetUB(CE->getArg(0), Op == OO_Greater || Op == OO_GreaterEqual, 3075276479Sdim Op == OO_Less || Op == OO_Greater, CE->getSourceRange(), 3076276479Sdim CE->getOperatorLoc()); 3077276479Sdim break; 3078276479Sdim default: 3079276479Sdim break; 3080276479Sdim } 3081276479Sdim } 3082276479Sdim } 3083276479Sdim SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond) 3084276479Sdim << S->getSourceRange() << Var; 3085276479Sdim return true; 3086276479Sdim} 3087276479Sdim 3088276479Sdimbool OpenMPIterationSpaceChecker::CheckIncRHS(Expr *RHS) { 3089276479Sdim // RHS of canonical loop form increment can be: 3090276479Sdim // var + incr 3091276479Sdim // incr + var 3092276479Sdim // var - incr 3093276479Sdim // 3094276479Sdim RHS = RHS->IgnoreParenImpCasts(); 3095276479Sdim if (auto BO = dyn_cast<BinaryOperator>(RHS)) { 3096276479Sdim if (BO->isAdditiveOp()) { 3097276479Sdim bool IsAdd = BO->getOpcode() == BO_Add; 3098276479Sdim if (GetInitVarDecl(BO->getLHS()) == Var) 3099276479Sdim return SetStep(BO->getRHS(), !IsAdd); 3100276479Sdim if (IsAdd && GetInitVarDecl(BO->getRHS()) == Var) 3101276479Sdim return SetStep(BO->getLHS(), false); 3102276479Sdim } 3103276479Sdim } else if (auto CE = dyn_cast<CXXOperatorCallExpr>(RHS)) { 3104276479Sdim bool IsAdd = CE->getOperator() == OO_Plus; 3105276479Sdim if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) { 3106276479Sdim if (GetInitVarDecl(CE->getArg(0)) == Var) 3107276479Sdim return SetStep(CE->getArg(1), !IsAdd); 3108276479Sdim if (IsAdd && GetInitVarDecl(CE->getArg(1)) == Var) 3109276479Sdim return SetStep(CE->getArg(0), false); 3110276479Sdim } 3111276479Sdim } 3112276479Sdim SemaRef.Diag(RHS->getLocStart(), diag::err_omp_loop_not_canonical_incr) 3113276479Sdim << RHS->getSourceRange() << Var; 3114276479Sdim return true; 3115276479Sdim} 3116276479Sdim 3117276479Sdimbool OpenMPIterationSpaceChecker::CheckInc(Expr *S) { 3118276479Sdim // Check incr-expr for canonical loop form and return true if it 3119276479Sdim // does not conform. 3120276479Sdim // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following: 3121276479Sdim // ++var 3122276479Sdim // var++ 3123276479Sdim // --var 3124276479Sdim // var-- 3125276479Sdim // var += incr 3126276479Sdim // var -= incr 3127276479Sdim // var = var + incr 3128276479Sdim // var = incr + var 3129276479Sdim // var = var - incr 3130276479Sdim // 3131276479Sdim if (!S) { 3132276479Sdim SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << Var; 3133276479Sdim return true; 3134276479Sdim } 3135280031Sdim IncrementSrcRange = S->getSourceRange(); 3136276479Sdim S = S->IgnoreParens(); 3137276479Sdim if (auto UO = dyn_cast<UnaryOperator>(S)) { 3138276479Sdim if (UO->isIncrementDecrementOp() && GetInitVarDecl(UO->getSubExpr()) == Var) 3139276479Sdim return SetStep( 3140276479Sdim SemaRef.ActOnIntegerConstant(UO->getLocStart(), 3141276479Sdim (UO->isDecrementOp() ? -1 : 1)).get(), 3142276479Sdim false); 3143276479Sdim } else if (auto BO = dyn_cast<BinaryOperator>(S)) { 3144276479Sdim switch (BO->getOpcode()) { 3145276479Sdim case BO_AddAssign: 3146276479Sdim case BO_SubAssign: 3147276479Sdim if (GetInitVarDecl(BO->getLHS()) == Var) 3148276479Sdim return SetStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign); 3149276479Sdim break; 3150276479Sdim case BO_Assign: 3151276479Sdim if (GetInitVarDecl(BO->getLHS()) == Var) 3152276479Sdim return CheckIncRHS(BO->getRHS()); 3153276479Sdim break; 3154276479Sdim default: 3155276479Sdim break; 3156276479Sdim } 3157276479Sdim } else if (auto CE = dyn_cast<CXXOperatorCallExpr>(S)) { 3158276479Sdim switch (CE->getOperator()) { 3159276479Sdim case OO_PlusPlus: 3160276479Sdim case OO_MinusMinus: 3161276479Sdim if (GetInitVarDecl(CE->getArg(0)) == Var) 3162276479Sdim return SetStep( 3163276479Sdim SemaRef.ActOnIntegerConstant( 3164276479Sdim CE->getLocStart(), 3165276479Sdim ((CE->getOperator() == OO_MinusMinus) ? -1 : 1)).get(), 3166276479Sdim false); 3167276479Sdim break; 3168276479Sdim case OO_PlusEqual: 3169276479Sdim case OO_MinusEqual: 3170276479Sdim if (GetInitVarDecl(CE->getArg(0)) == Var) 3171276479Sdim return SetStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual); 3172276479Sdim break; 3173276479Sdim case OO_Equal: 3174276479Sdim if (GetInitVarDecl(CE->getArg(0)) == Var) 3175276479Sdim return CheckIncRHS(CE->getArg(1)); 3176276479Sdim break; 3177276479Sdim default: 3178276479Sdim break; 3179276479Sdim } 3180276479Sdim } 3181276479Sdim SemaRef.Diag(S->getLocStart(), diag::err_omp_loop_not_canonical_incr) 3182276479Sdim << S->getSourceRange() << Var; 3183276479Sdim return true; 3184276479Sdim} 3185280031Sdim 3186288943Sdimnamespace { 3187288943Sdim// Transform variables declared in GNU statement expressions to new ones to 3188288943Sdim// avoid crash on codegen. 3189288943Sdimclass TransformToNewDefs : public TreeTransform<TransformToNewDefs> { 3190288943Sdim typedef TreeTransform<TransformToNewDefs> BaseTransform; 3191288943Sdim 3192288943Sdimpublic: 3193288943Sdim TransformToNewDefs(Sema &SemaRef) : BaseTransform(SemaRef) {} 3194288943Sdim 3195288943Sdim Decl *TransformDefinition(SourceLocation Loc, Decl *D) { 3196288943Sdim if (auto *VD = cast<VarDecl>(D)) 3197288943Sdim if (!isa<ParmVarDecl>(D) && !isa<VarTemplateSpecializationDecl>(D) && 3198288943Sdim !isa<ImplicitParamDecl>(D)) { 3199288943Sdim auto *NewVD = VarDecl::Create( 3200288943Sdim SemaRef.Context, VD->getDeclContext(), VD->getLocStart(), 3201288943Sdim VD->getLocation(), VD->getIdentifier(), VD->getType(), 3202288943Sdim VD->getTypeSourceInfo(), VD->getStorageClass()); 3203288943Sdim NewVD->setTSCSpec(VD->getTSCSpec()); 3204288943Sdim NewVD->setInit(VD->getInit()); 3205288943Sdim NewVD->setInitStyle(VD->getInitStyle()); 3206288943Sdim NewVD->setExceptionVariable(VD->isExceptionVariable()); 3207288943Sdim NewVD->setNRVOVariable(VD->isNRVOVariable()); 3208296417Sdim NewVD->setCXXForRangeDecl(VD->isCXXForRangeDecl()); 3209288943Sdim NewVD->setConstexpr(VD->isConstexpr()); 3210288943Sdim NewVD->setInitCapture(VD->isInitCapture()); 3211288943Sdim NewVD->setPreviousDeclInSameBlockScope( 3212288943Sdim VD->isPreviousDeclInSameBlockScope()); 3213288943Sdim VD->getDeclContext()->addHiddenDecl(NewVD); 3214296417Sdim if (VD->hasAttrs()) 3215296417Sdim NewVD->setAttrs(VD->getAttrs()); 3216288943Sdim transformedLocalDecl(VD, NewVD); 3217288943Sdim return NewVD; 3218288943Sdim } 3219288943Sdim return BaseTransform::TransformDefinition(Loc, D); 3220288943Sdim } 3221288943Sdim 3222288943Sdim ExprResult TransformDeclRefExpr(DeclRefExpr *E) { 3223288943Sdim if (auto *NewD = TransformDecl(E->getExprLoc(), E->getDecl())) 3224288943Sdim if (E->getDecl() != NewD) { 3225288943Sdim NewD->setReferenced(); 3226288943Sdim NewD->markUsed(SemaRef.Context); 3227288943Sdim return DeclRefExpr::Create( 3228288943Sdim SemaRef.Context, E->getQualifierLoc(), E->getTemplateKeywordLoc(), 3229288943Sdim cast<ValueDecl>(NewD), E->refersToEnclosingVariableOrCapture(), 3230288943Sdim E->getNameInfo(), E->getType(), E->getValueKind()); 3231288943Sdim } 3232288943Sdim return BaseTransform::TransformDeclRefExpr(E); 3233288943Sdim } 3234288943Sdim}; 3235288943Sdim} 3236288943Sdim 3237280031Sdim/// \brief Build the expression to calculate the number of iterations. 3238280031SdimExpr * 3239280031SdimOpenMPIterationSpaceChecker::BuildNumIterations(Scope *S, 3240280031Sdim const bool LimitedType) const { 3241288943Sdim TransformToNewDefs Transform(SemaRef); 3242280031Sdim ExprResult Diff; 3243288943Sdim auto VarType = Var->getType().getNonReferenceType(); 3244288943Sdim if (VarType->isIntegerType() || VarType->isPointerType() || 3245280031Sdim SemaRef.getLangOpts().CPlusPlus) { 3246280031Sdim // Upper - Lower 3247288943Sdim auto *UBExpr = TestIsLessOp ? UB : LB; 3248288943Sdim auto *LBExpr = TestIsLessOp ? LB : UB; 3249288943Sdim Expr *Upper = Transform.TransformExpr(UBExpr).get(); 3250288943Sdim Expr *Lower = Transform.TransformExpr(LBExpr).get(); 3251288943Sdim if (!Upper || !Lower) 3252288943Sdim return nullptr; 3253296417Sdim if (!SemaRef.Context.hasSameType(Upper->getType(), UBExpr->getType())) { 3254296417Sdim Upper = SemaRef 3255296417Sdim .PerformImplicitConversion(Upper, UBExpr->getType(), 3256296417Sdim Sema::AA_Converting, 3257296417Sdim /*AllowExplicit=*/true) 3258296417Sdim .get(); 3259296417Sdim } 3260296417Sdim if (!SemaRef.Context.hasSameType(Lower->getType(), LBExpr->getType())) { 3261296417Sdim Lower = SemaRef 3262296417Sdim .PerformImplicitConversion(Lower, LBExpr->getType(), 3263296417Sdim Sema::AA_Converting, 3264296417Sdim /*AllowExplicit=*/true) 3265296417Sdim .get(); 3266296417Sdim } 3267288943Sdim if (!Upper || !Lower) 3268288943Sdim return nullptr; 3269280031Sdim 3270280031Sdim Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower); 3271280031Sdim 3272288943Sdim if (!Diff.isUsable() && VarType->getAsCXXRecordDecl()) { 3273280031Sdim // BuildBinOp already emitted error, this one is to point user to upper 3274280031Sdim // and lower bound, and to tell what is passed to 'operator-'. 3275280031Sdim SemaRef.Diag(Upper->getLocStart(), diag::err_omp_loop_diff_cxx) 3276280031Sdim << Upper->getSourceRange() << Lower->getSourceRange(); 3277280031Sdim return nullptr; 3278280031Sdim } 3279280031Sdim } 3280280031Sdim 3281280031Sdim if (!Diff.isUsable()) 3282280031Sdim return nullptr; 3283280031Sdim 3284280031Sdim // Upper - Lower [- 1] 3285280031Sdim if (TestIsStrictOp) 3286280031Sdim Diff = SemaRef.BuildBinOp( 3287280031Sdim S, DefaultLoc, BO_Sub, Diff.get(), 3288280031Sdim SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get()); 3289280031Sdim if (!Diff.isUsable()) 3290280031Sdim return nullptr; 3291280031Sdim 3292280031Sdim // Upper - Lower [- 1] + Step 3293296417Sdim auto *StepNoImp = Step->IgnoreImplicit(); 3294296417Sdim auto NewStep = Transform.TransformExpr(StepNoImp); 3295288943Sdim if (NewStep.isInvalid()) 3296288943Sdim return nullptr; 3297296417Sdim if (!SemaRef.Context.hasSameType(NewStep.get()->getType(), 3298296417Sdim StepNoImp->getType())) { 3299296417Sdim NewStep = SemaRef.PerformImplicitConversion( 3300296417Sdim NewStep.get(), StepNoImp->getType(), Sema::AA_Converting, 3301296417Sdim /*AllowExplicit=*/true); 3302296417Sdim if (NewStep.isInvalid()) 3303296417Sdim return nullptr; 3304296417Sdim } 3305288943Sdim Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get()); 3306280031Sdim if (!Diff.isUsable()) 3307280031Sdim return nullptr; 3308280031Sdim 3309280031Sdim // Parentheses (for dumping/debugging purposes only). 3310280031Sdim Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get()); 3311280031Sdim if (!Diff.isUsable()) 3312280031Sdim return nullptr; 3313280031Sdim 3314280031Sdim // (Upper - Lower [- 1] + Step) / Step 3315296417Sdim NewStep = Transform.TransformExpr(StepNoImp); 3316288943Sdim if (NewStep.isInvalid()) 3317288943Sdim return nullptr; 3318296417Sdim if (!SemaRef.Context.hasSameType(NewStep.get()->getType(), 3319296417Sdim StepNoImp->getType())) { 3320296417Sdim NewStep = SemaRef.PerformImplicitConversion( 3321296417Sdim NewStep.get(), StepNoImp->getType(), Sema::AA_Converting, 3322296417Sdim /*AllowExplicit=*/true); 3323296417Sdim if (NewStep.isInvalid()) 3324296417Sdim return nullptr; 3325296417Sdim } 3326288943Sdim Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get()); 3327280031Sdim if (!Diff.isUsable()) 3328280031Sdim return nullptr; 3329280031Sdim 3330280031Sdim // OpenMP runtime requires 32-bit or 64-bit loop variables. 3331288943Sdim QualType Type = Diff.get()->getType(); 3332288943Sdim auto &C = SemaRef.Context; 3333288943Sdim bool UseVarType = VarType->hasIntegerRepresentation() && 3334288943Sdim C.getTypeSize(Type) > C.getTypeSize(VarType); 3335288943Sdim if (!Type->isIntegerType() || UseVarType) { 3336288943Sdim unsigned NewSize = 3337288943Sdim UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type); 3338288943Sdim bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation() 3339288943Sdim : Type->hasSignedIntegerRepresentation(); 3340288943Sdim Type = C.getIntTypeForBitwidth(NewSize, IsSigned); 3341296417Sdim if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) { 3342296417Sdim Diff = SemaRef.PerformImplicitConversion( 3343296417Sdim Diff.get(), Type, Sema::AA_Converting, /*AllowExplicit=*/true); 3344296417Sdim if (!Diff.isUsable()) 3345296417Sdim return nullptr; 3346296417Sdim } 3347288943Sdim } 3348280031Sdim if (LimitedType) { 3349280031Sdim unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32; 3350280031Sdim if (NewSize != C.getTypeSize(Type)) { 3351280031Sdim if (NewSize < C.getTypeSize(Type)) { 3352280031Sdim assert(NewSize == 64 && "incorrect loop var size"); 3353280031Sdim SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var) 3354280031Sdim << InitSrcRange << ConditionSrcRange; 3355280031Sdim } 3356280031Sdim QualType NewType = C.getIntTypeForBitwidth( 3357288943Sdim NewSize, Type->hasSignedIntegerRepresentation() || 3358288943Sdim C.getTypeSize(Type) < NewSize); 3359296417Sdim if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) { 3360296417Sdim Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType, 3361296417Sdim Sema::AA_Converting, true); 3362296417Sdim if (!Diff.isUsable()) 3363296417Sdim return nullptr; 3364296417Sdim } 3365280031Sdim } 3366280031Sdim } 3367280031Sdim 3368280031Sdim return Diff.get(); 3369280031Sdim} 3370280031Sdim 3371288943SdimExpr *OpenMPIterationSpaceChecker::BuildPreCond(Scope *S, Expr *Cond) const { 3372288943Sdim // Try to build LB <op> UB, where <op> is <, >, <=, or >=. 3373288943Sdim bool Suppress = SemaRef.getDiagnostics().getSuppressAllDiagnostics(); 3374288943Sdim SemaRef.getDiagnostics().setSuppressAllDiagnostics(/*Val=*/true); 3375288943Sdim TransformToNewDefs Transform(SemaRef); 3376288943Sdim 3377288943Sdim auto NewLB = Transform.TransformExpr(LB); 3378288943Sdim auto NewUB = Transform.TransformExpr(UB); 3379288943Sdim if (NewLB.isInvalid() || NewUB.isInvalid()) 3380288943Sdim return Cond; 3381296417Sdim if (!SemaRef.Context.hasSameType(NewLB.get()->getType(), LB->getType())) { 3382296417Sdim NewLB = SemaRef.PerformImplicitConversion(NewLB.get(), LB->getType(), 3383296417Sdim Sema::AA_Converting, 3384296417Sdim /*AllowExplicit=*/true); 3385296417Sdim } 3386296417Sdim if (!SemaRef.Context.hasSameType(NewUB.get()->getType(), UB->getType())) { 3387296417Sdim NewUB = SemaRef.PerformImplicitConversion(NewUB.get(), UB->getType(), 3388296417Sdim Sema::AA_Converting, 3389296417Sdim /*AllowExplicit=*/true); 3390296417Sdim } 3391288943Sdim if (NewLB.isInvalid() || NewUB.isInvalid()) 3392288943Sdim return Cond; 3393288943Sdim auto CondExpr = SemaRef.BuildBinOp( 3394288943Sdim S, DefaultLoc, TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE) 3395288943Sdim : (TestIsStrictOp ? BO_GT : BO_GE), 3396288943Sdim NewLB.get(), NewUB.get()); 3397288943Sdim if (CondExpr.isUsable()) { 3398296417Sdim if (!SemaRef.Context.hasSameType(CondExpr.get()->getType(), 3399296417Sdim SemaRef.Context.BoolTy)) 3400296417Sdim CondExpr = SemaRef.PerformImplicitConversion( 3401296417Sdim CondExpr.get(), SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting, 3402296417Sdim /*AllowExplicit=*/true); 3403288943Sdim } 3404288943Sdim SemaRef.getDiagnostics().setSuppressAllDiagnostics(Suppress); 3405288943Sdim // Otherwise use original loop conditon and evaluate it in runtime. 3406288943Sdim return CondExpr.isUsable() ? CondExpr.get() : Cond; 3407288943Sdim} 3408288943Sdim 3409280031Sdim/// \brief Build reference expression to the counter be used for codegen. 3410280031SdimExpr *OpenMPIterationSpaceChecker::BuildCounterVar() const { 3411296417Sdim return buildDeclRefExpr(SemaRef, Var, Var->getType().getNonReferenceType(), 3412296417Sdim DefaultLoc); 3413280031Sdim} 3414280031Sdim 3415296417SdimExpr *OpenMPIterationSpaceChecker::BuildPrivateCounterVar() const { 3416296417Sdim if (Var && !Var->isInvalidDecl()) { 3417296417Sdim auto Type = Var->getType().getNonReferenceType(); 3418296417Sdim auto *PrivateVar = 3419296417Sdim buildVarDecl(SemaRef, DefaultLoc, Type, Var->getName(), 3420296417Sdim Var->hasAttrs() ? &Var->getAttrs() : nullptr); 3421296417Sdim if (PrivateVar->isInvalidDecl()) 3422296417Sdim return nullptr; 3423296417Sdim return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc); 3424296417Sdim } 3425296417Sdim return nullptr; 3426296417Sdim} 3427296417Sdim 3428280031Sdim/// \brief Build initization of the counter be used for codegen. 3429280031SdimExpr *OpenMPIterationSpaceChecker::BuildCounterInit() const { return LB; } 3430280031Sdim 3431280031Sdim/// \brief Build step of the counter be used for codegen. 3432280031SdimExpr *OpenMPIterationSpaceChecker::BuildCounterStep() const { return Step; } 3433280031Sdim 3434280031Sdim/// \brief Iteration space of a single for loop. 3435280031Sdimstruct LoopIterationSpace { 3436288943Sdim /// \brief Condition of the loop. 3437288943Sdim Expr *PreCond; 3438280031Sdim /// \brief This expression calculates the number of iterations in the loop. 3439280031Sdim /// It is always possible to calculate it before starting the loop. 3440280031Sdim Expr *NumIterations; 3441280031Sdim /// \brief The loop counter variable. 3442280031Sdim Expr *CounterVar; 3443296417Sdim /// \brief Private loop counter variable. 3444296417Sdim Expr *PrivateCounterVar; 3445280031Sdim /// \brief This is initializer for the initial value of #CounterVar. 3446280031Sdim Expr *CounterInit; 3447280031Sdim /// \brief This is step for the #CounterVar used to generate its update: 3448280031Sdim /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration. 3449280031Sdim Expr *CounterStep; 3450280031Sdim /// \brief Should step be subtracted? 3451280031Sdim bool Subtract; 3452280031Sdim /// \brief Source range of the loop init. 3453280031Sdim SourceRange InitSrcRange; 3454280031Sdim /// \brief Source range of the loop condition. 3455280031Sdim SourceRange CondSrcRange; 3456280031Sdim /// \brief Source range of the loop increment. 3457280031Sdim SourceRange IncSrcRange; 3458280031Sdim}; 3459280031Sdim 3460276479Sdim} // namespace 3461276479Sdim 3462288943Sdimvoid Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) { 3463288943Sdim assert(getLangOpts().OpenMP && "OpenMP is not active."); 3464288943Sdim assert(Init && "Expected loop in canonical form."); 3465296417Sdim unsigned AssociatedLoops = DSAStack->getAssociatedLoops(); 3466296417Sdim if (AssociatedLoops > 0 && 3467288943Sdim isOpenMPLoopDirective(DSAStack->getCurrentDirective())) { 3468288943Sdim OpenMPIterationSpaceChecker ISC(*this, ForLoc); 3469296417Sdim if (!ISC.CheckInit(Init, /*EmitDiags=*/false)) 3470288943Sdim DSAStack->addLoopControlVariable(ISC.GetLoopVar()); 3471296417Sdim DSAStack->setAssociatedLoops(AssociatedLoops - 1); 3472288943Sdim } 3473288943Sdim} 3474288943Sdim 3475276479Sdim/// \brief Called on a for stmt to check and extract its iteration space 3476276479Sdim/// for further processing (such as collapsing). 3477276479Sdimstatic bool CheckOpenMPIterationSpace( 3478276479Sdim OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA, 3479276479Sdim unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, 3480296417Sdim Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, 3481280031Sdim llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA, 3482280031Sdim LoopIterationSpace &ResultIterSpace) { 3483276479Sdim // OpenMP [2.6, Canonical Loop Form] 3484276479Sdim // for (init-expr; test-expr; incr-expr) structured-block 3485276479Sdim auto For = dyn_cast_or_null<ForStmt>(S); 3486276479Sdim if (!For) { 3487276479Sdim SemaRef.Diag(S->getLocStart(), diag::err_omp_not_for) 3488296417Sdim << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr) 3489296417Sdim << getOpenMPDirectiveName(DKind) << NestedLoopCount 3490296417Sdim << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount; 3491296417Sdim if (NestedLoopCount > 1) { 3492296417Sdim if (CollapseLoopCountExpr && OrderedLoopCountExpr) 3493296417Sdim SemaRef.Diag(DSA.getConstructLoc(), 3494296417Sdim diag::note_omp_collapse_ordered_expr) 3495296417Sdim << 2 << CollapseLoopCountExpr->getSourceRange() 3496296417Sdim << OrderedLoopCountExpr->getSourceRange(); 3497296417Sdim else if (CollapseLoopCountExpr) 3498296417Sdim SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(), 3499296417Sdim diag::note_omp_collapse_ordered_expr) 3500296417Sdim << 0 << CollapseLoopCountExpr->getSourceRange(); 3501296417Sdim else 3502296417Sdim SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(), 3503296417Sdim diag::note_omp_collapse_ordered_expr) 3504296417Sdim << 1 << OrderedLoopCountExpr->getSourceRange(); 3505296417Sdim } 3506276479Sdim return true; 3507276479Sdim } 3508276479Sdim assert(For->getBody()); 3509276479Sdim 3510276479Sdim OpenMPIterationSpaceChecker ISC(SemaRef, For->getForLoc()); 3511276479Sdim 3512276479Sdim // Check init. 3513276479Sdim auto Init = For->getInit(); 3514276479Sdim if (ISC.CheckInit(Init)) { 3515276479Sdim return true; 3516276479Sdim } 3517276479Sdim 3518276479Sdim bool HasErrors = false; 3519276479Sdim 3520276479Sdim // Check loop variable's type. 3521276479Sdim auto Var = ISC.GetLoopVar(); 3522276479Sdim 3523276479Sdim // OpenMP [2.6, Canonical Loop Form] 3524276479Sdim // Var is one of the following: 3525276479Sdim // A variable of signed or unsigned integer type. 3526276479Sdim // For C++, a variable of a random access iterator type. 3527276479Sdim // For C, a variable of a pointer type. 3528296417Sdim auto VarType = Var->getType().getNonReferenceType(); 3529276479Sdim if (!VarType->isDependentType() && !VarType->isIntegerType() && 3530276479Sdim !VarType->isPointerType() && 3531276479Sdim !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) { 3532276479Sdim SemaRef.Diag(Init->getLocStart(), diag::err_omp_loop_variable_type) 3533276479Sdim << SemaRef.getLangOpts().CPlusPlus; 3534276479Sdim HasErrors = true; 3535276479Sdim } 3536276479Sdim 3537276479Sdim // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in a 3538276479Sdim // Construct 3539276479Sdim // The loop iteration variable(s) in the associated for-loop(s) of a for or 3540276479Sdim // parallel for construct is (are) private. 3541276479Sdim // The loop iteration variable in the associated for-loop of a simd construct 3542276479Sdim // with just one associated for-loop is linear with a constant-linear-step 3543276479Sdim // that is the increment of the associated for-loop. 3544276479Sdim // Exclude loop var from the list of variables with implicitly defined data 3545276479Sdim // sharing attributes. 3546280031Sdim VarsWithImplicitDSA.erase(Var); 3547276479Sdim 3548276479Sdim // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced in 3549276479Sdim // a Construct, C/C++]. 3550276479Sdim // The loop iteration variable in the associated for-loop of a simd construct 3551276479Sdim // with just one associated for-loop may be listed in a linear clause with a 3552276479Sdim // constant-linear-step that is the increment of the associated for-loop. 3553276479Sdim // The loop iteration variable(s) in the associated for-loop(s) of a for or 3554276479Sdim // parallel for construct may be listed in a private or lastprivate clause. 3555276479Sdim DSAStackTy::DSAVarData DVar = DSA.getTopDSA(Var, false); 3556280031Sdim auto LoopVarRefExpr = ISC.GetLoopVarRefExpr(); 3557280031Sdim // If LoopVarRefExpr is nullptr it means the corresponding loop variable is 3558280031Sdim // declared in the loop and it is predetermined as a private. 3559276479Sdim auto PredeterminedCKind = 3560276479Sdim isOpenMPSimdDirective(DKind) 3561276479Sdim ? ((NestedLoopCount == 1) ? OMPC_linear : OMPC_lastprivate) 3562276479Sdim : OMPC_private; 3563276479Sdim if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown && 3564296417Sdim DVar.CKind != PredeterminedCKind) || 3565296417Sdim ((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop || 3566296417Sdim isOpenMPDistributeDirective(DKind)) && 3567296417Sdim !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown && 3568296417Sdim DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) && 3569296417Sdim (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) { 3570276479Sdim SemaRef.Diag(Init->getLocStart(), diag::err_omp_loop_var_dsa) 3571276479Sdim << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind) 3572276479Sdim << getOpenMPClauseName(PredeterminedCKind); 3573288943Sdim if (DVar.RefExpr == nullptr) 3574288943Sdim DVar.CKind = PredeterminedCKind; 3575288943Sdim ReportOriginalDSA(SemaRef, &DSA, Var, DVar, /*IsLoopIterVar=*/true); 3576276479Sdim HasErrors = true; 3577280031Sdim } else if (LoopVarRefExpr != nullptr) { 3578276479Sdim // Make the loop iteration variable private (for worksharing constructs), 3579276479Sdim // linear (for simd directives with the only one associated loop) or 3580296417Sdim // lastprivate (for simd directives with several collapsed or ordered 3581296417Sdim // loops). 3582280031Sdim if (DVar.CKind == OMPC_unknown) 3583280031Sdim DVar = DSA.hasDSA(Var, isOpenMPPrivate, MatchesAlways(), 3584280031Sdim /*FromParent=*/false); 3585288943Sdim DSA.addDSA(Var, LoopVarRefExpr, PredeterminedCKind); 3586276479Sdim } 3587276479Sdim 3588276479Sdim assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars"); 3589276479Sdim 3590276479Sdim // Check test-expr. 3591276479Sdim HasErrors |= ISC.CheckCond(For->getCond()); 3592276479Sdim 3593276479Sdim // Check incr-expr. 3594276479Sdim HasErrors |= ISC.CheckInc(For->getInc()); 3595276479Sdim 3596280031Sdim if (ISC.Dependent() || SemaRef.CurContext->isDependentContext() || HasErrors) 3597276479Sdim return HasErrors; 3598276479Sdim 3599280031Sdim // Build the loop's iteration space representation. 3600288943Sdim ResultIterSpace.PreCond = ISC.BuildPreCond(DSA.getCurScope(), For->getCond()); 3601280031Sdim ResultIterSpace.NumIterations = ISC.BuildNumIterations( 3602296417Sdim DSA.getCurScope(), (isOpenMPWorksharingDirective(DKind) || 3603296417Sdim isOpenMPTaskLoopDirective(DKind) || 3604296417Sdim isOpenMPDistributeDirective(DKind))); 3605280031Sdim ResultIterSpace.CounterVar = ISC.BuildCounterVar(); 3606296417Sdim ResultIterSpace.PrivateCounterVar = ISC.BuildPrivateCounterVar(); 3607280031Sdim ResultIterSpace.CounterInit = ISC.BuildCounterInit(); 3608280031Sdim ResultIterSpace.CounterStep = ISC.BuildCounterStep(); 3609280031Sdim ResultIterSpace.InitSrcRange = ISC.GetInitSrcRange(); 3610280031Sdim ResultIterSpace.CondSrcRange = ISC.GetConditionSrcRange(); 3611280031Sdim ResultIterSpace.IncSrcRange = ISC.GetIncrementSrcRange(); 3612280031Sdim ResultIterSpace.Subtract = ISC.ShouldSubtractStep(); 3613280031Sdim 3614288943Sdim HasErrors |= (ResultIterSpace.PreCond == nullptr || 3615288943Sdim ResultIterSpace.NumIterations == nullptr || 3616280031Sdim ResultIterSpace.CounterVar == nullptr || 3617296417Sdim ResultIterSpace.PrivateCounterVar == nullptr || 3618280031Sdim ResultIterSpace.CounterInit == nullptr || 3619280031Sdim ResultIterSpace.CounterStep == nullptr); 3620280031Sdim 3621276479Sdim return HasErrors; 3622276479Sdim} 3623276479Sdim 3624288943Sdim/// \brief Build 'VarRef = Start. 3625288943Sdimstatic ExprResult BuildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, 3626288943Sdim ExprResult VarRef, ExprResult Start) { 3627288943Sdim TransformToNewDefs Transform(SemaRef); 3628288943Sdim // Build 'VarRef = Start. 3629296417Sdim auto *StartNoImp = Start.get()->IgnoreImplicit(); 3630296417Sdim auto NewStart = Transform.TransformExpr(StartNoImp); 3631288943Sdim if (NewStart.isInvalid()) 3632288943Sdim return ExprError(); 3633296417Sdim if (!SemaRef.Context.hasSameType(NewStart.get()->getType(), 3634296417Sdim StartNoImp->getType())) { 3635296417Sdim NewStart = SemaRef.PerformImplicitConversion( 3636296417Sdim NewStart.get(), StartNoImp->getType(), Sema::AA_Converting, 3637296417Sdim /*AllowExplicit=*/true); 3638296417Sdim if (NewStart.isInvalid()) 3639296417Sdim return ExprError(); 3640296417Sdim } 3641296417Sdim if (!SemaRef.Context.hasSameType(NewStart.get()->getType(), 3642296417Sdim VarRef.get()->getType())) { 3643296417Sdim NewStart = SemaRef.PerformImplicitConversion( 3644296417Sdim NewStart.get(), VarRef.get()->getType(), Sema::AA_Converting, 3645296417Sdim /*AllowExplicit=*/true); 3646296417Sdim if (!NewStart.isUsable()) 3647296417Sdim return ExprError(); 3648296417Sdim } 3649288943Sdim 3650288943Sdim auto Init = 3651288943Sdim SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get()); 3652288943Sdim return Init; 3653276479Sdim} 3654276479Sdim 3655280031Sdim/// \brief Build 'VarRef = Start + Iter * Step'. 3656280031Sdimstatic ExprResult BuildCounterUpdate(Sema &SemaRef, Scope *S, 3657280031Sdim SourceLocation Loc, ExprResult VarRef, 3658280031Sdim ExprResult Start, ExprResult Iter, 3659280031Sdim ExprResult Step, bool Subtract) { 3660280031Sdim // Add parentheses (for debugging purposes only). 3661280031Sdim Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get()); 3662280031Sdim if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() || 3663280031Sdim !Step.isUsable()) 3664280031Sdim return ExprError(); 3665280031Sdim 3666296417Sdim auto *StepNoImp = Step.get()->IgnoreImplicit(); 3667288943Sdim TransformToNewDefs Transform(SemaRef); 3668296417Sdim auto NewStep = Transform.TransformExpr(StepNoImp); 3669288943Sdim if (NewStep.isInvalid()) 3670288943Sdim return ExprError(); 3671296417Sdim if (!SemaRef.Context.hasSameType(NewStep.get()->getType(), 3672296417Sdim StepNoImp->getType())) { 3673296417Sdim NewStep = SemaRef.PerformImplicitConversion( 3674296417Sdim NewStep.get(), StepNoImp->getType(), Sema::AA_Converting, 3675296417Sdim /*AllowExplicit=*/true); 3676296417Sdim if (NewStep.isInvalid()) 3677296417Sdim return ExprError(); 3678296417Sdim } 3679288943Sdim ExprResult Update = 3680288943Sdim SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get()); 3681280031Sdim if (!Update.isUsable()) 3682280031Sdim return ExprError(); 3683280031Sdim 3684280031Sdim // Build 'VarRef = Start + Iter * Step'. 3685296417Sdim auto *StartNoImp = Start.get()->IgnoreImplicit(); 3686296417Sdim auto NewStart = Transform.TransformExpr(StartNoImp); 3687288943Sdim if (NewStart.isInvalid()) 3688288943Sdim return ExprError(); 3689296417Sdim if (!SemaRef.Context.hasSameType(NewStart.get()->getType(), 3690296417Sdim StartNoImp->getType())) { 3691296417Sdim NewStart = SemaRef.PerformImplicitConversion( 3692296417Sdim NewStart.get(), StartNoImp->getType(), Sema::AA_Converting, 3693296417Sdim /*AllowExplicit=*/true); 3694296417Sdim if (NewStart.isInvalid()) 3695296417Sdim return ExprError(); 3696296417Sdim } 3697280031Sdim Update = SemaRef.BuildBinOp(S, Loc, (Subtract ? BO_Sub : BO_Add), 3698288943Sdim NewStart.get(), Update.get()); 3699280031Sdim if (!Update.isUsable()) 3700280031Sdim return ExprError(); 3701280031Sdim 3702280031Sdim Update = SemaRef.PerformImplicitConversion( 3703280031Sdim Update.get(), VarRef.get()->getType(), Sema::AA_Converting, true); 3704280031Sdim if (!Update.isUsable()) 3705280031Sdim return ExprError(); 3706280031Sdim 3707280031Sdim Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get()); 3708280031Sdim return Update; 3709280031Sdim} 3710280031Sdim 3711280031Sdim/// \brief Convert integer expression \a E to make it have at least \a Bits 3712280031Sdim/// bits. 3713280031Sdimstatic ExprResult WidenIterationCount(unsigned Bits, Expr *E, 3714280031Sdim Sema &SemaRef) { 3715280031Sdim if (E == nullptr) 3716280031Sdim return ExprError(); 3717280031Sdim auto &C = SemaRef.Context; 3718280031Sdim QualType OldType = E->getType(); 3719280031Sdim unsigned HasBits = C.getTypeSize(OldType); 3720280031Sdim if (HasBits >= Bits) 3721280031Sdim return ExprResult(E); 3722280031Sdim // OK to convert to signed, because new type has more bits than old. 3723280031Sdim QualType NewType = C.getIntTypeForBitwidth(Bits, /* Signed */ true); 3724280031Sdim return SemaRef.PerformImplicitConversion(E, NewType, Sema::AA_Converting, 3725280031Sdim true); 3726280031Sdim} 3727280031Sdim 3728280031Sdim/// \brief Check if the given expression \a E is a constant integer that fits 3729280031Sdim/// into \a Bits bits. 3730280031Sdimstatic bool FitsInto(unsigned Bits, bool Signed, Expr *E, Sema &SemaRef) { 3731280031Sdim if (E == nullptr) 3732280031Sdim return false; 3733280031Sdim llvm::APSInt Result; 3734280031Sdim if (E->isIntegerConstantExpr(Result, SemaRef.Context)) 3735280031Sdim return Signed ? Result.isSignedIntN(Bits) : Result.isIntN(Bits); 3736280031Sdim return false; 3737280031Sdim} 3738280031Sdim 3739276479Sdim/// \brief Called on a for stmt to check itself and nested loops (if any). 3740276479Sdim/// \return Returns 0 if one of the collapsed stmts is not canonical for loop, 3741276479Sdim/// number of collapsed loops otherwise. 3742276479Sdimstatic unsigned 3743296417SdimCheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, 3744296417Sdim Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef, 3745296417Sdim DSAStackTy &DSA, 3746280031Sdim llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA, 3747280031Sdim OMPLoopDirective::HelperExprs &Built) { 3748276479Sdim unsigned NestedLoopCount = 1; 3749296417Sdim if (CollapseLoopCountExpr) { 3750276479Sdim // Found 'collapse' clause - calculate collapse number. 3751276479Sdim llvm::APSInt Result; 3752296417Sdim if (CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) 3753276479Sdim NestedLoopCount = Result.getLimitedValue(); 3754276479Sdim } 3755296417Sdim if (OrderedLoopCountExpr) { 3756296417Sdim // Found 'ordered' clause - calculate collapse number. 3757296417Sdim llvm::APSInt Result; 3758296417Sdim if (OrderedLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) { 3759296417Sdim if (Result.getLimitedValue() < NestedLoopCount) { 3760296417Sdim SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(), 3761296417Sdim diag::err_omp_wrong_ordered_loop_count) 3762296417Sdim << OrderedLoopCountExpr->getSourceRange(); 3763296417Sdim SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(), 3764296417Sdim diag::note_collapse_loop_count) 3765296417Sdim << CollapseLoopCountExpr->getSourceRange(); 3766296417Sdim } 3767296417Sdim NestedLoopCount = Result.getLimitedValue(); 3768296417Sdim } 3769296417Sdim } 3770276479Sdim // This is helper routine for loop directives (e.g., 'for', 'simd', 3771276479Sdim // 'for simd', etc.). 3772280031Sdim SmallVector<LoopIterationSpace, 4> IterSpaces; 3773280031Sdim IterSpaces.resize(NestedLoopCount); 3774280031Sdim Stmt *CurStmt = AStmt->IgnoreContainers(/* IgnoreCaptured */ true); 3775276479Sdim for (unsigned Cnt = 0; Cnt < NestedLoopCount; ++Cnt) { 3776276479Sdim if (CheckOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA, Cnt, 3777296417Sdim NestedLoopCount, CollapseLoopCountExpr, 3778296417Sdim OrderedLoopCountExpr, VarsWithImplicitDSA, 3779296417Sdim IterSpaces[Cnt])) 3780276479Sdim return 0; 3781276479Sdim // Move on to the next nested for loop, or to the loop body. 3782280031Sdim // OpenMP [2.8.1, simd construct, Restrictions] 3783280031Sdim // All loops associated with the construct must be perfectly nested; that 3784280031Sdim // is, there must be no intervening code nor any OpenMP directive between 3785280031Sdim // any two loops. 3786280031Sdim CurStmt = cast<ForStmt>(CurStmt)->getBody()->IgnoreContainers(); 3787276479Sdim } 3788276479Sdim 3789280031Sdim Built.clear(/* size */ NestedLoopCount); 3790280031Sdim 3791280031Sdim if (SemaRef.CurContext->isDependentContext()) 3792280031Sdim return NestedLoopCount; 3793280031Sdim 3794280031Sdim // An example of what is generated for the following code: 3795280031Sdim // 3796296417Sdim // #pragma omp simd collapse(2) ordered(2) 3797280031Sdim // for (i = 0; i < NI; ++i) 3798296417Sdim // for (k = 0; k < NK; ++k) 3799296417Sdim // for (j = J0; j < NJ; j+=2) { 3800296417Sdim // <loop body> 3801296417Sdim // } 3802280031Sdim // 3803280031Sdim // We generate the code below. 3804280031Sdim // Note: the loop body may be outlined in CodeGen. 3805280031Sdim // Note: some counters may be C++ classes, operator- is used to find number of 3806280031Sdim // iterations and operator+= to calculate counter value. 3807280031Sdim // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32 3808280031Sdim // or i64 is currently supported). 3809280031Sdim // 3810280031Sdim // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2)) 3811280031Sdim // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) { 3812280031Sdim // .local.i = IV / ((NJ - J0 - 1 + 2) / 2); 3813280031Sdim // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2; 3814280031Sdim // // similar updates for vars in clauses (e.g. 'linear') 3815280031Sdim // <loop body (using local i and j)> 3816280031Sdim // } 3817280031Sdim // i = NI; // assign final values of counters 3818280031Sdim // j = NJ; 3819280031Sdim // 3820280031Sdim 3821280031Sdim // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are 3822280031Sdim // the iteration counts of the collapsed for loops. 3823288943Sdim // Precondition tests if there is at least one iteration (all conditions are 3824288943Sdim // true). 3825288943Sdim auto PreCond = ExprResult(IterSpaces[0].PreCond); 3826280031Sdim auto N0 = IterSpaces[0].NumIterations; 3827288943Sdim ExprResult LastIteration32 = WidenIterationCount( 3828288943Sdim 32 /* Bits */, SemaRef.PerformImplicitConversion( 3829288943Sdim N0->IgnoreImpCasts(), N0->getType(), 3830288943Sdim Sema::AA_Converting, /*AllowExplicit=*/true) 3831288943Sdim .get(), 3832288943Sdim SemaRef); 3833288943Sdim ExprResult LastIteration64 = WidenIterationCount( 3834288943Sdim 64 /* Bits */, SemaRef.PerformImplicitConversion( 3835288943Sdim N0->IgnoreImpCasts(), N0->getType(), 3836288943Sdim Sema::AA_Converting, /*AllowExplicit=*/true) 3837288943Sdim .get(), 3838288943Sdim SemaRef); 3839280031Sdim 3840280031Sdim if (!LastIteration32.isUsable() || !LastIteration64.isUsable()) 3841280031Sdim return NestedLoopCount; 3842280031Sdim 3843280031Sdim auto &C = SemaRef.Context; 3844280031Sdim bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32; 3845280031Sdim 3846280031Sdim Scope *CurScope = DSA.getCurScope(); 3847280031Sdim for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) { 3848288943Sdim if (PreCond.isUsable()) { 3849288943Sdim PreCond = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_LAnd, 3850288943Sdim PreCond.get(), IterSpaces[Cnt].PreCond); 3851288943Sdim } 3852280031Sdim auto N = IterSpaces[Cnt].NumIterations; 3853280031Sdim AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32; 3854280031Sdim if (LastIteration32.isUsable()) 3855288943Sdim LastIteration32 = SemaRef.BuildBinOp( 3856288943Sdim CurScope, SourceLocation(), BO_Mul, LastIteration32.get(), 3857288943Sdim SemaRef.PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(), 3858288943Sdim Sema::AA_Converting, 3859288943Sdim /*AllowExplicit=*/true) 3860288943Sdim .get()); 3861280031Sdim if (LastIteration64.isUsable()) 3862288943Sdim LastIteration64 = SemaRef.BuildBinOp( 3863288943Sdim CurScope, SourceLocation(), BO_Mul, LastIteration64.get(), 3864288943Sdim SemaRef.PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(), 3865288943Sdim Sema::AA_Converting, 3866288943Sdim /*AllowExplicit=*/true) 3867288943Sdim .get()); 3868280031Sdim } 3869280031Sdim 3870280031Sdim // Choose either the 32-bit or 64-bit version. 3871280031Sdim ExprResult LastIteration = LastIteration64; 3872280031Sdim if (LastIteration32.isUsable() && 3873280031Sdim C.getTypeSize(LastIteration32.get()->getType()) == 32 && 3874280031Sdim (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 || 3875280031Sdim FitsInto( 3876280031Sdim 32 /* Bits */, 3877280031Sdim LastIteration32.get()->getType()->hasSignedIntegerRepresentation(), 3878280031Sdim LastIteration64.get(), SemaRef))) 3879280031Sdim LastIteration = LastIteration32; 3880280031Sdim 3881280031Sdim if (!LastIteration.isUsable()) 3882280031Sdim return 0; 3883280031Sdim 3884280031Sdim // Save the number of iterations. 3885280031Sdim ExprResult NumIterations = LastIteration; 3886280031Sdim { 3887280031Sdim LastIteration = SemaRef.BuildBinOp( 3888280031Sdim CurScope, SourceLocation(), BO_Sub, LastIteration.get(), 3889280031Sdim SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get()); 3890280031Sdim if (!LastIteration.isUsable()) 3891280031Sdim return 0; 3892280031Sdim } 3893280031Sdim 3894280031Sdim // Calculate the last iteration number beforehand instead of doing this on 3895280031Sdim // each iteration. Do not do this if the number of iterations may be kfold-ed. 3896280031Sdim llvm::APSInt Result; 3897280031Sdim bool IsConstant = 3898280031Sdim LastIteration.get()->isIntegerConstantExpr(Result, SemaRef.Context); 3899280031Sdim ExprResult CalcLastIteration; 3900280031Sdim if (!IsConstant) { 3901280031Sdim SourceLocation SaveLoc; 3902280031Sdim VarDecl *SaveVar = 3903288943Sdim buildVarDecl(SemaRef, SaveLoc, LastIteration.get()->getType(), 3904280031Sdim ".omp.last.iteration"); 3905288943Sdim ExprResult SaveRef = buildDeclRefExpr( 3906288943Sdim SemaRef, SaveVar, LastIteration.get()->getType(), SaveLoc); 3907280031Sdim CalcLastIteration = SemaRef.BuildBinOp(CurScope, SaveLoc, BO_Assign, 3908280031Sdim SaveRef.get(), LastIteration.get()); 3909280031Sdim LastIteration = SaveRef; 3910280031Sdim 3911280031Sdim // Prepare SaveRef + 1. 3912280031Sdim NumIterations = SemaRef.BuildBinOp( 3913280031Sdim CurScope, SaveLoc, BO_Add, SaveRef.get(), 3914280031Sdim SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get()); 3915280031Sdim if (!NumIterations.isUsable()) 3916280031Sdim return 0; 3917280031Sdim } 3918280031Sdim 3919280031Sdim SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin(); 3920280031Sdim 3921280031Sdim QualType VType = LastIteration.get()->getType(); 3922280031Sdim // Build variables passed into runtime, nesessary for worksharing directives. 3923280031Sdim ExprResult LB, UB, IL, ST, EUB; 3924296417Sdim if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) || 3925296417Sdim isOpenMPDistributeDirective(DKind)) { 3926280031Sdim // Lower bound variable, initialized with zero. 3927288943Sdim VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb"); 3928288943Sdim LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc); 3929280031Sdim SemaRef.AddInitializerToDecl( 3930280031Sdim LBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(), 3931280031Sdim /*DirectInit*/ false, /*TypeMayContainAuto*/ false); 3932280031Sdim 3933280031Sdim // Upper bound variable, initialized with last iteration number. 3934288943Sdim VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub"); 3935288943Sdim UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc); 3936280031Sdim SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(), 3937280031Sdim /*DirectInit*/ false, 3938280031Sdim /*TypeMayContainAuto*/ false); 3939280031Sdim 3940280031Sdim // A 32-bit variable-flag where runtime returns 1 for the last iteration. 3941280031Sdim // This will be used to implement clause 'lastprivate'. 3942280031Sdim QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true); 3943288943Sdim VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last"); 3944288943Sdim IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc); 3945280031Sdim SemaRef.AddInitializerToDecl( 3946280031Sdim ILDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(), 3947280031Sdim /*DirectInit*/ false, /*TypeMayContainAuto*/ false); 3948280031Sdim 3949280031Sdim // Stride variable returned by runtime (we initialize it to 1 by default). 3950288943Sdim VarDecl *STDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.stride"); 3951288943Sdim ST = buildDeclRefExpr(SemaRef, STDecl, VType, InitLoc); 3952280031Sdim SemaRef.AddInitializerToDecl( 3953280031Sdim STDecl, SemaRef.ActOnIntegerConstant(InitLoc, 1).get(), 3954280031Sdim /*DirectInit*/ false, /*TypeMayContainAuto*/ false); 3955280031Sdim 3956280031Sdim // Build expression: UB = min(UB, LastIteration) 3957280031Sdim // It is nesessary for CodeGen of directives with static scheduling. 3958280031Sdim ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT, 3959280031Sdim UB.get(), LastIteration.get()); 3960280031Sdim ExprResult CondOp = SemaRef.ActOnConditionalOp( 3961280031Sdim InitLoc, InitLoc, IsUBGreater.get(), LastIteration.get(), UB.get()); 3962280031Sdim EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(), 3963280031Sdim CondOp.get()); 3964280031Sdim EUB = SemaRef.ActOnFinishFullExpr(EUB.get()); 3965280031Sdim } 3966280031Sdim 3967280031Sdim // Build the iteration variable and its initialization before loop. 3968280031Sdim ExprResult IV; 3969280031Sdim ExprResult Init; 3970280031Sdim { 3971288943Sdim VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.iv"); 3972288943Sdim IV = buildDeclRefExpr(SemaRef, IVDecl, VType, InitLoc); 3973296417Sdim Expr *RHS = (isOpenMPWorksharingDirective(DKind) || 3974296417Sdim isOpenMPTaskLoopDirective(DKind) || 3975296417Sdim isOpenMPDistributeDirective(DKind)) 3976280031Sdim ? LB.get() 3977280031Sdim : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); 3978280031Sdim Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS); 3979280031Sdim Init = SemaRef.ActOnFinishFullExpr(Init.get()); 3980280031Sdim } 3981280031Sdim 3982280031Sdim // Loop condition (IV < NumIterations) or (IV <= UB) for worksharing loops. 3983280031Sdim SourceLocation CondLoc; 3984280031Sdim ExprResult Cond = 3985296417Sdim (isOpenMPWorksharingDirective(DKind) || 3986296417Sdim isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind)) 3987280031Sdim ? SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), UB.get()) 3988280031Sdim : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(), 3989280031Sdim NumIterations.get()); 3990280031Sdim 3991280031Sdim // Loop increment (IV = IV + 1) 3992280031Sdim SourceLocation IncLoc; 3993280031Sdim ExprResult Inc = 3994280031Sdim SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(), 3995280031Sdim SemaRef.ActOnIntegerConstant(IncLoc, 1).get()); 3996280031Sdim if (!Inc.isUsable()) 3997280031Sdim return 0; 3998280031Sdim Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get()); 3999280031Sdim Inc = SemaRef.ActOnFinishFullExpr(Inc.get()); 4000280031Sdim if (!Inc.isUsable()) 4001280031Sdim return 0; 4002280031Sdim 4003280031Sdim // Increments for worksharing loops (LB = LB + ST; UB = UB + ST). 4004280031Sdim // Used for directives with static scheduling. 4005280031Sdim ExprResult NextLB, NextUB; 4006296417Sdim if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) || 4007296417Sdim isOpenMPDistributeDirective(DKind)) { 4008280031Sdim // LB + ST 4009280031Sdim NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get()); 4010280031Sdim if (!NextLB.isUsable()) 4011280031Sdim return 0; 4012280031Sdim // LB = LB + ST 4013280031Sdim NextLB = 4014280031Sdim SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get()); 4015280031Sdim NextLB = SemaRef.ActOnFinishFullExpr(NextLB.get()); 4016280031Sdim if (!NextLB.isUsable()) 4017280031Sdim return 0; 4018280031Sdim // UB + ST 4019280031Sdim NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get()); 4020280031Sdim if (!NextUB.isUsable()) 4021280031Sdim return 0; 4022280031Sdim // UB = UB + ST 4023280031Sdim NextUB = 4024280031Sdim SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get()); 4025280031Sdim NextUB = SemaRef.ActOnFinishFullExpr(NextUB.get()); 4026280031Sdim if (!NextUB.isUsable()) 4027280031Sdim return 0; 4028280031Sdim } 4029280031Sdim 4030280031Sdim // Build updates and final values of the loop counters. 4031280031Sdim bool HasErrors = false; 4032280031Sdim Built.Counters.resize(NestedLoopCount); 4033288943Sdim Built.Inits.resize(NestedLoopCount); 4034280031Sdim Built.Updates.resize(NestedLoopCount); 4035280031Sdim Built.Finals.resize(NestedLoopCount); 4036280031Sdim { 4037280031Sdim ExprResult Div; 4038280031Sdim // Go from inner nested loop to outer. 4039280031Sdim for (int Cnt = NestedLoopCount - 1; Cnt >= 0; --Cnt) { 4040280031Sdim LoopIterationSpace &IS = IterSpaces[Cnt]; 4041280031Sdim SourceLocation UpdLoc = IS.IncSrcRange.getBegin(); 4042280031Sdim // Build: Iter = (IV / Div) % IS.NumIters 4043280031Sdim // where Div is product of previous iterations' IS.NumIters. 4044280031Sdim ExprResult Iter; 4045280031Sdim if (Div.isUsable()) { 4046280031Sdim Iter = 4047280031Sdim SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, IV.get(), Div.get()); 4048280031Sdim } else { 4049280031Sdim Iter = IV; 4050280031Sdim assert((Cnt == (int)NestedLoopCount - 1) && 4051280031Sdim "unusable div expected on first iteration only"); 4052280031Sdim } 4053280031Sdim 4054280031Sdim if (Cnt != 0 && Iter.isUsable()) 4055280031Sdim Iter = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Rem, Iter.get(), 4056280031Sdim IS.NumIterations); 4057280031Sdim if (!Iter.isUsable()) { 4058280031Sdim HasErrors = true; 4059280031Sdim break; 4060280031Sdim } 4061280031Sdim 4062288943Sdim // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step 4063288943Sdim auto *CounterVar = buildDeclRefExpr( 4064288943Sdim SemaRef, cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl()), 4065288943Sdim IS.CounterVar->getType(), IS.CounterVar->getExprLoc(), 4066288943Sdim /*RefersToCapture=*/true); 4067288943Sdim ExprResult Init = BuildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar, 4068288943Sdim IS.CounterInit); 4069288943Sdim if (!Init.isUsable()) { 4070288943Sdim HasErrors = true; 4071288943Sdim break; 4072288943Sdim } 4073280031Sdim ExprResult Update = 4074288943Sdim BuildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar, 4075280031Sdim IS.CounterInit, Iter, IS.CounterStep, IS.Subtract); 4076280031Sdim if (!Update.isUsable()) { 4077280031Sdim HasErrors = true; 4078280031Sdim break; 4079280031Sdim } 4080280031Sdim 4081280031Sdim // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step 4082280031Sdim ExprResult Final = BuildCounterUpdate( 4083288943Sdim SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, 4084280031Sdim IS.NumIterations, IS.CounterStep, IS.Subtract); 4085280031Sdim if (!Final.isUsable()) { 4086280031Sdim HasErrors = true; 4087280031Sdim break; 4088280031Sdim } 4089280031Sdim 4090280031Sdim // Build Div for the next iteration: Div <- Div * IS.NumIters 4091280031Sdim if (Cnt != 0) { 4092280031Sdim if (Div.isUnset()) 4093280031Sdim Div = IS.NumIterations; 4094280031Sdim else 4095280031Sdim Div = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Div.get(), 4096280031Sdim IS.NumIterations); 4097280031Sdim 4098280031Sdim // Add parentheses (for debugging purposes only). 4099280031Sdim if (Div.isUsable()) 4100280031Sdim Div = SemaRef.ActOnParenExpr(UpdLoc, UpdLoc, Div.get()); 4101280031Sdim if (!Div.isUsable()) { 4102280031Sdim HasErrors = true; 4103280031Sdim break; 4104280031Sdim } 4105280031Sdim } 4106280031Sdim if (!Update.isUsable() || !Final.isUsable()) { 4107280031Sdim HasErrors = true; 4108280031Sdim break; 4109280031Sdim } 4110280031Sdim // Save results 4111280031Sdim Built.Counters[Cnt] = IS.CounterVar; 4112296417Sdim Built.PrivateCounters[Cnt] = IS.PrivateCounterVar; 4113288943Sdim Built.Inits[Cnt] = Init.get(); 4114280031Sdim Built.Updates[Cnt] = Update.get(); 4115280031Sdim Built.Finals[Cnt] = Final.get(); 4116280031Sdim } 4117280031Sdim } 4118280031Sdim 4119280031Sdim if (HasErrors) 4120280031Sdim return 0; 4121280031Sdim 4122280031Sdim // Save results 4123280031Sdim Built.IterationVarRef = IV.get(); 4124280031Sdim Built.LastIteration = LastIteration.get(); 4125288943Sdim Built.NumIterations = NumIterations.get(); 4126288943Sdim Built.CalcLastIteration = 4127288943Sdim SemaRef.ActOnFinishFullExpr(CalcLastIteration.get()).get(); 4128280031Sdim Built.PreCond = PreCond.get(); 4129280031Sdim Built.Cond = Cond.get(); 4130280031Sdim Built.Init = Init.get(); 4131280031Sdim Built.Inc = Inc.get(); 4132280031Sdim Built.LB = LB.get(); 4133280031Sdim Built.UB = UB.get(); 4134280031Sdim Built.IL = IL.get(); 4135280031Sdim Built.ST = ST.get(); 4136280031Sdim Built.EUB = EUB.get(); 4137280031Sdim Built.NLB = NextLB.get(); 4138280031Sdim Built.NUB = NextUB.get(); 4139280031Sdim 4140276479Sdim return NestedLoopCount; 4141276479Sdim} 4142276479Sdim 4143296417Sdimstatic Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) { 4144296417Sdim auto CollapseClauses = 4145296417Sdim OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses); 4146296417Sdim if (CollapseClauses.begin() != CollapseClauses.end()) 4147296417Sdim return (*CollapseClauses.begin())->getNumForLoops(); 4148276479Sdim return nullptr; 4149276479Sdim} 4150276479Sdim 4151296417Sdimstatic Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) { 4152296417Sdim auto OrderedClauses = 4153296417Sdim OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses); 4154296417Sdim if (OrderedClauses.begin() != OrderedClauses.end()) 4155296417Sdim return (*OrderedClauses.begin())->getNumForLoops(); 4156296417Sdim return nullptr; 4157296417Sdim} 4158296417Sdim 4159296417Sdimstatic bool checkSimdlenSafelenValues(Sema &S, const Expr *Simdlen, 4160296417Sdim const Expr *Safelen) { 4161296417Sdim llvm::APSInt SimdlenRes, SafelenRes; 4162296417Sdim if (Simdlen->isValueDependent() || Simdlen->isTypeDependent() || 4163296417Sdim Simdlen->isInstantiationDependent() || 4164296417Sdim Simdlen->containsUnexpandedParameterPack()) 4165296417Sdim return false; 4166296417Sdim if (Safelen->isValueDependent() || Safelen->isTypeDependent() || 4167296417Sdim Safelen->isInstantiationDependent() || 4168296417Sdim Safelen->containsUnexpandedParameterPack()) 4169296417Sdim return false; 4170296417Sdim Simdlen->EvaluateAsInt(SimdlenRes, S.Context); 4171296417Sdim Safelen->EvaluateAsInt(SafelenRes, S.Context); 4172296417Sdim // OpenMP 4.1 [2.8.1, simd Construct, Restrictions] 4173296417Sdim // If both simdlen and safelen clauses are specified, the value of the simdlen 4174296417Sdim // parameter must be less than or equal to the value of the safelen parameter. 4175296417Sdim if (SimdlenRes > SafelenRes) { 4176296417Sdim S.Diag(Simdlen->getExprLoc(), diag::err_omp_wrong_simdlen_safelen_values) 4177296417Sdim << Simdlen->getSourceRange() << Safelen->getSourceRange(); 4178296417Sdim return true; 4179296417Sdim } 4180296417Sdim return false; 4181296417Sdim} 4182296417Sdim 4183276479SdimStmtResult Sema::ActOnOpenMPSimdDirective( 4184276479Sdim ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 4185276479Sdim SourceLocation EndLoc, 4186276479Sdim llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { 4187296417Sdim if (!AStmt) 4188296417Sdim return StmtError(); 4189296417Sdim 4190296417Sdim assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 4191280031Sdim OMPLoopDirective::HelperExprs B; 4192296417Sdim // In presence of clause 'collapse' or 'ordered' with number of loops, it will 4193296417Sdim // define the nested loops number. 4194296417Sdim unsigned NestedLoopCount = CheckOpenMPLoop( 4195296417Sdim OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses), 4196296417Sdim AStmt, *this, *DSAStack, VarsWithImplicitDSA, B); 4197276479Sdim if (NestedLoopCount == 0) 4198276479Sdim return StmtError(); 4199276479Sdim 4200280031Sdim assert((CurContext->isDependentContext() || B.builtAll()) && 4201280031Sdim "omp simd loop exprs were not built"); 4202280031Sdim 4203288943Sdim if (!CurContext->isDependentContext()) { 4204288943Sdim // Finalize the clauses that need pre-built expressions for CodeGen. 4205288943Sdim for (auto C : Clauses) { 4206288943Sdim if (auto LC = dyn_cast<OMPLinearClause>(C)) 4207288943Sdim if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef), 4208288943Sdim B.NumIterations, *this, CurScope)) 4209288943Sdim return StmtError(); 4210288943Sdim } 4211288943Sdim } 4212288943Sdim 4213296417Sdim // OpenMP 4.1 [2.8.1, simd Construct, Restrictions] 4214296417Sdim // If both simdlen and safelen clauses are specified, the value of the simdlen 4215296417Sdim // parameter must be less than or equal to the value of the safelen parameter. 4216296417Sdim OMPSafelenClause *Safelen = nullptr; 4217296417Sdim OMPSimdlenClause *Simdlen = nullptr; 4218296417Sdim for (auto *Clause : Clauses) { 4219296417Sdim if (Clause->getClauseKind() == OMPC_safelen) 4220296417Sdim Safelen = cast<OMPSafelenClause>(Clause); 4221296417Sdim else if (Clause->getClauseKind() == OMPC_simdlen) 4222296417Sdim Simdlen = cast<OMPSimdlenClause>(Clause); 4223296417Sdim if (Safelen && Simdlen) 4224296417Sdim break; 4225296417Sdim } 4226296417Sdim if (Simdlen && Safelen && 4227296417Sdim checkSimdlenSafelenValues(*this, Simdlen->getSimdlen(), 4228296417Sdim Safelen->getSafelen())) 4229296417Sdim return StmtError(); 4230296417Sdim 4231276479Sdim getCurFunction()->setHasBranchProtectedScope(); 4232276479Sdim return OMPSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount, 4233280031Sdim Clauses, AStmt, B); 4234276479Sdim} 4235276479Sdim 4236276479SdimStmtResult Sema::ActOnOpenMPForDirective( 4237276479Sdim ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 4238276479Sdim SourceLocation EndLoc, 4239276479Sdim llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { 4240296417Sdim if (!AStmt) 4241296417Sdim return StmtError(); 4242296417Sdim 4243296417Sdim assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 4244280031Sdim OMPLoopDirective::HelperExprs B; 4245296417Sdim // In presence of clause 'collapse' or 'ordered' with number of loops, it will 4246296417Sdim // define the nested loops number. 4247296417Sdim unsigned NestedLoopCount = CheckOpenMPLoop( 4248296417Sdim OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses), 4249296417Sdim AStmt, *this, *DSAStack, VarsWithImplicitDSA, B); 4250276479Sdim if (NestedLoopCount == 0) 4251276479Sdim return StmtError(); 4252276479Sdim 4253280031Sdim assert((CurContext->isDependentContext() || B.builtAll()) && 4254280031Sdim "omp for loop exprs were not built"); 4255280031Sdim 4256296417Sdim if (!CurContext->isDependentContext()) { 4257296417Sdim // Finalize the clauses that need pre-built expressions for CodeGen. 4258296417Sdim for (auto C : Clauses) { 4259296417Sdim if (auto LC = dyn_cast<OMPLinearClause>(C)) 4260296417Sdim if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef), 4261296417Sdim B.NumIterations, *this, CurScope)) 4262296417Sdim return StmtError(); 4263296417Sdim } 4264296417Sdim } 4265296417Sdim 4266276479Sdim getCurFunction()->setHasBranchProtectedScope(); 4267276479Sdim return OMPForDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount, 4268296417Sdim Clauses, AStmt, B, DSAStack->isCancelRegion()); 4269276479Sdim} 4270276479Sdim 4271280031SdimStmtResult Sema::ActOnOpenMPForSimdDirective( 4272280031Sdim ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 4273280031Sdim SourceLocation EndLoc, 4274280031Sdim llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { 4275296417Sdim if (!AStmt) 4276296417Sdim return StmtError(); 4277296417Sdim 4278296417Sdim assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 4279280031Sdim OMPLoopDirective::HelperExprs B; 4280296417Sdim // In presence of clause 'collapse' or 'ordered' with number of loops, it will 4281296417Sdim // define the nested loops number. 4282280031Sdim unsigned NestedLoopCount = 4283296417Sdim CheckOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses), 4284296417Sdim getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack, 4285296417Sdim VarsWithImplicitDSA, B); 4286280031Sdim if (NestedLoopCount == 0) 4287280031Sdim return StmtError(); 4288280031Sdim 4289280031Sdim assert((CurContext->isDependentContext() || B.builtAll()) && 4290280031Sdim "omp for simd loop exprs were not built"); 4291280031Sdim 4292288943Sdim if (!CurContext->isDependentContext()) { 4293288943Sdim // Finalize the clauses that need pre-built expressions for CodeGen. 4294288943Sdim for (auto C : Clauses) { 4295288943Sdim if (auto LC = dyn_cast<OMPLinearClause>(C)) 4296288943Sdim if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef), 4297288943Sdim B.NumIterations, *this, CurScope)) 4298288943Sdim return StmtError(); 4299288943Sdim } 4300288943Sdim } 4301288943Sdim 4302296417Sdim // OpenMP 4.1 [2.8.1, simd Construct, Restrictions] 4303296417Sdim // If both simdlen and safelen clauses are specified, the value of the simdlen 4304296417Sdim // parameter must be less than or equal to the value of the safelen parameter. 4305296417Sdim OMPSafelenClause *Safelen = nullptr; 4306296417Sdim OMPSimdlenClause *Simdlen = nullptr; 4307296417Sdim for (auto *Clause : Clauses) { 4308296417Sdim if (Clause->getClauseKind() == OMPC_safelen) 4309296417Sdim Safelen = cast<OMPSafelenClause>(Clause); 4310296417Sdim else if (Clause->getClauseKind() == OMPC_simdlen) 4311296417Sdim Simdlen = cast<OMPSimdlenClause>(Clause); 4312296417Sdim if (Safelen && Simdlen) 4313296417Sdim break; 4314296417Sdim } 4315296417Sdim if (Simdlen && Safelen && 4316296417Sdim checkSimdlenSafelenValues(*this, Simdlen->getSimdlen(), 4317296417Sdim Safelen->getSafelen())) 4318296417Sdim return StmtError(); 4319296417Sdim 4320280031Sdim getCurFunction()->setHasBranchProtectedScope(); 4321280031Sdim return OMPForSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount, 4322280031Sdim Clauses, AStmt, B); 4323280031Sdim} 4324280031Sdim 4325276479SdimStmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses, 4326276479Sdim Stmt *AStmt, 4327276479Sdim SourceLocation StartLoc, 4328276479Sdim SourceLocation EndLoc) { 4329296417Sdim if (!AStmt) 4330296417Sdim return StmtError(); 4331296417Sdim 4332296417Sdim assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 4333276479Sdim auto BaseStmt = AStmt; 4334276479Sdim while (CapturedStmt *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt)) 4335276479Sdim BaseStmt = CS->getCapturedStmt(); 4336276479Sdim if (auto C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) { 4337276479Sdim auto S = C->children(); 4338296417Sdim if (S.begin() == S.end()) 4339276479Sdim return StmtError(); 4340276479Sdim // All associated statements must be '#pragma omp section' except for 4341276479Sdim // the first one. 4342296417Sdim for (Stmt *SectionStmt : llvm::make_range(std::next(S.begin()), S.end())) { 4343276479Sdim if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) { 4344276479Sdim if (SectionStmt) 4345276479Sdim Diag(SectionStmt->getLocStart(), 4346276479Sdim diag::err_omp_sections_substmt_not_section); 4347276479Sdim return StmtError(); 4348276479Sdim } 4349296417Sdim cast<OMPSectionDirective>(SectionStmt) 4350296417Sdim ->setHasCancel(DSAStack->isCancelRegion()); 4351276479Sdim } 4352276479Sdim } else { 4353276479Sdim Diag(AStmt->getLocStart(), diag::err_omp_sections_not_compound_stmt); 4354276479Sdim return StmtError(); 4355276479Sdim } 4356276479Sdim 4357276479Sdim getCurFunction()->setHasBranchProtectedScope(); 4358276479Sdim 4359296417Sdim return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, 4360296417Sdim DSAStack->isCancelRegion()); 4361276479Sdim} 4362276479Sdim 4363276479SdimStmtResult Sema::ActOnOpenMPSectionDirective(Stmt *AStmt, 4364276479Sdim SourceLocation StartLoc, 4365276479Sdim SourceLocation EndLoc) { 4366296417Sdim if (!AStmt) 4367296417Sdim return StmtError(); 4368276479Sdim 4369296417Sdim assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 4370296417Sdim 4371276479Sdim getCurFunction()->setHasBranchProtectedScope(); 4372296417Sdim DSAStack->setParentCancelRegion(DSAStack->isCancelRegion()); 4373276479Sdim 4374296417Sdim return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt, 4375296417Sdim DSAStack->isCancelRegion()); 4376276479Sdim} 4377276479Sdim 4378276479SdimStmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses, 4379276479Sdim Stmt *AStmt, 4380276479Sdim SourceLocation StartLoc, 4381276479Sdim SourceLocation EndLoc) { 4382296417Sdim if (!AStmt) 4383296417Sdim return StmtError(); 4384276479Sdim 4385296417Sdim assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 4386296417Sdim 4387276479Sdim getCurFunction()->setHasBranchProtectedScope(); 4388276479Sdim 4389288943Sdim // OpenMP [2.7.3, single Construct, Restrictions] 4390288943Sdim // The copyprivate clause must not be used with the nowait clause. 4391288943Sdim OMPClause *Nowait = nullptr; 4392288943Sdim OMPClause *Copyprivate = nullptr; 4393288943Sdim for (auto *Clause : Clauses) { 4394288943Sdim if (Clause->getClauseKind() == OMPC_nowait) 4395288943Sdim Nowait = Clause; 4396288943Sdim else if (Clause->getClauseKind() == OMPC_copyprivate) 4397288943Sdim Copyprivate = Clause; 4398288943Sdim if (Copyprivate && Nowait) { 4399288943Sdim Diag(Copyprivate->getLocStart(), 4400288943Sdim diag::err_omp_single_copyprivate_with_nowait); 4401288943Sdim Diag(Nowait->getLocStart(), diag::note_omp_nowait_clause_here); 4402288943Sdim return StmtError(); 4403288943Sdim } 4404288943Sdim } 4405288943Sdim 4406276479Sdim return OMPSingleDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt); 4407276479Sdim} 4408276479Sdim 4409276479SdimStmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt, 4410276479Sdim SourceLocation StartLoc, 4411276479Sdim SourceLocation EndLoc) { 4412296417Sdim if (!AStmt) 4413296417Sdim return StmtError(); 4414276479Sdim 4415296417Sdim assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 4416296417Sdim 4417276479Sdim getCurFunction()->setHasBranchProtectedScope(); 4418276479Sdim 4419276479Sdim return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt); 4420276479Sdim} 4421276479Sdim 4422296417SdimStmtResult Sema::ActOnOpenMPCriticalDirective( 4423296417Sdim const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses, 4424296417Sdim Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { 4425296417Sdim if (!AStmt) 4426296417Sdim return StmtError(); 4427276479Sdim 4428296417Sdim assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 4429296417Sdim 4430296417Sdim bool ErrorFound = false; 4431296417Sdim llvm::APSInt Hint; 4432296417Sdim SourceLocation HintLoc; 4433296417Sdim bool DependentHint = false; 4434296417Sdim for (auto *C : Clauses) { 4435296417Sdim if (C->getClauseKind() == OMPC_hint) { 4436296417Sdim if (!DirName.getName()) { 4437296417Sdim Diag(C->getLocStart(), diag::err_omp_hint_clause_no_name); 4438296417Sdim ErrorFound = true; 4439296417Sdim } 4440296417Sdim Expr *E = cast<OMPHintClause>(C)->getHint(); 4441296417Sdim if (E->isTypeDependent() || E->isValueDependent() || 4442296417Sdim E->isInstantiationDependent()) 4443296417Sdim DependentHint = true; 4444296417Sdim else { 4445296417Sdim Hint = E->EvaluateKnownConstInt(Context); 4446296417Sdim HintLoc = C->getLocStart(); 4447296417Sdim } 4448296417Sdim } 4449296417Sdim } 4450296417Sdim if (ErrorFound) 4451296417Sdim return StmtError(); 4452296417Sdim auto Pair = DSAStack->getCriticalWithHint(DirName); 4453296417Sdim if (Pair.first && DirName.getName() && !DependentHint) { 4454296417Sdim if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) { 4455296417Sdim Diag(StartLoc, diag::err_omp_critical_with_hint); 4456296417Sdim if (HintLoc.isValid()) { 4457296417Sdim Diag(HintLoc, diag::note_omp_critical_hint_here) 4458296417Sdim << 0 << Hint.toString(/*Radix=*/10, /*Signed=*/false); 4459296417Sdim } else 4460296417Sdim Diag(StartLoc, diag::note_omp_critical_no_hint) << 0; 4461296417Sdim if (auto *C = Pair.first->getSingleClause<OMPHintClause>()) { 4462296417Sdim Diag(C->getLocStart(), diag::note_omp_critical_hint_here) 4463296417Sdim << 1 4464296417Sdim << C->getHint()->EvaluateKnownConstInt(Context).toString( 4465296417Sdim /*Radix=*/10, /*Signed=*/false); 4466296417Sdim } else 4467296417Sdim Diag(Pair.first->getLocStart(), diag::note_omp_critical_no_hint) << 1; 4468296417Sdim } 4469296417Sdim } 4470296417Sdim 4471276479Sdim getCurFunction()->setHasBranchProtectedScope(); 4472276479Sdim 4473296417Sdim auto *Dir = OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc, 4474296417Sdim Clauses, AStmt); 4475296417Sdim if (!Pair.first && DirName.getName() && !DependentHint) 4476296417Sdim DSAStack->addCriticalWithHint(Dir, Hint); 4477296417Sdim return Dir; 4478276479Sdim} 4479276479Sdim 4480276479SdimStmtResult Sema::ActOnOpenMPParallelForDirective( 4481276479Sdim ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 4482276479Sdim SourceLocation EndLoc, 4483276479Sdim llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { 4484296417Sdim if (!AStmt) 4485296417Sdim return StmtError(); 4486296417Sdim 4487276479Sdim CapturedStmt *CS = cast<CapturedStmt>(AStmt); 4488276479Sdim // 1.2.2 OpenMP Language Terminology 4489276479Sdim // Structured block - An executable statement with a single entry at the 4490276479Sdim // top and a single exit at the bottom. 4491276479Sdim // The point of exit cannot be a branch out of the structured block. 4492276479Sdim // longjmp() and throw() must not violate the entry/exit criteria. 4493276479Sdim CS->getCapturedDecl()->setNothrow(); 4494276479Sdim 4495280031Sdim OMPLoopDirective::HelperExprs B; 4496296417Sdim // In presence of clause 'collapse' or 'ordered' with number of loops, it will 4497296417Sdim // define the nested loops number. 4498276479Sdim unsigned NestedLoopCount = 4499296417Sdim CheckOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses), 4500296417Sdim getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack, 4501296417Sdim VarsWithImplicitDSA, B); 4502276479Sdim if (NestedLoopCount == 0) 4503276479Sdim return StmtError(); 4504276479Sdim 4505280031Sdim assert((CurContext->isDependentContext() || B.builtAll()) && 4506280031Sdim "omp parallel for loop exprs were not built"); 4507280031Sdim 4508296417Sdim if (!CurContext->isDependentContext()) { 4509296417Sdim // Finalize the clauses that need pre-built expressions for CodeGen. 4510296417Sdim for (auto C : Clauses) { 4511296417Sdim if (auto LC = dyn_cast<OMPLinearClause>(C)) 4512296417Sdim if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef), 4513296417Sdim B.NumIterations, *this, CurScope)) 4514296417Sdim return StmtError(); 4515296417Sdim } 4516296417Sdim } 4517296417Sdim 4518276479Sdim getCurFunction()->setHasBranchProtectedScope(); 4519276479Sdim return OMPParallelForDirective::Create(Context, StartLoc, EndLoc, 4520296417Sdim NestedLoopCount, Clauses, AStmt, B, 4521296417Sdim DSAStack->isCancelRegion()); 4522276479Sdim} 4523276479Sdim 4524280031SdimStmtResult Sema::ActOnOpenMPParallelForSimdDirective( 4525280031Sdim ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 4526280031Sdim SourceLocation EndLoc, 4527280031Sdim llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { 4528296417Sdim if (!AStmt) 4529296417Sdim return StmtError(); 4530296417Sdim 4531280031Sdim CapturedStmt *CS = cast<CapturedStmt>(AStmt); 4532280031Sdim // 1.2.2 OpenMP Language Terminology 4533280031Sdim // Structured block - An executable statement with a single entry at the 4534280031Sdim // top and a single exit at the bottom. 4535280031Sdim // The point of exit cannot be a branch out of the structured block. 4536280031Sdim // longjmp() and throw() must not violate the entry/exit criteria. 4537280031Sdim CS->getCapturedDecl()->setNothrow(); 4538280031Sdim 4539280031Sdim OMPLoopDirective::HelperExprs B; 4540296417Sdim // In presence of clause 'collapse' or 'ordered' with number of loops, it will 4541296417Sdim // define the nested loops number. 4542280031Sdim unsigned NestedLoopCount = 4543296417Sdim CheckOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses), 4544296417Sdim getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack, 4545296417Sdim VarsWithImplicitDSA, B); 4546280031Sdim if (NestedLoopCount == 0) 4547280031Sdim return StmtError(); 4548280031Sdim 4549288943Sdim if (!CurContext->isDependentContext()) { 4550288943Sdim // Finalize the clauses that need pre-built expressions for CodeGen. 4551288943Sdim for (auto C : Clauses) { 4552288943Sdim if (auto LC = dyn_cast<OMPLinearClause>(C)) 4553288943Sdim if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef), 4554288943Sdim B.NumIterations, *this, CurScope)) 4555288943Sdim return StmtError(); 4556288943Sdim } 4557288943Sdim } 4558288943Sdim 4559296417Sdim // OpenMP 4.1 [2.8.1, simd Construct, Restrictions] 4560296417Sdim // If both simdlen and safelen clauses are specified, the value of the simdlen 4561296417Sdim // parameter must be less than or equal to the value of the safelen parameter. 4562296417Sdim OMPSafelenClause *Safelen = nullptr; 4563296417Sdim OMPSimdlenClause *Simdlen = nullptr; 4564296417Sdim for (auto *Clause : Clauses) { 4565296417Sdim if (Clause->getClauseKind() == OMPC_safelen) 4566296417Sdim Safelen = cast<OMPSafelenClause>(Clause); 4567296417Sdim else if (Clause->getClauseKind() == OMPC_simdlen) 4568296417Sdim Simdlen = cast<OMPSimdlenClause>(Clause); 4569296417Sdim if (Safelen && Simdlen) 4570296417Sdim break; 4571296417Sdim } 4572296417Sdim if (Simdlen && Safelen && 4573296417Sdim checkSimdlenSafelenValues(*this, Simdlen->getSimdlen(), 4574296417Sdim Safelen->getSafelen())) 4575296417Sdim return StmtError(); 4576296417Sdim 4577280031Sdim getCurFunction()->setHasBranchProtectedScope(); 4578280031Sdim return OMPParallelForSimdDirective::Create( 4579280031Sdim Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); 4580280031Sdim} 4581280031Sdim 4582276479SdimStmtResult 4583276479SdimSema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses, 4584276479Sdim Stmt *AStmt, SourceLocation StartLoc, 4585276479Sdim SourceLocation EndLoc) { 4586296417Sdim if (!AStmt) 4587296417Sdim return StmtError(); 4588296417Sdim 4589296417Sdim assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 4590276479Sdim auto BaseStmt = AStmt; 4591276479Sdim while (CapturedStmt *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt)) 4592276479Sdim BaseStmt = CS->getCapturedStmt(); 4593276479Sdim if (auto C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) { 4594276479Sdim auto S = C->children(); 4595296417Sdim if (S.begin() == S.end()) 4596276479Sdim return StmtError(); 4597276479Sdim // All associated statements must be '#pragma omp section' except for 4598276479Sdim // the first one. 4599296417Sdim for (Stmt *SectionStmt : llvm::make_range(std::next(S.begin()), S.end())) { 4600276479Sdim if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) { 4601276479Sdim if (SectionStmt) 4602276479Sdim Diag(SectionStmt->getLocStart(), 4603276479Sdim diag::err_omp_parallel_sections_substmt_not_section); 4604276479Sdim return StmtError(); 4605276479Sdim } 4606296417Sdim cast<OMPSectionDirective>(SectionStmt) 4607296417Sdim ->setHasCancel(DSAStack->isCancelRegion()); 4608276479Sdim } 4609276479Sdim } else { 4610276479Sdim Diag(AStmt->getLocStart(), 4611276479Sdim diag::err_omp_parallel_sections_not_compound_stmt); 4612276479Sdim return StmtError(); 4613276479Sdim } 4614276479Sdim 4615276479Sdim getCurFunction()->setHasBranchProtectedScope(); 4616276479Sdim 4617296417Sdim return OMPParallelSectionsDirective::Create( 4618296417Sdim Context, StartLoc, EndLoc, Clauses, AStmt, DSAStack->isCancelRegion()); 4619276479Sdim} 4620276479Sdim 4621276479SdimStmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses, 4622276479Sdim Stmt *AStmt, SourceLocation StartLoc, 4623276479Sdim SourceLocation EndLoc) { 4624296417Sdim if (!AStmt) 4625296417Sdim return StmtError(); 4626296417Sdim 4627276479Sdim CapturedStmt *CS = cast<CapturedStmt>(AStmt); 4628276479Sdim // 1.2.2 OpenMP Language Terminology 4629276479Sdim // Structured block - An executable statement with a single entry at the 4630276479Sdim // top and a single exit at the bottom. 4631276479Sdim // The point of exit cannot be a branch out of the structured block. 4632276479Sdim // longjmp() and throw() must not violate the entry/exit criteria. 4633276479Sdim CS->getCapturedDecl()->setNothrow(); 4634276479Sdim 4635276479Sdim getCurFunction()->setHasBranchProtectedScope(); 4636276479Sdim 4637296417Sdim return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, 4638296417Sdim DSAStack->isCancelRegion()); 4639276479Sdim} 4640276479Sdim 4641276479SdimStmtResult Sema::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, 4642276479Sdim SourceLocation EndLoc) { 4643276479Sdim return OMPTaskyieldDirective::Create(Context, StartLoc, EndLoc); 4644276479Sdim} 4645276479Sdim 4646276479SdimStmtResult Sema::ActOnOpenMPBarrierDirective(SourceLocation StartLoc, 4647276479Sdim SourceLocation EndLoc) { 4648276479Sdim return OMPBarrierDirective::Create(Context, StartLoc, EndLoc); 4649276479Sdim} 4650276479Sdim 4651276479SdimStmtResult Sema::ActOnOpenMPTaskwaitDirective(SourceLocation StartLoc, 4652276479Sdim SourceLocation EndLoc) { 4653276479Sdim return OMPTaskwaitDirective::Create(Context, StartLoc, EndLoc); 4654276479Sdim} 4655276479Sdim 4656288943SdimStmtResult Sema::ActOnOpenMPTaskgroupDirective(Stmt *AStmt, 4657288943Sdim SourceLocation StartLoc, 4658288943Sdim SourceLocation EndLoc) { 4659296417Sdim if (!AStmt) 4660296417Sdim return StmtError(); 4661288943Sdim 4662296417Sdim assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 4663296417Sdim 4664288943Sdim getCurFunction()->setHasBranchProtectedScope(); 4665288943Sdim 4666288943Sdim return OMPTaskgroupDirective::Create(Context, StartLoc, EndLoc, AStmt); 4667288943Sdim} 4668288943Sdim 4669276479SdimStmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses, 4670276479Sdim SourceLocation StartLoc, 4671276479Sdim SourceLocation EndLoc) { 4672276479Sdim assert(Clauses.size() <= 1 && "Extra clauses in flush directive"); 4673276479Sdim return OMPFlushDirective::Create(Context, StartLoc, EndLoc, Clauses); 4674276479Sdim} 4675276479Sdim 4676296417SdimStmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses, 4677296417Sdim Stmt *AStmt, 4678280031Sdim SourceLocation StartLoc, 4679280031Sdim SourceLocation EndLoc) { 4680296417Sdim OMPClause *DependFound = nullptr; 4681296417Sdim OMPClause *DependSourceClause = nullptr; 4682296417Sdim OMPClause *DependSinkClause = nullptr; 4683296417Sdim bool ErrorFound = false; 4684296417Sdim OMPThreadsClause *TC = nullptr; 4685296417Sdim OMPSIMDClause *SC = nullptr; 4686296417Sdim for (auto *C : Clauses) { 4687296417Sdim if (auto *DC = dyn_cast<OMPDependClause>(C)) { 4688296417Sdim DependFound = C; 4689296417Sdim if (DC->getDependencyKind() == OMPC_DEPEND_source) { 4690296417Sdim if (DependSourceClause) { 4691296417Sdim Diag(C->getLocStart(), diag::err_omp_more_one_clause) 4692296417Sdim << getOpenMPDirectiveName(OMPD_ordered) 4693296417Sdim << getOpenMPClauseName(OMPC_depend) << 2; 4694296417Sdim ErrorFound = true; 4695296417Sdim } else 4696296417Sdim DependSourceClause = C; 4697296417Sdim if (DependSinkClause) { 4698296417Sdim Diag(C->getLocStart(), diag::err_omp_depend_sink_source_not_allowed) 4699296417Sdim << 0; 4700296417Sdim ErrorFound = true; 4701296417Sdim } 4702296417Sdim } else if (DC->getDependencyKind() == OMPC_DEPEND_sink) { 4703296417Sdim if (DependSourceClause) { 4704296417Sdim Diag(C->getLocStart(), diag::err_omp_depend_sink_source_not_allowed) 4705296417Sdim << 1; 4706296417Sdim ErrorFound = true; 4707296417Sdim } 4708296417Sdim DependSinkClause = C; 4709296417Sdim } 4710296417Sdim } else if (C->getClauseKind() == OMPC_threads) 4711296417Sdim TC = cast<OMPThreadsClause>(C); 4712296417Sdim else if (C->getClauseKind() == OMPC_simd) 4713296417Sdim SC = cast<OMPSIMDClause>(C); 4714296417Sdim } 4715296417Sdim if (!ErrorFound && !SC && 4716296417Sdim isOpenMPSimdDirective(DSAStack->getParentDirective())) { 4717296417Sdim // OpenMP [2.8.1,simd Construct, Restrictions] 4718296417Sdim // An ordered construct with the simd clause is the only OpenMP construct 4719296417Sdim // that can appear in the simd region. 4720296417Sdim Diag(StartLoc, diag::err_omp_prohibited_region_simd); 4721296417Sdim ErrorFound = true; 4722296417Sdim } else if (DependFound && (TC || SC)) { 4723296417Sdim Diag(DependFound->getLocStart(), diag::err_omp_depend_clause_thread_simd) 4724296417Sdim << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind()); 4725296417Sdim ErrorFound = true; 4726296417Sdim } else if (DependFound && !DSAStack->getParentOrderedRegionParam()) { 4727296417Sdim Diag(DependFound->getLocStart(), 4728296417Sdim diag::err_omp_ordered_directive_without_param); 4729296417Sdim ErrorFound = true; 4730296417Sdim } else if (TC || Clauses.empty()) { 4731296417Sdim if (auto *Param = DSAStack->getParentOrderedRegionParam()) { 4732296417Sdim SourceLocation ErrLoc = TC ? TC->getLocStart() : StartLoc; 4733296417Sdim Diag(ErrLoc, diag::err_omp_ordered_directive_with_param) 4734296417Sdim << (TC != nullptr); 4735296417Sdim Diag(Param->getLocStart(), diag::note_omp_ordered_param); 4736296417Sdim ErrorFound = true; 4737296417Sdim } 4738296417Sdim } 4739296417Sdim if ((!AStmt && !DependFound) || ErrorFound) 4740296417Sdim return StmtError(); 4741280031Sdim 4742296417Sdim if (AStmt) { 4743296417Sdim assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 4744280031Sdim 4745296417Sdim getCurFunction()->setHasBranchProtectedScope(); 4746296417Sdim } 4747296417Sdim 4748296417Sdim return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt); 4749280031Sdim} 4750280031Sdim 4751288943Sdimnamespace { 4752288943Sdim/// \brief Helper class for checking expression in 'omp atomic [update]' 4753288943Sdim/// construct. 4754288943Sdimclass OpenMPAtomicUpdateChecker { 4755288943Sdim /// \brief Error results for atomic update expressions. 4756288943Sdim enum ExprAnalysisErrorCode { 4757288943Sdim /// \brief A statement is not an expression statement. 4758288943Sdim NotAnExpression, 4759288943Sdim /// \brief Expression is not builtin binary or unary operation. 4760288943Sdim NotABinaryOrUnaryExpression, 4761288943Sdim /// \brief Unary operation is not post-/pre- increment/decrement operation. 4762288943Sdim NotAnUnaryIncDecExpression, 4763288943Sdim /// \brief An expression is not of scalar type. 4764288943Sdim NotAScalarType, 4765288943Sdim /// \brief A binary operation is not an assignment operation. 4766288943Sdim NotAnAssignmentOp, 4767288943Sdim /// \brief RHS part of the binary operation is not a binary expression. 4768288943Sdim NotABinaryExpression, 4769288943Sdim /// \brief RHS part is not additive/multiplicative/shift/biwise binary 4770288943Sdim /// expression. 4771288943Sdim NotABinaryOperator, 4772288943Sdim /// \brief RHS binary operation does not have reference to the updated LHS 4773288943Sdim /// part. 4774288943Sdim NotAnUpdateExpression, 4775288943Sdim /// \brief No errors is found. 4776288943Sdim NoError 4777288943Sdim }; 4778288943Sdim /// \brief Reference to Sema. 4779288943Sdim Sema &SemaRef; 4780288943Sdim /// \brief A location for note diagnostics (when error is found). 4781288943Sdim SourceLocation NoteLoc; 4782288943Sdim /// \brief 'x' lvalue part of the source atomic expression. 4783288943Sdim Expr *X; 4784288943Sdim /// \brief 'expr' rvalue part of the source atomic expression. 4785288943Sdim Expr *E; 4786288943Sdim /// \brief Helper expression of the form 4787288943Sdim /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or 4788288943Sdim /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. 4789288943Sdim Expr *UpdateExpr; 4790288943Sdim /// \brief Is 'x' a LHS in a RHS part of full update expression. It is 4791288943Sdim /// important for non-associative operations. 4792288943Sdim bool IsXLHSInRHSPart; 4793288943Sdim BinaryOperatorKind Op; 4794288943Sdim SourceLocation OpLoc; 4795288943Sdim /// \brief true if the source expression is a postfix unary operation, false 4796288943Sdim /// if it is a prefix unary operation. 4797288943Sdim bool IsPostfixUpdate; 4798288943Sdim 4799288943Sdimpublic: 4800288943Sdim OpenMPAtomicUpdateChecker(Sema &SemaRef) 4801288943Sdim : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr), 4802288943Sdim IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {} 4803288943Sdim /// \brief Check specified statement that it is suitable for 'atomic update' 4804288943Sdim /// constructs and extract 'x', 'expr' and Operation from the original 4805288943Sdim /// expression. If DiagId and NoteId == 0, then only check is performed 4806288943Sdim /// without error notification. 4807288943Sdim /// \param DiagId Diagnostic which should be emitted if error is found. 4808288943Sdim /// \param NoteId Diagnostic note for the main error message. 4809288943Sdim /// \return true if statement is not an update expression, false otherwise. 4810288943Sdim bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0); 4811288943Sdim /// \brief Return the 'x' lvalue part of the source atomic expression. 4812288943Sdim Expr *getX() const { return X; } 4813288943Sdim /// \brief Return the 'expr' rvalue part of the source atomic expression. 4814288943Sdim Expr *getExpr() const { return E; } 4815288943Sdim /// \brief Return the update expression used in calculation of the updated 4816288943Sdim /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or 4817288943Sdim /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. 4818288943Sdim Expr *getUpdateExpr() const { return UpdateExpr; } 4819288943Sdim /// \brief Return true if 'x' is LHS in RHS part of full update expression, 4820288943Sdim /// false otherwise. 4821288943Sdim bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; } 4822288943Sdim 4823288943Sdim /// \brief true if the source expression is a postfix unary operation, false 4824288943Sdim /// if it is a prefix unary operation. 4825288943Sdim bool isPostfixUpdate() const { return IsPostfixUpdate; } 4826288943Sdim 4827288943Sdimprivate: 4828288943Sdim bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0, 4829288943Sdim unsigned NoteId = 0); 4830288943Sdim}; 4831288943Sdim} // namespace 4832288943Sdim 4833288943Sdimbool OpenMPAtomicUpdateChecker::checkBinaryOperation( 4834288943Sdim BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) { 4835288943Sdim ExprAnalysisErrorCode ErrorFound = NoError; 4836288943Sdim SourceLocation ErrorLoc, NoteLoc; 4837288943Sdim SourceRange ErrorRange, NoteRange; 4838288943Sdim // Allowed constructs are: 4839288943Sdim // x = x binop expr; 4840288943Sdim // x = expr binop x; 4841288943Sdim if (AtomicBinOp->getOpcode() == BO_Assign) { 4842288943Sdim X = AtomicBinOp->getLHS(); 4843288943Sdim if (auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>( 4844288943Sdim AtomicBinOp->getRHS()->IgnoreParenImpCasts())) { 4845288943Sdim if (AtomicInnerBinOp->isMultiplicativeOp() || 4846288943Sdim AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() || 4847288943Sdim AtomicInnerBinOp->isBitwiseOp()) { 4848288943Sdim Op = AtomicInnerBinOp->getOpcode(); 4849288943Sdim OpLoc = AtomicInnerBinOp->getOperatorLoc(); 4850288943Sdim auto *LHS = AtomicInnerBinOp->getLHS(); 4851288943Sdim auto *RHS = AtomicInnerBinOp->getRHS(); 4852288943Sdim llvm::FoldingSetNodeID XId, LHSId, RHSId; 4853288943Sdim X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(), 4854288943Sdim /*Canonical=*/true); 4855288943Sdim LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(), 4856288943Sdim /*Canonical=*/true); 4857288943Sdim RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(), 4858288943Sdim /*Canonical=*/true); 4859288943Sdim if (XId == LHSId) { 4860288943Sdim E = RHS; 4861288943Sdim IsXLHSInRHSPart = true; 4862288943Sdim } else if (XId == RHSId) { 4863288943Sdim E = LHS; 4864288943Sdim IsXLHSInRHSPart = false; 4865288943Sdim } else { 4866288943Sdim ErrorLoc = AtomicInnerBinOp->getExprLoc(); 4867288943Sdim ErrorRange = AtomicInnerBinOp->getSourceRange(); 4868288943Sdim NoteLoc = X->getExprLoc(); 4869288943Sdim NoteRange = X->getSourceRange(); 4870288943Sdim ErrorFound = NotAnUpdateExpression; 4871288943Sdim } 4872288943Sdim } else { 4873288943Sdim ErrorLoc = AtomicInnerBinOp->getExprLoc(); 4874288943Sdim ErrorRange = AtomicInnerBinOp->getSourceRange(); 4875288943Sdim NoteLoc = AtomicInnerBinOp->getOperatorLoc(); 4876288943Sdim NoteRange = SourceRange(NoteLoc, NoteLoc); 4877288943Sdim ErrorFound = NotABinaryOperator; 4878288943Sdim } 4879288943Sdim } else { 4880288943Sdim NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc(); 4881288943Sdim NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange(); 4882288943Sdim ErrorFound = NotABinaryExpression; 4883288943Sdim } 4884288943Sdim } else { 4885288943Sdim ErrorLoc = AtomicBinOp->getExprLoc(); 4886288943Sdim ErrorRange = AtomicBinOp->getSourceRange(); 4887288943Sdim NoteLoc = AtomicBinOp->getOperatorLoc(); 4888288943Sdim NoteRange = SourceRange(NoteLoc, NoteLoc); 4889288943Sdim ErrorFound = NotAnAssignmentOp; 4890288943Sdim } 4891288943Sdim if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) { 4892288943Sdim SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange; 4893288943Sdim SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange; 4894288943Sdim return true; 4895288943Sdim } else if (SemaRef.CurContext->isDependentContext()) 4896288943Sdim E = X = UpdateExpr = nullptr; 4897288943Sdim return ErrorFound != NoError; 4898288943Sdim} 4899288943Sdim 4900288943Sdimbool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId, 4901288943Sdim unsigned NoteId) { 4902288943Sdim ExprAnalysisErrorCode ErrorFound = NoError; 4903288943Sdim SourceLocation ErrorLoc, NoteLoc; 4904288943Sdim SourceRange ErrorRange, NoteRange; 4905288943Sdim // Allowed constructs are: 4906288943Sdim // x++; 4907288943Sdim // x--; 4908288943Sdim // ++x; 4909288943Sdim // --x; 4910288943Sdim // x binop= expr; 4911288943Sdim // x = x binop expr; 4912288943Sdim // x = expr binop x; 4913288943Sdim if (auto *AtomicBody = dyn_cast<Expr>(S)) { 4914288943Sdim AtomicBody = AtomicBody->IgnoreParenImpCasts(); 4915288943Sdim if (AtomicBody->getType()->isScalarType() || 4916288943Sdim AtomicBody->isInstantiationDependent()) { 4917288943Sdim if (auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>( 4918288943Sdim AtomicBody->IgnoreParenImpCasts())) { 4919288943Sdim // Check for Compound Assignment Operation 4920288943Sdim Op = BinaryOperator::getOpForCompoundAssignment( 4921288943Sdim AtomicCompAssignOp->getOpcode()); 4922288943Sdim OpLoc = AtomicCompAssignOp->getOperatorLoc(); 4923288943Sdim E = AtomicCompAssignOp->getRHS(); 4924288943Sdim X = AtomicCompAssignOp->getLHS(); 4925288943Sdim IsXLHSInRHSPart = true; 4926288943Sdim } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>( 4927288943Sdim AtomicBody->IgnoreParenImpCasts())) { 4928288943Sdim // Check for Binary Operation 4929288943Sdim if(checkBinaryOperation(AtomicBinOp, DiagId, NoteId)) 4930288943Sdim return true; 4931288943Sdim } else if (auto *AtomicUnaryOp = 4932288943Sdim dyn_cast<UnaryOperator>(AtomicBody->IgnoreParenImpCasts())) { 4933288943Sdim // Check for Unary Operation 4934288943Sdim if (AtomicUnaryOp->isIncrementDecrementOp()) { 4935288943Sdim IsPostfixUpdate = AtomicUnaryOp->isPostfix(); 4936288943Sdim Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub; 4937288943Sdim OpLoc = AtomicUnaryOp->getOperatorLoc(); 4938288943Sdim X = AtomicUnaryOp->getSubExpr(); 4939288943Sdim E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get(); 4940288943Sdim IsXLHSInRHSPart = true; 4941288943Sdim } else { 4942288943Sdim ErrorFound = NotAnUnaryIncDecExpression; 4943288943Sdim ErrorLoc = AtomicUnaryOp->getExprLoc(); 4944288943Sdim ErrorRange = AtomicUnaryOp->getSourceRange(); 4945288943Sdim NoteLoc = AtomicUnaryOp->getOperatorLoc(); 4946288943Sdim NoteRange = SourceRange(NoteLoc, NoteLoc); 4947288943Sdim } 4948296417Sdim } else if (!AtomicBody->isInstantiationDependent()) { 4949288943Sdim ErrorFound = NotABinaryOrUnaryExpression; 4950288943Sdim NoteLoc = ErrorLoc = AtomicBody->getExprLoc(); 4951288943Sdim NoteRange = ErrorRange = AtomicBody->getSourceRange(); 4952288943Sdim } 4953288943Sdim } else { 4954288943Sdim ErrorFound = NotAScalarType; 4955288943Sdim NoteLoc = ErrorLoc = AtomicBody->getLocStart(); 4956288943Sdim NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); 4957288943Sdim } 4958288943Sdim } else { 4959288943Sdim ErrorFound = NotAnExpression; 4960288943Sdim NoteLoc = ErrorLoc = S->getLocStart(); 4961288943Sdim NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); 4962288943Sdim } 4963288943Sdim if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) { 4964288943Sdim SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange; 4965288943Sdim SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange; 4966288943Sdim return true; 4967288943Sdim } else if (SemaRef.CurContext->isDependentContext()) 4968288943Sdim E = X = UpdateExpr = nullptr; 4969288943Sdim if (ErrorFound == NoError && E && X) { 4970288943Sdim // Build an update expression of form 'OpaqueValueExpr(x) binop 4971288943Sdim // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop 4972288943Sdim // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression. 4973288943Sdim auto *OVEX = new (SemaRef.getASTContext()) 4974288943Sdim OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_RValue); 4975288943Sdim auto *OVEExpr = new (SemaRef.getASTContext()) 4976288943Sdim OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_RValue); 4977288943Sdim auto Update = 4978288943Sdim SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr, 4979288943Sdim IsXLHSInRHSPart ? OVEExpr : OVEX); 4980288943Sdim if (Update.isInvalid()) 4981288943Sdim return true; 4982288943Sdim Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(), 4983288943Sdim Sema::AA_Casting); 4984288943Sdim if (Update.isInvalid()) 4985288943Sdim return true; 4986288943Sdim UpdateExpr = Update.get(); 4987288943Sdim } 4988288943Sdim return ErrorFound != NoError; 4989288943Sdim} 4990288943Sdim 4991280031SdimStmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, 4992280031Sdim Stmt *AStmt, 4993280031Sdim SourceLocation StartLoc, 4994280031Sdim SourceLocation EndLoc) { 4995296417Sdim if (!AStmt) 4996296417Sdim return StmtError(); 4997296417Sdim 4998280031Sdim auto CS = cast<CapturedStmt>(AStmt); 4999280031Sdim // 1.2.2 OpenMP Language Terminology 5000280031Sdim // Structured block - An executable statement with a single entry at the 5001280031Sdim // top and a single exit at the bottom. 5002280031Sdim // The point of exit cannot be a branch out of the structured block. 5003280031Sdim // longjmp() and throw() must not violate the entry/exit criteria. 5004280031Sdim OpenMPClauseKind AtomicKind = OMPC_unknown; 5005280031Sdim SourceLocation AtomicKindLoc; 5006280031Sdim for (auto *C : Clauses) { 5007280031Sdim if (C->getClauseKind() == OMPC_read || C->getClauseKind() == OMPC_write || 5008280031Sdim C->getClauseKind() == OMPC_update || 5009280031Sdim C->getClauseKind() == OMPC_capture) { 5010280031Sdim if (AtomicKind != OMPC_unknown) { 5011280031Sdim Diag(C->getLocStart(), diag::err_omp_atomic_several_clauses) 5012280031Sdim << SourceRange(C->getLocStart(), C->getLocEnd()); 5013280031Sdim Diag(AtomicKindLoc, diag::note_omp_atomic_previous_clause) 5014280031Sdim << getOpenMPClauseName(AtomicKind); 5015280031Sdim } else { 5016280031Sdim AtomicKind = C->getClauseKind(); 5017280031Sdim AtomicKindLoc = C->getLocStart(); 5018280031Sdim } 5019280031Sdim } 5020280031Sdim } 5021280031Sdim 5022280031Sdim auto Body = CS->getCapturedStmt(); 5023288943Sdim if (auto *EWC = dyn_cast<ExprWithCleanups>(Body)) 5024288943Sdim Body = EWC->getSubExpr(); 5025288943Sdim 5026280031Sdim Expr *X = nullptr; 5027280031Sdim Expr *V = nullptr; 5028280031Sdim Expr *E = nullptr; 5029288943Sdim Expr *UE = nullptr; 5030288943Sdim bool IsXLHSInRHSPart = false; 5031288943Sdim bool IsPostfixUpdate = false; 5032280031Sdim // OpenMP [2.12.6, atomic Construct] 5033280031Sdim // In the next expressions: 5034280031Sdim // * x and v (as applicable) are both l-value expressions with scalar type. 5035280031Sdim // * During the execution of an atomic region, multiple syntactic 5036280031Sdim // occurrences of x must designate the same storage location. 5037280031Sdim // * Neither of v and expr (as applicable) may access the storage location 5038280031Sdim // designated by x. 5039280031Sdim // * Neither of x and expr (as applicable) may access the storage location 5040280031Sdim // designated by v. 5041280031Sdim // * expr is an expression with scalar type. 5042280031Sdim // * binop is one of +, *, -, /, &, ^, |, <<, or >>. 5043280031Sdim // * binop, binop=, ++, and -- are not overloaded operators. 5044280031Sdim // * The expression x binop expr must be numerically equivalent to x binop 5045280031Sdim // (expr). This requirement is satisfied if the operators in expr have 5046280031Sdim // precedence greater than binop, or by using parentheses around expr or 5047280031Sdim // subexpressions of expr. 5048280031Sdim // * The expression expr binop x must be numerically equivalent to (expr) 5049280031Sdim // binop x. This requirement is satisfied if the operators in expr have 5050280031Sdim // precedence equal to or greater than binop, or by using parentheses around 5051280031Sdim // expr or subexpressions of expr. 5052280031Sdim // * For forms that allow multiple occurrences of x, the number of times 5053280031Sdim // that x is evaluated is unspecified. 5054280031Sdim if (AtomicKind == OMPC_read) { 5055288943Sdim enum { 5056288943Sdim NotAnExpression, 5057288943Sdim NotAnAssignmentOp, 5058288943Sdim NotAScalarType, 5059288943Sdim NotAnLValue, 5060288943Sdim NoError 5061288943Sdim } ErrorFound = NoError; 5062280031Sdim SourceLocation ErrorLoc, NoteLoc; 5063280031Sdim SourceRange ErrorRange, NoteRange; 5064280031Sdim // If clause is read: 5065280031Sdim // v = x; 5066280031Sdim if (auto AtomicBody = dyn_cast<Expr>(Body)) { 5067280031Sdim auto AtomicBinOp = 5068280031Sdim dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts()); 5069280031Sdim if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) { 5070280031Sdim X = AtomicBinOp->getRHS()->IgnoreParenImpCasts(); 5071280031Sdim V = AtomicBinOp->getLHS()->IgnoreParenImpCasts(); 5072280031Sdim if ((X->isInstantiationDependent() || X->getType()->isScalarType()) && 5073280031Sdim (V->isInstantiationDependent() || V->getType()->isScalarType())) { 5074280031Sdim if (!X->isLValue() || !V->isLValue()) { 5075280031Sdim auto NotLValueExpr = X->isLValue() ? V : X; 5076280031Sdim ErrorFound = NotAnLValue; 5077280031Sdim ErrorLoc = AtomicBinOp->getExprLoc(); 5078280031Sdim ErrorRange = AtomicBinOp->getSourceRange(); 5079280031Sdim NoteLoc = NotLValueExpr->getExprLoc(); 5080280031Sdim NoteRange = NotLValueExpr->getSourceRange(); 5081280031Sdim } 5082280031Sdim } else if (!X->isInstantiationDependent() || 5083280031Sdim !V->isInstantiationDependent()) { 5084280031Sdim auto NotScalarExpr = 5085280031Sdim (X->isInstantiationDependent() || X->getType()->isScalarType()) 5086280031Sdim ? V 5087280031Sdim : X; 5088280031Sdim ErrorFound = NotAScalarType; 5089280031Sdim ErrorLoc = AtomicBinOp->getExprLoc(); 5090280031Sdim ErrorRange = AtomicBinOp->getSourceRange(); 5091280031Sdim NoteLoc = NotScalarExpr->getExprLoc(); 5092280031Sdim NoteRange = NotScalarExpr->getSourceRange(); 5093280031Sdim } 5094296417Sdim } else if (!AtomicBody->isInstantiationDependent()) { 5095280031Sdim ErrorFound = NotAnAssignmentOp; 5096280031Sdim ErrorLoc = AtomicBody->getExprLoc(); 5097280031Sdim ErrorRange = AtomicBody->getSourceRange(); 5098280031Sdim NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc() 5099280031Sdim : AtomicBody->getExprLoc(); 5100280031Sdim NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange() 5101280031Sdim : AtomicBody->getSourceRange(); 5102280031Sdim } 5103280031Sdim } else { 5104280031Sdim ErrorFound = NotAnExpression; 5105280031Sdim NoteLoc = ErrorLoc = Body->getLocStart(); 5106280031Sdim NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); 5107280031Sdim } 5108280031Sdim if (ErrorFound != NoError) { 5109280031Sdim Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement) 5110280031Sdim << ErrorRange; 5111280031Sdim Diag(NoteLoc, diag::note_omp_atomic_read_write) << ErrorFound 5112280031Sdim << NoteRange; 5113280031Sdim return StmtError(); 5114280031Sdim } else if (CurContext->isDependentContext()) 5115280031Sdim V = X = nullptr; 5116280031Sdim } else if (AtomicKind == OMPC_write) { 5117288943Sdim enum { 5118288943Sdim NotAnExpression, 5119288943Sdim NotAnAssignmentOp, 5120288943Sdim NotAScalarType, 5121288943Sdim NotAnLValue, 5122288943Sdim NoError 5123288943Sdim } ErrorFound = NoError; 5124280031Sdim SourceLocation ErrorLoc, NoteLoc; 5125280031Sdim SourceRange ErrorRange, NoteRange; 5126280031Sdim // If clause is write: 5127280031Sdim // x = expr; 5128280031Sdim if (auto AtomicBody = dyn_cast<Expr>(Body)) { 5129280031Sdim auto AtomicBinOp = 5130280031Sdim dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts()); 5131280031Sdim if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) { 5132288943Sdim X = AtomicBinOp->getLHS(); 5133288943Sdim E = AtomicBinOp->getRHS(); 5134280031Sdim if ((X->isInstantiationDependent() || X->getType()->isScalarType()) && 5135280031Sdim (E->isInstantiationDependent() || E->getType()->isScalarType())) { 5136280031Sdim if (!X->isLValue()) { 5137280031Sdim ErrorFound = NotAnLValue; 5138280031Sdim ErrorLoc = AtomicBinOp->getExprLoc(); 5139280031Sdim ErrorRange = AtomicBinOp->getSourceRange(); 5140280031Sdim NoteLoc = X->getExprLoc(); 5141280031Sdim NoteRange = X->getSourceRange(); 5142280031Sdim } 5143280031Sdim } else if (!X->isInstantiationDependent() || 5144280031Sdim !E->isInstantiationDependent()) { 5145280031Sdim auto NotScalarExpr = 5146280031Sdim (X->isInstantiationDependent() || X->getType()->isScalarType()) 5147280031Sdim ? E 5148280031Sdim : X; 5149280031Sdim ErrorFound = NotAScalarType; 5150280031Sdim ErrorLoc = AtomicBinOp->getExprLoc(); 5151280031Sdim ErrorRange = AtomicBinOp->getSourceRange(); 5152280031Sdim NoteLoc = NotScalarExpr->getExprLoc(); 5153280031Sdim NoteRange = NotScalarExpr->getSourceRange(); 5154280031Sdim } 5155296417Sdim } else if (!AtomicBody->isInstantiationDependent()) { 5156280031Sdim ErrorFound = NotAnAssignmentOp; 5157280031Sdim ErrorLoc = AtomicBody->getExprLoc(); 5158280031Sdim ErrorRange = AtomicBody->getSourceRange(); 5159280031Sdim NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc() 5160280031Sdim : AtomicBody->getExprLoc(); 5161280031Sdim NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange() 5162280031Sdim : AtomicBody->getSourceRange(); 5163280031Sdim } 5164280031Sdim } else { 5165280031Sdim ErrorFound = NotAnExpression; 5166280031Sdim NoteLoc = ErrorLoc = Body->getLocStart(); 5167280031Sdim NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc); 5168280031Sdim } 5169280031Sdim if (ErrorFound != NoError) { 5170280031Sdim Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement) 5171280031Sdim << ErrorRange; 5172280031Sdim Diag(NoteLoc, diag::note_omp_atomic_read_write) << ErrorFound 5173280031Sdim << NoteRange; 5174280031Sdim return StmtError(); 5175280031Sdim } else if (CurContext->isDependentContext()) 5176280031Sdim E = X = nullptr; 5177280031Sdim } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) { 5178288943Sdim // If clause is update: 5179288943Sdim // x++; 5180288943Sdim // x--; 5181288943Sdim // ++x; 5182288943Sdim // --x; 5183288943Sdim // x binop= expr; 5184288943Sdim // x = x binop expr; 5185288943Sdim // x = expr binop x; 5186288943Sdim OpenMPAtomicUpdateChecker Checker(*this); 5187288943Sdim if (Checker.checkStatement( 5188288943Sdim Body, (AtomicKind == OMPC_update) 5189288943Sdim ? diag::err_omp_atomic_update_not_expression_statement 5190288943Sdim : diag::err_omp_atomic_not_expression_statement, 5191288943Sdim diag::note_omp_atomic_update)) 5192280031Sdim return StmtError(); 5193288943Sdim if (!CurContext->isDependentContext()) { 5194288943Sdim E = Checker.getExpr(); 5195288943Sdim X = Checker.getX(); 5196288943Sdim UE = Checker.getUpdateExpr(); 5197288943Sdim IsXLHSInRHSPart = Checker.isXLHSInRHSPart(); 5198280031Sdim } 5199280031Sdim } else if (AtomicKind == OMPC_capture) { 5200288943Sdim enum { 5201288943Sdim NotAnAssignmentOp, 5202288943Sdim NotACompoundStatement, 5203288943Sdim NotTwoSubstatements, 5204288943Sdim NotASpecificExpression, 5205288943Sdim NoError 5206288943Sdim } ErrorFound = NoError; 5207288943Sdim SourceLocation ErrorLoc, NoteLoc; 5208288943Sdim SourceRange ErrorRange, NoteRange; 5209288943Sdim if (auto *AtomicBody = dyn_cast<Expr>(Body)) { 5210288943Sdim // If clause is a capture: 5211288943Sdim // v = x++; 5212288943Sdim // v = x--; 5213288943Sdim // v = ++x; 5214288943Sdim // v = --x; 5215288943Sdim // v = x binop= expr; 5216288943Sdim // v = x = x binop expr; 5217288943Sdim // v = x = expr binop x; 5218288943Sdim auto *AtomicBinOp = 5219288943Sdim dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts()); 5220288943Sdim if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) { 5221288943Sdim V = AtomicBinOp->getLHS(); 5222288943Sdim Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts(); 5223288943Sdim OpenMPAtomicUpdateChecker Checker(*this); 5224288943Sdim if (Checker.checkStatement( 5225288943Sdim Body, diag::err_omp_atomic_capture_not_expression_statement, 5226288943Sdim diag::note_omp_atomic_update)) 5227288943Sdim return StmtError(); 5228288943Sdim E = Checker.getExpr(); 5229288943Sdim X = Checker.getX(); 5230288943Sdim UE = Checker.getUpdateExpr(); 5231288943Sdim IsXLHSInRHSPart = Checker.isXLHSInRHSPart(); 5232288943Sdim IsPostfixUpdate = Checker.isPostfixUpdate(); 5233296417Sdim } else if (!AtomicBody->isInstantiationDependent()) { 5234288943Sdim ErrorLoc = AtomicBody->getExprLoc(); 5235288943Sdim ErrorRange = AtomicBody->getSourceRange(); 5236288943Sdim NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc() 5237288943Sdim : AtomicBody->getExprLoc(); 5238288943Sdim NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange() 5239288943Sdim : AtomicBody->getSourceRange(); 5240288943Sdim ErrorFound = NotAnAssignmentOp; 5241288943Sdim } 5242288943Sdim if (ErrorFound != NoError) { 5243288943Sdim Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement) 5244288943Sdim << ErrorRange; 5245288943Sdim Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange; 5246288943Sdim return StmtError(); 5247288943Sdim } else if (CurContext->isDependentContext()) { 5248288943Sdim UE = V = E = X = nullptr; 5249288943Sdim } 5250288943Sdim } else { 5251288943Sdim // If clause is a capture: 5252288943Sdim // { v = x; x = expr; } 5253288943Sdim // { v = x; x++; } 5254288943Sdim // { v = x; x--; } 5255288943Sdim // { v = x; ++x; } 5256288943Sdim // { v = x; --x; } 5257288943Sdim // { v = x; x binop= expr; } 5258288943Sdim // { v = x; x = x binop expr; } 5259288943Sdim // { v = x; x = expr binop x; } 5260288943Sdim // { x++; v = x; } 5261288943Sdim // { x--; v = x; } 5262288943Sdim // { ++x; v = x; } 5263288943Sdim // { --x; v = x; } 5264288943Sdim // { x binop= expr; v = x; } 5265288943Sdim // { x = x binop expr; v = x; } 5266288943Sdim // { x = expr binop x; v = x; } 5267288943Sdim if (auto *CS = dyn_cast<CompoundStmt>(Body)) { 5268288943Sdim // Check that this is { expr1; expr2; } 5269288943Sdim if (CS->size() == 2) { 5270288943Sdim auto *First = CS->body_front(); 5271288943Sdim auto *Second = CS->body_back(); 5272288943Sdim if (auto *EWC = dyn_cast<ExprWithCleanups>(First)) 5273288943Sdim First = EWC->getSubExpr()->IgnoreParenImpCasts(); 5274288943Sdim if (auto *EWC = dyn_cast<ExprWithCleanups>(Second)) 5275288943Sdim Second = EWC->getSubExpr()->IgnoreParenImpCasts(); 5276288943Sdim // Need to find what subexpression is 'v' and what is 'x'. 5277288943Sdim OpenMPAtomicUpdateChecker Checker(*this); 5278288943Sdim bool IsUpdateExprFound = !Checker.checkStatement(Second); 5279288943Sdim BinaryOperator *BinOp = nullptr; 5280288943Sdim if (IsUpdateExprFound) { 5281288943Sdim BinOp = dyn_cast<BinaryOperator>(First); 5282288943Sdim IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign; 5283288943Sdim } 5284288943Sdim if (IsUpdateExprFound && !CurContext->isDependentContext()) { 5285288943Sdim // { v = x; x++; } 5286288943Sdim // { v = x; x--; } 5287288943Sdim // { v = x; ++x; } 5288288943Sdim // { v = x; --x; } 5289288943Sdim // { v = x; x binop= expr; } 5290288943Sdim // { v = x; x = x binop expr; } 5291288943Sdim // { v = x; x = expr binop x; } 5292288943Sdim // Check that the first expression has form v = x. 5293288943Sdim auto *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts(); 5294288943Sdim llvm::FoldingSetNodeID XId, PossibleXId; 5295288943Sdim Checker.getX()->Profile(XId, Context, /*Canonical=*/true); 5296288943Sdim PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true); 5297288943Sdim IsUpdateExprFound = XId == PossibleXId; 5298288943Sdim if (IsUpdateExprFound) { 5299288943Sdim V = BinOp->getLHS(); 5300288943Sdim X = Checker.getX(); 5301288943Sdim E = Checker.getExpr(); 5302288943Sdim UE = Checker.getUpdateExpr(); 5303288943Sdim IsXLHSInRHSPart = Checker.isXLHSInRHSPart(); 5304288943Sdim IsPostfixUpdate = true; 5305288943Sdim } 5306288943Sdim } 5307288943Sdim if (!IsUpdateExprFound) { 5308288943Sdim IsUpdateExprFound = !Checker.checkStatement(First); 5309288943Sdim BinOp = nullptr; 5310288943Sdim if (IsUpdateExprFound) { 5311288943Sdim BinOp = dyn_cast<BinaryOperator>(Second); 5312288943Sdim IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign; 5313288943Sdim } 5314288943Sdim if (IsUpdateExprFound && !CurContext->isDependentContext()) { 5315288943Sdim // { x++; v = x; } 5316288943Sdim // { x--; v = x; } 5317288943Sdim // { ++x; v = x; } 5318288943Sdim // { --x; v = x; } 5319288943Sdim // { x binop= expr; v = x; } 5320288943Sdim // { x = x binop expr; v = x; } 5321288943Sdim // { x = expr binop x; v = x; } 5322288943Sdim // Check that the second expression has form v = x. 5323288943Sdim auto *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts(); 5324288943Sdim llvm::FoldingSetNodeID XId, PossibleXId; 5325288943Sdim Checker.getX()->Profile(XId, Context, /*Canonical=*/true); 5326288943Sdim PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true); 5327288943Sdim IsUpdateExprFound = XId == PossibleXId; 5328288943Sdim if (IsUpdateExprFound) { 5329288943Sdim V = BinOp->getLHS(); 5330288943Sdim X = Checker.getX(); 5331288943Sdim E = Checker.getExpr(); 5332288943Sdim UE = Checker.getUpdateExpr(); 5333288943Sdim IsXLHSInRHSPart = Checker.isXLHSInRHSPart(); 5334288943Sdim IsPostfixUpdate = false; 5335288943Sdim } 5336288943Sdim } 5337288943Sdim } 5338288943Sdim if (!IsUpdateExprFound) { 5339288943Sdim // { v = x; x = expr; } 5340296417Sdim auto *FirstExpr = dyn_cast<Expr>(First); 5341296417Sdim auto *SecondExpr = dyn_cast<Expr>(Second); 5342296417Sdim if (!FirstExpr || !SecondExpr || 5343296417Sdim !(FirstExpr->isInstantiationDependent() || 5344296417Sdim SecondExpr->isInstantiationDependent())) { 5345296417Sdim auto *FirstBinOp = dyn_cast<BinaryOperator>(First); 5346296417Sdim if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) { 5347288943Sdim ErrorFound = NotAnAssignmentOp; 5348296417Sdim NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc() 5349296417Sdim : First->getLocStart(); 5350296417Sdim NoteRange = ErrorRange = FirstBinOp 5351296417Sdim ? FirstBinOp->getSourceRange() 5352288943Sdim : SourceRange(ErrorLoc, ErrorLoc); 5353288943Sdim } else { 5354296417Sdim auto *SecondBinOp = dyn_cast<BinaryOperator>(Second); 5355296417Sdim if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) { 5356296417Sdim ErrorFound = NotAnAssignmentOp; 5357296417Sdim NoteLoc = ErrorLoc = SecondBinOp 5358296417Sdim ? SecondBinOp->getOperatorLoc() 5359296417Sdim : Second->getLocStart(); 5360296417Sdim NoteRange = ErrorRange = 5361296417Sdim SecondBinOp ? SecondBinOp->getSourceRange() 5362296417Sdim : SourceRange(ErrorLoc, ErrorLoc); 5363288943Sdim } else { 5364296417Sdim auto *PossibleXRHSInFirst = 5365296417Sdim FirstBinOp->getRHS()->IgnoreParenImpCasts(); 5366296417Sdim auto *PossibleXLHSInSecond = 5367296417Sdim SecondBinOp->getLHS()->IgnoreParenImpCasts(); 5368296417Sdim llvm::FoldingSetNodeID X1Id, X2Id; 5369296417Sdim PossibleXRHSInFirst->Profile(X1Id, Context, 5370296417Sdim /*Canonical=*/true); 5371296417Sdim PossibleXLHSInSecond->Profile(X2Id, Context, 5372296417Sdim /*Canonical=*/true); 5373296417Sdim IsUpdateExprFound = X1Id == X2Id; 5374296417Sdim if (IsUpdateExprFound) { 5375296417Sdim V = FirstBinOp->getLHS(); 5376296417Sdim X = SecondBinOp->getLHS(); 5377296417Sdim E = SecondBinOp->getRHS(); 5378296417Sdim UE = nullptr; 5379296417Sdim IsXLHSInRHSPart = false; 5380296417Sdim IsPostfixUpdate = true; 5381296417Sdim } else { 5382296417Sdim ErrorFound = NotASpecificExpression; 5383296417Sdim ErrorLoc = FirstBinOp->getExprLoc(); 5384296417Sdim ErrorRange = FirstBinOp->getSourceRange(); 5385296417Sdim NoteLoc = SecondBinOp->getLHS()->getExprLoc(); 5386296417Sdim NoteRange = SecondBinOp->getRHS()->getSourceRange(); 5387296417Sdim } 5388288943Sdim } 5389288943Sdim } 5390288943Sdim } 5391288943Sdim } 5392288943Sdim } else { 5393288943Sdim NoteLoc = ErrorLoc = Body->getLocStart(); 5394288943Sdim NoteRange = ErrorRange = 5395288943Sdim SourceRange(Body->getLocStart(), Body->getLocStart()); 5396288943Sdim ErrorFound = NotTwoSubstatements; 5397288943Sdim } 5398288943Sdim } else { 5399288943Sdim NoteLoc = ErrorLoc = Body->getLocStart(); 5400288943Sdim NoteRange = ErrorRange = 5401288943Sdim SourceRange(Body->getLocStart(), Body->getLocStart()); 5402288943Sdim ErrorFound = NotACompoundStatement; 5403288943Sdim } 5404288943Sdim if (ErrorFound != NoError) { 5405288943Sdim Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement) 5406288943Sdim << ErrorRange; 5407288943Sdim Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange; 5408288943Sdim return StmtError(); 5409288943Sdim } else if (CurContext->isDependentContext()) { 5410288943Sdim UE = V = E = X = nullptr; 5411288943Sdim } 5412280031Sdim } 5413280031Sdim } 5414280031Sdim 5415280031Sdim getCurFunction()->setHasBranchProtectedScope(); 5416280031Sdim 5417280031Sdim return OMPAtomicDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, 5418288943Sdim X, V, E, UE, IsXLHSInRHSPart, 5419288943Sdim IsPostfixUpdate); 5420280031Sdim} 5421280031Sdim 5422280031SdimStmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses, 5423280031Sdim Stmt *AStmt, 5424280031Sdim SourceLocation StartLoc, 5425280031Sdim SourceLocation EndLoc) { 5426296417Sdim if (!AStmt) 5427296417Sdim return StmtError(); 5428280031Sdim 5429296417Sdim CapturedStmt *CS = cast<CapturedStmt>(AStmt); 5430296417Sdim // 1.2.2 OpenMP Language Terminology 5431296417Sdim // Structured block - An executable statement with a single entry at the 5432296417Sdim // top and a single exit at the bottom. 5433296417Sdim // The point of exit cannot be a branch out of the structured block. 5434296417Sdim // longjmp() and throw() must not violate the entry/exit criteria. 5435296417Sdim CS->getCapturedDecl()->setNothrow(); 5436296417Sdim 5437280031Sdim // OpenMP [2.16, Nesting of Regions] 5438280031Sdim // If specified, a teams construct must be contained within a target 5439280031Sdim // construct. That target construct must contain no statements or directives 5440280031Sdim // outside of the teams construct. 5441280031Sdim if (DSAStack->hasInnerTeamsRegion()) { 5442280031Sdim auto S = AStmt->IgnoreContainers(/*IgnoreCaptured*/ true); 5443280031Sdim bool OMPTeamsFound = true; 5444280031Sdim if (auto *CS = dyn_cast<CompoundStmt>(S)) { 5445280031Sdim auto I = CS->body_begin(); 5446280031Sdim while (I != CS->body_end()) { 5447280031Sdim auto OED = dyn_cast<OMPExecutableDirective>(*I); 5448280031Sdim if (!OED || !isOpenMPTeamsDirective(OED->getDirectiveKind())) { 5449280031Sdim OMPTeamsFound = false; 5450280031Sdim break; 5451280031Sdim } 5452280031Sdim ++I; 5453280031Sdim } 5454280031Sdim assert(I != CS->body_end() && "Not found statement"); 5455280031Sdim S = *I; 5456280031Sdim } 5457280031Sdim if (!OMPTeamsFound) { 5458280031Sdim Diag(StartLoc, diag::err_omp_target_contains_not_only_teams); 5459280031Sdim Diag(DSAStack->getInnerTeamsRegionLoc(), 5460280031Sdim diag::note_omp_nested_teams_construct_here); 5461280031Sdim Diag(S->getLocStart(), diag::note_omp_nested_statement_here) 5462280031Sdim << isa<OMPExecutableDirective>(S); 5463280031Sdim return StmtError(); 5464280031Sdim } 5465280031Sdim } 5466280031Sdim 5467280031Sdim getCurFunction()->setHasBranchProtectedScope(); 5468280031Sdim 5469280031Sdim return OMPTargetDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt); 5470280031Sdim} 5471280031Sdim 5472296417SdimStmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses, 5473296417Sdim Stmt *AStmt, 5474296417Sdim SourceLocation StartLoc, 5475296417Sdim SourceLocation EndLoc) { 5476296417Sdim if (!AStmt) 5477296417Sdim return StmtError(); 5478296417Sdim 5479296417Sdim assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 5480296417Sdim 5481296417Sdim getCurFunction()->setHasBranchProtectedScope(); 5482296417Sdim 5483296417Sdim return OMPTargetDataDirective::Create(Context, StartLoc, EndLoc, Clauses, 5484296417Sdim AStmt); 5485296417Sdim} 5486296417Sdim 5487280031SdimStmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses, 5488280031Sdim Stmt *AStmt, SourceLocation StartLoc, 5489280031Sdim SourceLocation EndLoc) { 5490296417Sdim if (!AStmt) 5491296417Sdim return StmtError(); 5492296417Sdim 5493280031Sdim CapturedStmt *CS = cast<CapturedStmt>(AStmt); 5494280031Sdim // 1.2.2 OpenMP Language Terminology 5495280031Sdim // Structured block - An executable statement with a single entry at the 5496280031Sdim // top and a single exit at the bottom. 5497280031Sdim // The point of exit cannot be a branch out of the structured block. 5498280031Sdim // longjmp() and throw() must not violate the entry/exit criteria. 5499280031Sdim CS->getCapturedDecl()->setNothrow(); 5500280031Sdim 5501280031Sdim getCurFunction()->setHasBranchProtectedScope(); 5502280031Sdim 5503280031Sdim return OMPTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt); 5504280031Sdim} 5505280031Sdim 5506288943SdimStmtResult 5507288943SdimSema::ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, 5508288943Sdim SourceLocation EndLoc, 5509288943Sdim OpenMPDirectiveKind CancelRegion) { 5510288943Sdim if (CancelRegion != OMPD_parallel && CancelRegion != OMPD_for && 5511288943Sdim CancelRegion != OMPD_sections && CancelRegion != OMPD_taskgroup) { 5512288943Sdim Diag(StartLoc, diag::err_omp_wrong_cancel_region) 5513288943Sdim << getOpenMPDirectiveName(CancelRegion); 5514288943Sdim return StmtError(); 5515288943Sdim } 5516288943Sdim if (DSAStack->isParentNowaitRegion()) { 5517288943Sdim Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0; 5518288943Sdim return StmtError(); 5519288943Sdim } 5520288943Sdim if (DSAStack->isParentOrderedRegion()) { 5521288943Sdim Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0; 5522288943Sdim return StmtError(); 5523288943Sdim } 5524288943Sdim return OMPCancellationPointDirective::Create(Context, StartLoc, EndLoc, 5525288943Sdim CancelRegion); 5526288943Sdim} 5527288943Sdim 5528296417SdimStmtResult Sema::ActOnOpenMPCancelDirective(ArrayRef<OMPClause *> Clauses, 5529296417Sdim SourceLocation StartLoc, 5530288943Sdim SourceLocation EndLoc, 5531288943Sdim OpenMPDirectiveKind CancelRegion) { 5532288943Sdim if (CancelRegion != OMPD_parallel && CancelRegion != OMPD_for && 5533288943Sdim CancelRegion != OMPD_sections && CancelRegion != OMPD_taskgroup) { 5534288943Sdim Diag(StartLoc, diag::err_omp_wrong_cancel_region) 5535288943Sdim << getOpenMPDirectiveName(CancelRegion); 5536288943Sdim return StmtError(); 5537288943Sdim } 5538288943Sdim if (DSAStack->isParentNowaitRegion()) { 5539288943Sdim Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1; 5540288943Sdim return StmtError(); 5541288943Sdim } 5542288943Sdim if (DSAStack->isParentOrderedRegion()) { 5543288943Sdim Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1; 5544288943Sdim return StmtError(); 5545288943Sdim } 5546296417Sdim DSAStack->setParentCancelRegion(/*Cancel=*/true); 5547296417Sdim return OMPCancelDirective::Create(Context, StartLoc, EndLoc, Clauses, 5548296417Sdim CancelRegion); 5549288943Sdim} 5550288943Sdim 5551296417Sdimstatic bool checkGrainsizeNumTasksClauses(Sema &S, 5552296417Sdim ArrayRef<OMPClause *> Clauses) { 5553296417Sdim OMPClause *PrevClause = nullptr; 5554296417Sdim bool ErrorFound = false; 5555296417Sdim for (auto *C : Clauses) { 5556296417Sdim if (C->getClauseKind() == OMPC_grainsize || 5557296417Sdim C->getClauseKind() == OMPC_num_tasks) { 5558296417Sdim if (!PrevClause) 5559296417Sdim PrevClause = C; 5560296417Sdim else if (PrevClause->getClauseKind() != C->getClauseKind()) { 5561296417Sdim S.Diag(C->getLocStart(), 5562296417Sdim diag::err_omp_grainsize_num_tasks_mutually_exclusive) 5563296417Sdim << getOpenMPClauseName(C->getClauseKind()) 5564296417Sdim << getOpenMPClauseName(PrevClause->getClauseKind()); 5565296417Sdim S.Diag(PrevClause->getLocStart(), 5566296417Sdim diag::note_omp_previous_grainsize_num_tasks) 5567296417Sdim << getOpenMPClauseName(PrevClause->getClauseKind()); 5568296417Sdim ErrorFound = true; 5569296417Sdim } 5570296417Sdim } 5571296417Sdim } 5572296417Sdim return ErrorFound; 5573296417Sdim} 5574296417Sdim 5575296417SdimStmtResult Sema::ActOnOpenMPTaskLoopDirective( 5576296417Sdim ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 5577296417Sdim SourceLocation EndLoc, 5578296417Sdim llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { 5579296417Sdim if (!AStmt) 5580296417Sdim return StmtError(); 5581296417Sdim 5582296417Sdim assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 5583296417Sdim OMPLoopDirective::HelperExprs B; 5584296417Sdim // In presence of clause 'collapse' or 'ordered' with number of loops, it will 5585296417Sdim // define the nested loops number. 5586296417Sdim unsigned NestedLoopCount = 5587296417Sdim CheckOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses), 5588296417Sdim /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack, 5589296417Sdim VarsWithImplicitDSA, B); 5590296417Sdim if (NestedLoopCount == 0) 5591296417Sdim return StmtError(); 5592296417Sdim 5593296417Sdim assert((CurContext->isDependentContext() || B.builtAll()) && 5594296417Sdim "omp for loop exprs were not built"); 5595296417Sdim 5596296417Sdim // OpenMP, [2.9.2 taskloop Construct, Restrictions] 5597296417Sdim // The grainsize clause and num_tasks clause are mutually exclusive and may 5598296417Sdim // not appear on the same taskloop directive. 5599296417Sdim if (checkGrainsizeNumTasksClauses(*this, Clauses)) 5600296417Sdim return StmtError(); 5601296417Sdim 5602296417Sdim getCurFunction()->setHasBranchProtectedScope(); 5603296417Sdim return OMPTaskLoopDirective::Create(Context, StartLoc, EndLoc, 5604296417Sdim NestedLoopCount, Clauses, AStmt, B); 5605296417Sdim} 5606296417Sdim 5607296417SdimStmtResult Sema::ActOnOpenMPTaskLoopSimdDirective( 5608296417Sdim ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 5609296417Sdim SourceLocation EndLoc, 5610296417Sdim llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { 5611296417Sdim if (!AStmt) 5612296417Sdim return StmtError(); 5613296417Sdim 5614296417Sdim assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 5615296417Sdim OMPLoopDirective::HelperExprs B; 5616296417Sdim // In presence of clause 'collapse' or 'ordered' with number of loops, it will 5617296417Sdim // define the nested loops number. 5618296417Sdim unsigned NestedLoopCount = 5619296417Sdim CheckOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses), 5620296417Sdim /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack, 5621296417Sdim VarsWithImplicitDSA, B); 5622296417Sdim if (NestedLoopCount == 0) 5623296417Sdim return StmtError(); 5624296417Sdim 5625296417Sdim assert((CurContext->isDependentContext() || B.builtAll()) && 5626296417Sdim "omp for loop exprs were not built"); 5627296417Sdim 5628296417Sdim // OpenMP, [2.9.2 taskloop Construct, Restrictions] 5629296417Sdim // The grainsize clause and num_tasks clause are mutually exclusive and may 5630296417Sdim // not appear on the same taskloop directive. 5631296417Sdim if (checkGrainsizeNumTasksClauses(*this, Clauses)) 5632296417Sdim return StmtError(); 5633296417Sdim 5634296417Sdim getCurFunction()->setHasBranchProtectedScope(); 5635296417Sdim return OMPTaskLoopSimdDirective::Create(Context, StartLoc, EndLoc, 5636296417Sdim NestedLoopCount, Clauses, AStmt, B); 5637296417Sdim} 5638296417Sdim 5639296417SdimStmtResult Sema::ActOnOpenMPDistributeDirective( 5640296417Sdim ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, 5641296417Sdim SourceLocation EndLoc, 5642296417Sdim llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { 5643296417Sdim if (!AStmt) 5644296417Sdim return StmtError(); 5645296417Sdim 5646296417Sdim assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); 5647296417Sdim OMPLoopDirective::HelperExprs B; 5648296417Sdim // In presence of clause 'collapse' with number of loops, it will 5649296417Sdim // define the nested loops number. 5650296417Sdim unsigned NestedLoopCount = 5651296417Sdim CheckOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses), 5652296417Sdim nullptr /*ordered not a clause on distribute*/, AStmt, 5653296417Sdim *this, *DSAStack, VarsWithImplicitDSA, B); 5654296417Sdim if (NestedLoopCount == 0) 5655296417Sdim return StmtError(); 5656296417Sdim 5657296417Sdim assert((CurContext->isDependentContext() || B.builtAll()) && 5658296417Sdim "omp for loop exprs were not built"); 5659296417Sdim 5660296417Sdim getCurFunction()->setHasBranchProtectedScope(); 5661296417Sdim return OMPDistributeDirective::Create(Context, StartLoc, EndLoc, 5662296417Sdim NestedLoopCount, Clauses, AStmt, B); 5663296417Sdim} 5664296417Sdim 5665276479SdimOMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, 5666276479Sdim SourceLocation StartLoc, 5667276479Sdim SourceLocation LParenLoc, 5668276479Sdim SourceLocation EndLoc) { 5669276479Sdim OMPClause *Res = nullptr; 5670261991Sdim switch (Kind) { 5671276479Sdim case OMPC_final: 5672276479Sdim Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc); 5673276479Sdim break; 5674276479Sdim case OMPC_num_threads: 5675276479Sdim Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc); 5676276479Sdim break; 5677276479Sdim case OMPC_safelen: 5678276479Sdim Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc); 5679276479Sdim break; 5680296417Sdim case OMPC_simdlen: 5681296417Sdim Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc); 5682296417Sdim break; 5683276479Sdim case OMPC_collapse: 5684276479Sdim Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc); 5685276479Sdim break; 5686296417Sdim case OMPC_ordered: 5687296417Sdim Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr); 5688296417Sdim break; 5689296417Sdim case OMPC_device: 5690296417Sdim Res = ActOnOpenMPDeviceClause(Expr, StartLoc, LParenLoc, EndLoc); 5691296417Sdim break; 5692296417Sdim case OMPC_num_teams: 5693296417Sdim Res = ActOnOpenMPNumTeamsClause(Expr, StartLoc, LParenLoc, EndLoc); 5694296417Sdim break; 5695296417Sdim case OMPC_thread_limit: 5696296417Sdim Res = ActOnOpenMPThreadLimitClause(Expr, StartLoc, LParenLoc, EndLoc); 5697296417Sdim break; 5698296417Sdim case OMPC_priority: 5699296417Sdim Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc); 5700296417Sdim break; 5701296417Sdim case OMPC_grainsize: 5702296417Sdim Res = ActOnOpenMPGrainsizeClause(Expr, StartLoc, LParenLoc, EndLoc); 5703296417Sdim break; 5704296417Sdim case OMPC_num_tasks: 5705296417Sdim Res = ActOnOpenMPNumTasksClause(Expr, StartLoc, LParenLoc, EndLoc); 5706296417Sdim break; 5707296417Sdim case OMPC_hint: 5708296417Sdim Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc); 5709296417Sdim break; 5710296417Sdim case OMPC_if: 5711261991Sdim case OMPC_default: 5712276479Sdim case OMPC_proc_bind: 5713276479Sdim case OMPC_schedule: 5714276479Sdim case OMPC_private: 5715276479Sdim case OMPC_firstprivate: 5716276479Sdim case OMPC_lastprivate: 5717276479Sdim case OMPC_shared: 5718276479Sdim case OMPC_reduction: 5719276479Sdim case OMPC_linear: 5720276479Sdim case OMPC_aligned: 5721276479Sdim case OMPC_copyin: 5722276479Sdim case OMPC_copyprivate: 5723276479Sdim case OMPC_nowait: 5724276479Sdim case OMPC_untied: 5725276479Sdim case OMPC_mergeable: 5726276479Sdim case OMPC_threadprivate: 5727276479Sdim case OMPC_flush: 5728280031Sdim case OMPC_read: 5729280031Sdim case OMPC_write: 5730280031Sdim case OMPC_update: 5731280031Sdim case OMPC_capture: 5732280031Sdim case OMPC_seq_cst: 5733288943Sdim case OMPC_depend: 5734296417Sdim case OMPC_threads: 5735296417Sdim case OMPC_simd: 5736296417Sdim case OMPC_map: 5737296417Sdim case OMPC_nogroup: 5738276479Sdim case OMPC_unknown: 5739276479Sdim llvm_unreachable("Clause is not allowed."); 5740276479Sdim } 5741276479Sdim return Res; 5742276479Sdim} 5743276479Sdim 5744296417SdimOMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, 5745296417Sdim Expr *Condition, SourceLocation StartLoc, 5746276479Sdim SourceLocation LParenLoc, 5747296417Sdim SourceLocation NameModifierLoc, 5748296417Sdim SourceLocation ColonLoc, 5749276479Sdim SourceLocation EndLoc) { 5750276479Sdim Expr *ValExpr = Condition; 5751276479Sdim if (!Condition->isValueDependent() && !Condition->isTypeDependent() && 5752276479Sdim !Condition->isInstantiationDependent() && 5753276479Sdim !Condition->containsUnexpandedParameterPack()) { 5754276479Sdim ExprResult Val = ActOnBooleanCondition(DSAStack->getCurScope(), 5755276479Sdim Condition->getExprLoc(), Condition); 5756276479Sdim if (Val.isInvalid()) 5757276479Sdim return nullptr; 5758276479Sdim 5759276479Sdim ValExpr = Val.get(); 5760276479Sdim } 5761276479Sdim 5762296417Sdim return new (Context) OMPIfClause(NameModifier, ValExpr, StartLoc, LParenLoc, 5763296417Sdim NameModifierLoc, ColonLoc, EndLoc); 5764276479Sdim} 5765276479Sdim 5766276479SdimOMPClause *Sema::ActOnOpenMPFinalClause(Expr *Condition, 5767276479Sdim SourceLocation StartLoc, 5768276479Sdim SourceLocation LParenLoc, 5769276479Sdim SourceLocation EndLoc) { 5770276479Sdim Expr *ValExpr = Condition; 5771276479Sdim if (!Condition->isValueDependent() && !Condition->isTypeDependent() && 5772276479Sdim !Condition->isInstantiationDependent() && 5773276479Sdim !Condition->containsUnexpandedParameterPack()) { 5774276479Sdim ExprResult Val = ActOnBooleanCondition(DSAStack->getCurScope(), 5775276479Sdim Condition->getExprLoc(), Condition); 5776276479Sdim if (Val.isInvalid()) 5777276479Sdim return nullptr; 5778276479Sdim 5779276479Sdim ValExpr = Val.get(); 5780276479Sdim } 5781276479Sdim 5782276479Sdim return new (Context) OMPFinalClause(ValExpr, StartLoc, LParenLoc, EndLoc); 5783276479Sdim} 5784276479SdimExprResult Sema::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc, 5785276479Sdim Expr *Op) { 5786276479Sdim if (!Op) 5787276479Sdim return ExprError(); 5788276479Sdim 5789276479Sdim class IntConvertDiagnoser : public ICEConvertDiagnoser { 5790276479Sdim public: 5791276479Sdim IntConvertDiagnoser() 5792276479Sdim : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {} 5793276479Sdim SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, 5794276479Sdim QualType T) override { 5795276479Sdim return S.Diag(Loc, diag::err_omp_not_integral) << T; 5796276479Sdim } 5797276479Sdim SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc, 5798276479Sdim QualType T) override { 5799276479Sdim return S.Diag(Loc, diag::err_omp_incomplete_type) << T; 5800276479Sdim } 5801276479Sdim SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc, 5802276479Sdim QualType T, 5803276479Sdim QualType ConvTy) override { 5804276479Sdim return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy; 5805276479Sdim } 5806276479Sdim SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv, 5807276479Sdim QualType ConvTy) override { 5808276479Sdim return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here) 5809276479Sdim << ConvTy->isEnumeralType() << ConvTy; 5810276479Sdim } 5811276479Sdim SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc, 5812276479Sdim QualType T) override { 5813276479Sdim return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T; 5814276479Sdim } 5815276479Sdim SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv, 5816276479Sdim QualType ConvTy) override { 5817276479Sdim return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here) 5818276479Sdim << ConvTy->isEnumeralType() << ConvTy; 5819276479Sdim } 5820276479Sdim SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType, 5821276479Sdim QualType) override { 5822276479Sdim llvm_unreachable("conversion functions are permitted"); 5823276479Sdim } 5824276479Sdim } ConvertDiagnoser; 5825276479Sdim return PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser); 5826276479Sdim} 5827276479Sdim 5828296417Sdimstatic bool IsNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, 5829296417Sdim OpenMPClauseKind CKind, 5830296417Sdim bool StrictlyPositive) { 5831296417Sdim if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() && 5832296417Sdim !ValExpr->isInstantiationDependent()) { 5833296417Sdim SourceLocation Loc = ValExpr->getExprLoc(); 5834296417Sdim ExprResult Value = 5835296417Sdim SemaRef.PerformOpenMPImplicitIntegerConversion(Loc, ValExpr); 5836296417Sdim if (Value.isInvalid()) 5837296417Sdim return false; 5838296417Sdim 5839296417Sdim ValExpr = Value.get(); 5840296417Sdim // The expression must evaluate to a non-negative integer value. 5841296417Sdim llvm::APSInt Result; 5842296417Sdim if (ValExpr->isIntegerConstantExpr(Result, SemaRef.Context) && 5843296417Sdim Result.isSigned() && 5844296417Sdim !((!StrictlyPositive && Result.isNonNegative()) || 5845296417Sdim (StrictlyPositive && Result.isStrictlyPositive()))) { 5846296417Sdim SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause) 5847296417Sdim << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0) 5848296417Sdim << ValExpr->getSourceRange(); 5849296417Sdim return false; 5850296417Sdim } 5851296417Sdim } 5852296417Sdim return true; 5853296417Sdim} 5854296417Sdim 5855276479SdimOMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads, 5856276479Sdim SourceLocation StartLoc, 5857276479Sdim SourceLocation LParenLoc, 5858276479Sdim SourceLocation EndLoc) { 5859276479Sdim Expr *ValExpr = NumThreads; 5860276479Sdim 5861296417Sdim // OpenMP [2.5, Restrictions] 5862296417Sdim // The num_threads expression must evaluate to a positive integer value. 5863296417Sdim if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_num_threads, 5864296417Sdim /*StrictlyPositive=*/true)) 5865296417Sdim return nullptr; 5866276479Sdim 5867276479Sdim return new (Context) 5868276479Sdim OMPNumThreadsClause(ValExpr, StartLoc, LParenLoc, EndLoc); 5869276479Sdim} 5870276479Sdim 5871276479SdimExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E, 5872296417Sdim OpenMPClauseKind CKind, 5873296417Sdim bool StrictlyPositive) { 5874276479Sdim if (!E) 5875276479Sdim return ExprError(); 5876276479Sdim if (E->isValueDependent() || E->isTypeDependent() || 5877276479Sdim E->isInstantiationDependent() || E->containsUnexpandedParameterPack()) 5878276479Sdim return E; 5879276479Sdim llvm::APSInt Result; 5880276479Sdim ExprResult ICE = VerifyIntegerConstantExpression(E, &Result); 5881276479Sdim if (ICE.isInvalid()) 5882276479Sdim return ExprError(); 5883296417Sdim if ((StrictlyPositive && !Result.isStrictlyPositive()) || 5884296417Sdim (!StrictlyPositive && !Result.isNonNegative())) { 5885276479Sdim Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause) 5886296417Sdim << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0) 5887296417Sdim << E->getSourceRange(); 5888276479Sdim return ExprError(); 5889276479Sdim } 5890280031Sdim if (CKind == OMPC_aligned && !Result.isPowerOf2()) { 5891280031Sdim Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two) 5892280031Sdim << E->getSourceRange(); 5893280031Sdim return ExprError(); 5894280031Sdim } 5895296417Sdim if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1) 5896296417Sdim DSAStack->setAssociatedLoops(Result.getExtValue()); 5897296417Sdim else if (CKind == OMPC_ordered) 5898296417Sdim DSAStack->setAssociatedLoops(Result.getExtValue()); 5899276479Sdim return ICE; 5900276479Sdim} 5901276479Sdim 5902276479SdimOMPClause *Sema::ActOnOpenMPSafelenClause(Expr *Len, SourceLocation StartLoc, 5903276479Sdim SourceLocation LParenLoc, 5904276479Sdim SourceLocation EndLoc) { 5905276479Sdim // OpenMP [2.8.1, simd construct, Description] 5906276479Sdim // The parameter of the safelen clause must be a constant 5907276479Sdim // positive integer expression. 5908276479Sdim ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen); 5909276479Sdim if (Safelen.isInvalid()) 5910276479Sdim return nullptr; 5911276479Sdim return new (Context) 5912276479Sdim OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc); 5913276479Sdim} 5914276479Sdim 5915296417SdimOMPClause *Sema::ActOnOpenMPSimdlenClause(Expr *Len, SourceLocation StartLoc, 5916296417Sdim SourceLocation LParenLoc, 5917296417Sdim SourceLocation EndLoc) { 5918296417Sdim // OpenMP [2.8.1, simd construct, Description] 5919296417Sdim // The parameter of the simdlen clause must be a constant 5920296417Sdim // positive integer expression. 5921296417Sdim ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen); 5922296417Sdim if (Simdlen.isInvalid()) 5923296417Sdim return nullptr; 5924296417Sdim return new (Context) 5925296417Sdim OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc); 5926296417Sdim} 5927296417Sdim 5928276479SdimOMPClause *Sema::ActOnOpenMPCollapseClause(Expr *NumForLoops, 5929276479Sdim SourceLocation StartLoc, 5930276479Sdim SourceLocation LParenLoc, 5931276479Sdim SourceLocation EndLoc) { 5932276479Sdim // OpenMP [2.7.1, loop construct, Description] 5933276479Sdim // OpenMP [2.8.1, simd construct, Description] 5934276479Sdim // OpenMP [2.9.6, distribute construct, Description] 5935276479Sdim // The parameter of the collapse clause must be a constant 5936276479Sdim // positive integer expression. 5937276479Sdim ExprResult NumForLoopsResult = 5938276479Sdim VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse); 5939276479Sdim if (NumForLoopsResult.isInvalid()) 5940276479Sdim return nullptr; 5941276479Sdim return new (Context) 5942276479Sdim OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc); 5943276479Sdim} 5944276479Sdim 5945296417SdimOMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc, 5946296417Sdim SourceLocation EndLoc, 5947296417Sdim SourceLocation LParenLoc, 5948296417Sdim Expr *NumForLoops) { 5949296417Sdim // OpenMP [2.7.1, loop construct, Description] 5950296417Sdim // OpenMP [2.8.1, simd construct, Description] 5951296417Sdim // OpenMP [2.9.6, distribute construct, Description] 5952296417Sdim // The parameter of the ordered clause must be a constant 5953296417Sdim // positive integer expression if any. 5954296417Sdim if (NumForLoops && LParenLoc.isValid()) { 5955296417Sdim ExprResult NumForLoopsResult = 5956296417Sdim VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered); 5957296417Sdim if (NumForLoopsResult.isInvalid()) 5958296417Sdim return nullptr; 5959296417Sdim NumForLoops = NumForLoopsResult.get(); 5960296417Sdim } else 5961296417Sdim NumForLoops = nullptr; 5962296417Sdim DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops); 5963296417Sdim return new (Context) 5964296417Sdim OMPOrderedClause(NumForLoops, StartLoc, LParenLoc, EndLoc); 5965296417Sdim} 5966296417Sdim 5967276479SdimOMPClause *Sema::ActOnOpenMPSimpleClause( 5968276479Sdim OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, 5969276479Sdim SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { 5970276479Sdim OMPClause *Res = nullptr; 5971276479Sdim switch (Kind) { 5972276479Sdim case OMPC_default: 5973261991Sdim Res = 5974276479Sdim ActOnOpenMPDefaultClause(static_cast<OpenMPDefaultClauseKind>(Argument), 5975276479Sdim ArgumentLoc, StartLoc, LParenLoc, EndLoc); 5976261991Sdim break; 5977276479Sdim case OMPC_proc_bind: 5978276479Sdim Res = ActOnOpenMPProcBindClause( 5979276479Sdim static_cast<OpenMPProcBindClauseKind>(Argument), ArgumentLoc, StartLoc, 5980276479Sdim LParenLoc, EndLoc); 5981276479Sdim break; 5982276479Sdim case OMPC_if: 5983276479Sdim case OMPC_final: 5984276479Sdim case OMPC_num_threads: 5985276479Sdim case OMPC_safelen: 5986296417Sdim case OMPC_simdlen: 5987276479Sdim case OMPC_collapse: 5988276479Sdim case OMPC_schedule: 5989261991Sdim case OMPC_private: 5990261991Sdim case OMPC_firstprivate: 5991276479Sdim case OMPC_lastprivate: 5992261991Sdim case OMPC_shared: 5993276479Sdim case OMPC_reduction: 5994276479Sdim case OMPC_linear: 5995276479Sdim case OMPC_aligned: 5996276479Sdim case OMPC_copyin: 5997276479Sdim case OMPC_copyprivate: 5998276479Sdim case OMPC_ordered: 5999276479Sdim case OMPC_nowait: 6000276479Sdim case OMPC_untied: 6001276479Sdim case OMPC_mergeable: 6002261991Sdim case OMPC_threadprivate: 6003276479Sdim case OMPC_flush: 6004280031Sdim case OMPC_read: 6005280031Sdim case OMPC_write: 6006280031Sdim case OMPC_update: 6007280031Sdim case OMPC_capture: 6008280031Sdim case OMPC_seq_cst: 6009288943Sdim case OMPC_depend: 6010296417Sdim case OMPC_device: 6011296417Sdim case OMPC_threads: 6012296417Sdim case OMPC_simd: 6013296417Sdim case OMPC_map: 6014296417Sdim case OMPC_num_teams: 6015296417Sdim case OMPC_thread_limit: 6016296417Sdim case OMPC_priority: 6017296417Sdim case OMPC_grainsize: 6018296417Sdim case OMPC_nogroup: 6019296417Sdim case OMPC_num_tasks: 6020296417Sdim case OMPC_hint: 6021261991Sdim case OMPC_unknown: 6022261991Sdim llvm_unreachable("Clause is not allowed."); 6023261991Sdim } 6024261991Sdim return Res; 6025261991Sdim} 6026261991Sdim 6027296417Sdimstatic std::string 6028296417SdimgetListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, 6029296417Sdim ArrayRef<unsigned> Exclude = llvm::None) { 6030296417Sdim std::string Values; 6031296417Sdim unsigned Bound = Last >= 2 ? Last - 2 : 0; 6032296417Sdim unsigned Skipped = Exclude.size(); 6033296417Sdim auto S = Exclude.begin(), E = Exclude.end(); 6034296417Sdim for (unsigned i = First; i < Last; ++i) { 6035296417Sdim if (std::find(S, E, i) != E) { 6036296417Sdim --Skipped; 6037296417Sdim continue; 6038296417Sdim } 6039296417Sdim Values += "'"; 6040296417Sdim Values += getOpenMPSimpleClauseTypeName(K, i); 6041296417Sdim Values += "'"; 6042296417Sdim if (i == Bound - Skipped) 6043296417Sdim Values += " or "; 6044296417Sdim else if (i != Bound + 1 - Skipped) 6045296417Sdim Values += ", "; 6046296417Sdim } 6047296417Sdim return Values; 6048296417Sdim} 6049296417Sdim 6050261991SdimOMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind, 6051261991Sdim SourceLocation KindKwLoc, 6052261991Sdim SourceLocation StartLoc, 6053261991Sdim SourceLocation LParenLoc, 6054261991Sdim SourceLocation EndLoc) { 6055261991Sdim if (Kind == OMPC_DEFAULT_unknown) { 6056276479Sdim static_assert(OMPC_DEFAULT_unknown > 0, 6057276479Sdim "OMPC_DEFAULT_unknown not greater than 0"); 6058261991Sdim Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) 6059296417Sdim << getListOfPossibleValues(OMPC_default, /*First=*/0, 6060296417Sdim /*Last=*/OMPC_DEFAULT_unknown) 6061296417Sdim << getOpenMPClauseName(OMPC_default); 6062276479Sdim return nullptr; 6063261991Sdim } 6064261991Sdim switch (Kind) { 6065261991Sdim case OMPC_DEFAULT_none: 6066276479Sdim DSAStack->setDefaultDSANone(KindKwLoc); 6067261991Sdim break; 6068261991Sdim case OMPC_DEFAULT_shared: 6069276479Sdim DSAStack->setDefaultDSAShared(KindKwLoc); 6070261991Sdim break; 6071276479Sdim case OMPC_DEFAULT_unknown: 6072276479Sdim llvm_unreachable("Clause kind is not allowed."); 6073261991Sdim break; 6074261991Sdim } 6075276479Sdim return new (Context) 6076276479Sdim OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); 6077261991Sdim} 6078261991Sdim 6079276479SdimOMPClause *Sema::ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind, 6080276479Sdim SourceLocation KindKwLoc, 6081276479Sdim SourceLocation StartLoc, 6082276479Sdim SourceLocation LParenLoc, 6083276479Sdim SourceLocation EndLoc) { 6084276479Sdim if (Kind == OMPC_PROC_BIND_unknown) { 6085276479Sdim Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) 6086296417Sdim << getListOfPossibleValues(OMPC_proc_bind, /*First=*/0, 6087296417Sdim /*Last=*/OMPC_PROC_BIND_unknown) 6088296417Sdim << getOpenMPClauseName(OMPC_proc_bind); 6089276479Sdim return nullptr; 6090276479Sdim } 6091276479Sdim return new (Context) 6092276479Sdim OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); 6093276479Sdim} 6094276479Sdim 6095276479SdimOMPClause *Sema::ActOnOpenMPSingleExprWithArgClause( 6096296417Sdim OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr, 6097276479Sdim SourceLocation StartLoc, SourceLocation LParenLoc, 6098296417Sdim ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc, 6099276479Sdim SourceLocation EndLoc) { 6100276479Sdim OMPClause *Res = nullptr; 6101276479Sdim switch (Kind) { 6102276479Sdim case OMPC_schedule: 6103296417Sdim enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements }; 6104296417Sdim assert(Argument.size() == NumberOfElements && 6105296417Sdim ArgumentLoc.size() == NumberOfElements); 6106276479Sdim Res = ActOnOpenMPScheduleClause( 6107296417Sdim static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]), 6108296417Sdim static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]), 6109296417Sdim static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr, 6110296417Sdim StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2], 6111296417Sdim ArgumentLoc[ScheduleKind], DelimLoc, EndLoc); 6112276479Sdim break; 6113276479Sdim case OMPC_if: 6114296417Sdim assert(Argument.size() == 1 && ArgumentLoc.size() == 1); 6115296417Sdim Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()), 6116296417Sdim Expr, StartLoc, LParenLoc, ArgumentLoc.back(), 6117296417Sdim DelimLoc, EndLoc); 6118296417Sdim break; 6119276479Sdim case OMPC_final: 6120276479Sdim case OMPC_num_threads: 6121276479Sdim case OMPC_safelen: 6122296417Sdim case OMPC_simdlen: 6123276479Sdim case OMPC_collapse: 6124276479Sdim case OMPC_default: 6125276479Sdim case OMPC_proc_bind: 6126276479Sdim case OMPC_private: 6127276479Sdim case OMPC_firstprivate: 6128276479Sdim case OMPC_lastprivate: 6129276479Sdim case OMPC_shared: 6130276479Sdim case OMPC_reduction: 6131276479Sdim case OMPC_linear: 6132276479Sdim case OMPC_aligned: 6133276479Sdim case OMPC_copyin: 6134276479Sdim case OMPC_copyprivate: 6135276479Sdim case OMPC_ordered: 6136276479Sdim case OMPC_nowait: 6137276479Sdim case OMPC_untied: 6138276479Sdim case OMPC_mergeable: 6139276479Sdim case OMPC_threadprivate: 6140276479Sdim case OMPC_flush: 6141280031Sdim case OMPC_read: 6142280031Sdim case OMPC_write: 6143280031Sdim case OMPC_update: 6144280031Sdim case OMPC_capture: 6145280031Sdim case OMPC_seq_cst: 6146288943Sdim case OMPC_depend: 6147296417Sdim case OMPC_device: 6148296417Sdim case OMPC_threads: 6149296417Sdim case OMPC_simd: 6150296417Sdim case OMPC_map: 6151296417Sdim case OMPC_num_teams: 6152296417Sdim case OMPC_thread_limit: 6153296417Sdim case OMPC_priority: 6154296417Sdim case OMPC_grainsize: 6155296417Sdim case OMPC_nogroup: 6156296417Sdim case OMPC_num_tasks: 6157296417Sdim case OMPC_hint: 6158276479Sdim case OMPC_unknown: 6159276479Sdim llvm_unreachable("Clause is not allowed."); 6160276479Sdim } 6161276479Sdim return Res; 6162276479Sdim} 6163276479Sdim 6164296417Sdimstatic bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1, 6165296417Sdim OpenMPScheduleClauseModifier M2, 6166296417Sdim SourceLocation M1Loc, SourceLocation M2Loc) { 6167296417Sdim if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) { 6168296417Sdim SmallVector<unsigned, 2> Excluded; 6169296417Sdim if (M2 != OMPC_SCHEDULE_MODIFIER_unknown) 6170296417Sdim Excluded.push_back(M2); 6171296417Sdim if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) 6172296417Sdim Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic); 6173296417Sdim if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic) 6174296417Sdim Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic); 6175296417Sdim S.Diag(M1Loc, diag::err_omp_unexpected_clause_value) 6176296417Sdim << getListOfPossibleValues(OMPC_schedule, 6177296417Sdim /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1, 6178296417Sdim /*Last=*/OMPC_SCHEDULE_MODIFIER_last, 6179296417Sdim Excluded) 6180296417Sdim << getOpenMPClauseName(OMPC_schedule); 6181296417Sdim return true; 6182296417Sdim } 6183296417Sdim return false; 6184296417Sdim} 6185296417Sdim 6186276479SdimOMPClause *Sema::ActOnOpenMPScheduleClause( 6187296417Sdim OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 6188276479Sdim OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, 6189296417Sdim SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, 6190296417Sdim SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) { 6191296417Sdim if (checkScheduleModifiers(*this, M1, M2, M1Loc, M2Loc) || 6192296417Sdim checkScheduleModifiers(*this, M2, M1, M2Loc, M1Loc)) 6193296417Sdim return nullptr; 6194296417Sdim // OpenMP, 2.7.1, Loop Construct, Restrictions 6195296417Sdim // Either the monotonic modifier or the nonmonotonic modifier can be specified 6196296417Sdim // but not both. 6197296417Sdim if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) || 6198296417Sdim (M1 == OMPC_SCHEDULE_MODIFIER_monotonic && 6199296417Sdim M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) || 6200296417Sdim (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic && 6201296417Sdim M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) { 6202296417Sdim Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier) 6203296417Sdim << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2) 6204296417Sdim << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1); 6205296417Sdim return nullptr; 6206296417Sdim } 6207276479Sdim if (Kind == OMPC_SCHEDULE_unknown) { 6208276479Sdim std::string Values; 6209296417Sdim if (M1Loc.isInvalid() && M2Loc.isInvalid()) { 6210296417Sdim unsigned Exclude[] = {OMPC_SCHEDULE_unknown}; 6211296417Sdim Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0, 6212296417Sdim /*Last=*/OMPC_SCHEDULE_MODIFIER_last, 6213296417Sdim Exclude); 6214296417Sdim } else { 6215296417Sdim Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0, 6216296417Sdim /*Last=*/OMPC_SCHEDULE_unknown); 6217276479Sdim } 6218276479Sdim Diag(KindLoc, diag::err_omp_unexpected_clause_value) 6219276479Sdim << Values << getOpenMPClauseName(OMPC_schedule); 6220276479Sdim return nullptr; 6221276479Sdim } 6222296417Sdim // OpenMP, 2.7.1, Loop Construct, Restrictions 6223296417Sdim // The nonmonotonic modifier can only be specified with schedule(dynamic) or 6224296417Sdim // schedule(guided). 6225296417Sdim if ((M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic || 6226296417Sdim M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) && 6227296417Sdim Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) { 6228296417Sdim Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc, 6229296417Sdim diag::err_omp_schedule_nonmonotonic_static); 6230296417Sdim return nullptr; 6231296417Sdim } 6232276479Sdim Expr *ValExpr = ChunkSize; 6233288943Sdim Expr *HelperValExpr = nullptr; 6234276479Sdim if (ChunkSize) { 6235276479Sdim if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() && 6236276479Sdim !ChunkSize->isInstantiationDependent() && 6237276479Sdim !ChunkSize->containsUnexpandedParameterPack()) { 6238276479Sdim SourceLocation ChunkSizeLoc = ChunkSize->getLocStart(); 6239276479Sdim ExprResult Val = 6240276479Sdim PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize); 6241276479Sdim if (Val.isInvalid()) 6242276479Sdim return nullptr; 6243276479Sdim 6244276479Sdim ValExpr = Val.get(); 6245276479Sdim 6246276479Sdim // OpenMP [2.7.1, Restrictions] 6247276479Sdim // chunk_size must be a loop invariant integer expression with a positive 6248276479Sdim // value. 6249276479Sdim llvm::APSInt Result; 6250288943Sdim if (ValExpr->isIntegerConstantExpr(Result, Context)) { 6251288943Sdim if (Result.isSigned() && !Result.isStrictlyPositive()) { 6252288943Sdim Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause) 6253296417Sdim << "schedule" << 1 << ChunkSize->getSourceRange(); 6254288943Sdim return nullptr; 6255288943Sdim } 6256288943Sdim } else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective())) { 6257288943Sdim auto *ImpVar = buildVarDecl(*this, ChunkSize->getExprLoc(), 6258288943Sdim ChunkSize->getType(), ".chunk."); 6259288943Sdim auto *ImpVarRef = buildDeclRefExpr(*this, ImpVar, ChunkSize->getType(), 6260288943Sdim ChunkSize->getExprLoc(), 6261288943Sdim /*RefersToCapture=*/true); 6262288943Sdim HelperValExpr = ImpVarRef; 6263276479Sdim } 6264276479Sdim } 6265276479Sdim } 6266276479Sdim 6267296417Sdim return new (Context) 6268296417Sdim OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind, 6269296417Sdim ValExpr, HelperValExpr, M1, M1Loc, M2, M2Loc); 6270276479Sdim} 6271276479Sdim 6272276479SdimOMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, 6273276479Sdim SourceLocation StartLoc, 6274276479Sdim SourceLocation EndLoc) { 6275276479Sdim OMPClause *Res = nullptr; 6276276479Sdim switch (Kind) { 6277276479Sdim case OMPC_ordered: 6278276479Sdim Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc); 6279276479Sdim break; 6280276479Sdim case OMPC_nowait: 6281276479Sdim Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc); 6282276479Sdim break; 6283276479Sdim case OMPC_untied: 6284276479Sdim Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc); 6285276479Sdim break; 6286276479Sdim case OMPC_mergeable: 6287276479Sdim Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc); 6288276479Sdim break; 6289280031Sdim case OMPC_read: 6290280031Sdim Res = ActOnOpenMPReadClause(StartLoc, EndLoc); 6291280031Sdim break; 6292280031Sdim case OMPC_write: 6293280031Sdim Res = ActOnOpenMPWriteClause(StartLoc, EndLoc); 6294280031Sdim break; 6295280031Sdim case OMPC_update: 6296280031Sdim Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc); 6297280031Sdim break; 6298280031Sdim case OMPC_capture: 6299280031Sdim Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc); 6300280031Sdim break; 6301280031Sdim case OMPC_seq_cst: 6302280031Sdim Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc); 6303280031Sdim break; 6304296417Sdim case OMPC_threads: 6305296417Sdim Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc); 6306296417Sdim break; 6307296417Sdim case OMPC_simd: 6308296417Sdim Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc); 6309296417Sdim break; 6310296417Sdim case OMPC_nogroup: 6311296417Sdim Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc); 6312296417Sdim break; 6313276479Sdim case OMPC_if: 6314276479Sdim case OMPC_final: 6315276479Sdim case OMPC_num_threads: 6316276479Sdim case OMPC_safelen: 6317296417Sdim case OMPC_simdlen: 6318276479Sdim case OMPC_collapse: 6319276479Sdim case OMPC_schedule: 6320276479Sdim case OMPC_private: 6321276479Sdim case OMPC_firstprivate: 6322276479Sdim case OMPC_lastprivate: 6323276479Sdim case OMPC_shared: 6324276479Sdim case OMPC_reduction: 6325276479Sdim case OMPC_linear: 6326276479Sdim case OMPC_aligned: 6327276479Sdim case OMPC_copyin: 6328276479Sdim case OMPC_copyprivate: 6329276479Sdim case OMPC_default: 6330276479Sdim case OMPC_proc_bind: 6331276479Sdim case OMPC_threadprivate: 6332276479Sdim case OMPC_flush: 6333288943Sdim case OMPC_depend: 6334296417Sdim case OMPC_device: 6335296417Sdim case OMPC_map: 6336296417Sdim case OMPC_num_teams: 6337296417Sdim case OMPC_thread_limit: 6338296417Sdim case OMPC_priority: 6339296417Sdim case OMPC_grainsize: 6340296417Sdim case OMPC_num_tasks: 6341296417Sdim case OMPC_hint: 6342276479Sdim case OMPC_unknown: 6343276479Sdim llvm_unreachable("Clause is not allowed."); 6344276479Sdim } 6345276479Sdim return Res; 6346276479Sdim} 6347276479Sdim 6348276479SdimOMPClause *Sema::ActOnOpenMPNowaitClause(SourceLocation StartLoc, 6349276479Sdim SourceLocation EndLoc) { 6350288943Sdim DSAStack->setNowaitRegion(); 6351276479Sdim return new (Context) OMPNowaitClause(StartLoc, EndLoc); 6352276479Sdim} 6353276479Sdim 6354276479SdimOMPClause *Sema::ActOnOpenMPUntiedClause(SourceLocation StartLoc, 6355276479Sdim SourceLocation EndLoc) { 6356276479Sdim return new (Context) OMPUntiedClause(StartLoc, EndLoc); 6357276479Sdim} 6358276479Sdim 6359276479SdimOMPClause *Sema::ActOnOpenMPMergeableClause(SourceLocation StartLoc, 6360276479Sdim SourceLocation EndLoc) { 6361276479Sdim return new (Context) OMPMergeableClause(StartLoc, EndLoc); 6362276479Sdim} 6363276479Sdim 6364280031SdimOMPClause *Sema::ActOnOpenMPReadClause(SourceLocation StartLoc, 6365280031Sdim SourceLocation EndLoc) { 6366280031Sdim return new (Context) OMPReadClause(StartLoc, EndLoc); 6367280031Sdim} 6368280031Sdim 6369280031SdimOMPClause *Sema::ActOnOpenMPWriteClause(SourceLocation StartLoc, 6370280031Sdim SourceLocation EndLoc) { 6371280031Sdim return new (Context) OMPWriteClause(StartLoc, EndLoc); 6372280031Sdim} 6373280031Sdim 6374280031SdimOMPClause *Sema::ActOnOpenMPUpdateClause(SourceLocation StartLoc, 6375280031Sdim SourceLocation EndLoc) { 6376280031Sdim return new (Context) OMPUpdateClause(StartLoc, EndLoc); 6377280031Sdim} 6378280031Sdim 6379280031SdimOMPClause *Sema::ActOnOpenMPCaptureClause(SourceLocation StartLoc, 6380280031Sdim SourceLocation EndLoc) { 6381280031Sdim return new (Context) OMPCaptureClause(StartLoc, EndLoc); 6382280031Sdim} 6383280031Sdim 6384280031SdimOMPClause *Sema::ActOnOpenMPSeqCstClause(SourceLocation StartLoc, 6385280031Sdim SourceLocation EndLoc) { 6386280031Sdim return new (Context) OMPSeqCstClause(StartLoc, EndLoc); 6387280031Sdim} 6388280031Sdim 6389296417SdimOMPClause *Sema::ActOnOpenMPThreadsClause(SourceLocation StartLoc, 6390296417Sdim SourceLocation EndLoc) { 6391296417Sdim return new (Context) OMPThreadsClause(StartLoc, EndLoc); 6392296417Sdim} 6393296417Sdim 6394296417SdimOMPClause *Sema::ActOnOpenMPSIMDClause(SourceLocation StartLoc, 6395296417Sdim SourceLocation EndLoc) { 6396296417Sdim return new (Context) OMPSIMDClause(StartLoc, EndLoc); 6397296417Sdim} 6398296417Sdim 6399296417SdimOMPClause *Sema::ActOnOpenMPNogroupClause(SourceLocation StartLoc, 6400296417Sdim SourceLocation EndLoc) { 6401296417Sdim return new (Context) OMPNogroupClause(StartLoc, EndLoc); 6402296417Sdim} 6403296417Sdim 6404276479SdimOMPClause *Sema::ActOnOpenMPVarListClause( 6405276479Sdim OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *TailExpr, 6406276479Sdim SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, 6407276479Sdim SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, 6408288943Sdim const DeclarationNameInfo &ReductionId, OpenMPDependClauseKind DepKind, 6409296417Sdim OpenMPLinearClauseKind LinKind, OpenMPMapClauseKind MapTypeModifier, 6410296417Sdim OpenMPMapClauseKind MapType, SourceLocation DepLinMapLoc) { 6411276479Sdim OMPClause *Res = nullptr; 6412261991Sdim switch (Kind) { 6413261991Sdim case OMPC_private: 6414261991Sdim Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc); 6415261991Sdim break; 6416261991Sdim case OMPC_firstprivate: 6417261991Sdim Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc); 6418261991Sdim break; 6419276479Sdim case OMPC_lastprivate: 6420276479Sdim Res = ActOnOpenMPLastprivateClause(VarList, StartLoc, LParenLoc, EndLoc); 6421276479Sdim break; 6422261991Sdim case OMPC_shared: 6423261991Sdim Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc); 6424261991Sdim break; 6425276479Sdim case OMPC_reduction: 6426276479Sdim Res = ActOnOpenMPReductionClause(VarList, StartLoc, LParenLoc, ColonLoc, 6427276479Sdim EndLoc, ReductionIdScopeSpec, ReductionId); 6428276479Sdim break; 6429276479Sdim case OMPC_linear: 6430276479Sdim Res = ActOnOpenMPLinearClause(VarList, TailExpr, StartLoc, LParenLoc, 6431296417Sdim LinKind, DepLinMapLoc, ColonLoc, EndLoc); 6432276479Sdim break; 6433276479Sdim case OMPC_aligned: 6434276479Sdim Res = ActOnOpenMPAlignedClause(VarList, TailExpr, StartLoc, LParenLoc, 6435276479Sdim ColonLoc, EndLoc); 6436276479Sdim break; 6437276479Sdim case OMPC_copyin: 6438276479Sdim Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc); 6439276479Sdim break; 6440276479Sdim case OMPC_copyprivate: 6441276479Sdim Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc); 6442276479Sdim break; 6443276479Sdim case OMPC_flush: 6444276479Sdim Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc); 6445276479Sdim break; 6446288943Sdim case OMPC_depend: 6447296417Sdim Res = ActOnOpenMPDependClause(DepKind, DepLinMapLoc, ColonLoc, VarList, 6448296417Sdim StartLoc, LParenLoc, EndLoc); 6449288943Sdim break; 6450296417Sdim case OMPC_map: 6451296417Sdim Res = ActOnOpenMPMapClause(MapTypeModifier, MapType, DepLinMapLoc, ColonLoc, 6452296417Sdim VarList, StartLoc, LParenLoc, EndLoc); 6453296417Sdim break; 6454276479Sdim case OMPC_if: 6455276479Sdim case OMPC_final: 6456276479Sdim case OMPC_num_threads: 6457276479Sdim case OMPC_safelen: 6458296417Sdim case OMPC_simdlen: 6459276479Sdim case OMPC_collapse: 6460261991Sdim case OMPC_default: 6461276479Sdim case OMPC_proc_bind: 6462276479Sdim case OMPC_schedule: 6463276479Sdim case OMPC_ordered: 6464276479Sdim case OMPC_nowait: 6465276479Sdim case OMPC_untied: 6466276479Sdim case OMPC_mergeable: 6467261991Sdim case OMPC_threadprivate: 6468280031Sdim case OMPC_read: 6469280031Sdim case OMPC_write: 6470280031Sdim case OMPC_update: 6471280031Sdim case OMPC_capture: 6472280031Sdim case OMPC_seq_cst: 6473296417Sdim case OMPC_device: 6474296417Sdim case OMPC_threads: 6475296417Sdim case OMPC_simd: 6476296417Sdim case OMPC_num_teams: 6477296417Sdim case OMPC_thread_limit: 6478296417Sdim case OMPC_priority: 6479296417Sdim case OMPC_grainsize: 6480296417Sdim case OMPC_nogroup: 6481296417Sdim case OMPC_num_tasks: 6482296417Sdim case OMPC_hint: 6483261991Sdim case OMPC_unknown: 6484261991Sdim llvm_unreachable("Clause is not allowed."); 6485261991Sdim } 6486261991Sdim return Res; 6487261991Sdim} 6488261991Sdim 6489261991SdimOMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList, 6490261991Sdim SourceLocation StartLoc, 6491261991Sdim SourceLocation LParenLoc, 6492261991Sdim SourceLocation EndLoc) { 6493261991Sdim SmallVector<Expr *, 8> Vars; 6494280031Sdim SmallVector<Expr *, 8> PrivateCopies; 6495276479Sdim for (auto &RefExpr : VarList) { 6496276479Sdim assert(RefExpr && "NULL expr in OpenMP private clause."); 6497276479Sdim if (isa<DependentScopeDeclRefExpr>(RefExpr)) { 6498261991Sdim // It will be analyzed later. 6499276479Sdim Vars.push_back(RefExpr); 6500280031Sdim PrivateCopies.push_back(nullptr); 6501261991Sdim continue; 6502261991Sdim } 6503261991Sdim 6504276479Sdim SourceLocation ELoc = RefExpr->getExprLoc(); 6505261991Sdim // OpenMP [2.1, C/C++] 6506261991Sdim // A list item is a variable name. 6507261991Sdim // OpenMP [2.9.3.3, Restrictions, p.1] 6508261991Sdim // A variable that is part of another variable (as an array or 6509261991Sdim // structure element) cannot appear in a private clause. 6510276479Sdim DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr); 6511261991Sdim if (!DE || !isa<VarDecl>(DE->getDecl())) { 6512276479Sdim Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange(); 6513261991Sdim continue; 6514261991Sdim } 6515261991Sdim Decl *D = DE->getDecl(); 6516261991Sdim VarDecl *VD = cast<VarDecl>(D); 6517261991Sdim 6518261991Sdim QualType Type = VD->getType(); 6519261991Sdim if (Type->isDependentType() || Type->isInstantiationDependentType()) { 6520261991Sdim // It will be analyzed later. 6521261991Sdim Vars.push_back(DE); 6522280031Sdim PrivateCopies.push_back(nullptr); 6523261991Sdim continue; 6524261991Sdim } 6525261991Sdim 6526261991Sdim // OpenMP [2.9.3.3, Restrictions, C/C++, p.3] 6527261991Sdim // A variable that appears in a private clause must not have an incomplete 6528261991Sdim // type or a reference type. 6529261991Sdim if (RequireCompleteType(ELoc, Type, 6530261991Sdim diag::err_omp_private_incomplete_type)) { 6531261991Sdim continue; 6532261991Sdim } 6533296417Sdim Type = Type.getNonReferenceType(); 6534261991Sdim 6535261991Sdim // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 6536261991Sdim // in a Construct] 6537261991Sdim // Variables with the predetermined data-sharing attributes may not be 6538261991Sdim // listed in data-sharing attributes clauses, except for the cases 6539261991Sdim // listed below. For these exceptions only, listing a predetermined 6540261991Sdim // variable in a data-sharing attribute clause is allowed and overrides 6541261991Sdim // the variable's predetermined data-sharing attributes. 6542276479Sdim DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false); 6543261991Sdim if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) { 6544276479Sdim Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind) 6545276479Sdim << getOpenMPClauseName(OMPC_private); 6546276479Sdim ReportOriginalDSA(*this, DSAStack, VD, DVar); 6547261991Sdim continue; 6548261991Sdim } 6549261991Sdim 6550288943Sdim // Variably modified types are not supported for tasks. 6551288943Sdim if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() && 6552288943Sdim DSAStack->getCurrentDirective() == OMPD_task) { 6553288943Sdim Diag(ELoc, diag::err_omp_variably_modified_type_not_supported) 6554288943Sdim << getOpenMPClauseName(OMPC_private) << Type 6555288943Sdim << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); 6556288943Sdim bool IsDecl = 6557288943Sdim VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 6558288943Sdim Diag(VD->getLocation(), 6559288943Sdim IsDecl ? diag::note_previous_decl : diag::note_defined_here) 6560288943Sdim << VD; 6561288943Sdim continue; 6562288943Sdim } 6563288943Sdim 6564288943Sdim // OpenMP [2.9.3.3, Restrictions, C/C++, p.1] 6565288943Sdim // A variable of class type (or array thereof) that appears in a private 6566288943Sdim // clause requires an accessible, unambiguous default constructor for the 6567288943Sdim // class type. 6568280031Sdim // Generate helper private variable and initialize it with the default 6569280031Sdim // value. The address of the original variable is replaced by the address of 6570280031Sdim // the new private variable in CodeGen. This new variable is not added to 6571280031Sdim // IdResolver, so the code in the OpenMP region uses original variable for 6572280031Sdim // proper diagnostics. 6573288943Sdim Type = Type.getUnqualifiedType(); 6574296417Sdim auto VDPrivate = buildVarDecl(*this, DE->getExprLoc(), Type, VD->getName(), 6575296417Sdim VD->hasAttrs() ? &VD->getAttrs() : nullptr); 6576288943Sdim ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false); 6577280031Sdim if (VDPrivate->isInvalidDecl()) 6578280031Sdim continue; 6579288943Sdim auto VDPrivateRefExpr = buildDeclRefExpr( 6580288943Sdim *this, VDPrivate, DE->getType().getUnqualifiedType(), DE->getExprLoc()); 6581280031Sdim 6582261991Sdim DSAStack->addDSA(VD, DE, OMPC_private); 6583261991Sdim Vars.push_back(DE); 6584280031Sdim PrivateCopies.push_back(VDPrivateRefExpr); 6585261991Sdim } 6586261991Sdim 6587276479Sdim if (Vars.empty()) 6588276479Sdim return nullptr; 6589261991Sdim 6590280031Sdim return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars, 6591280031Sdim PrivateCopies); 6592261991Sdim} 6593261991Sdim 6594280031Sdimnamespace { 6595280031Sdimclass DiagsUninitializedSeveretyRAII { 6596280031Sdimprivate: 6597280031Sdim DiagnosticsEngine &Diags; 6598280031Sdim SourceLocation SavedLoc; 6599280031Sdim bool IsIgnored; 6600280031Sdim 6601280031Sdimpublic: 6602280031Sdim DiagsUninitializedSeveretyRAII(DiagnosticsEngine &Diags, SourceLocation Loc, 6603280031Sdim bool IsIgnored) 6604280031Sdim : Diags(Diags), SavedLoc(Loc), IsIgnored(IsIgnored) { 6605280031Sdim if (!IsIgnored) { 6606280031Sdim Diags.setSeverity(/*Diag*/ diag::warn_uninit_self_reference_in_init, 6607280031Sdim /*Map*/ diag::Severity::Ignored, Loc); 6608280031Sdim } 6609280031Sdim } 6610280031Sdim ~DiagsUninitializedSeveretyRAII() { 6611280031Sdim if (!IsIgnored) 6612280031Sdim Diags.popMappings(SavedLoc); 6613280031Sdim } 6614280031Sdim}; 6615280031Sdim} 6616280031Sdim 6617261991SdimOMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, 6618261991Sdim SourceLocation StartLoc, 6619261991Sdim SourceLocation LParenLoc, 6620261991Sdim SourceLocation EndLoc) { 6621261991Sdim SmallVector<Expr *, 8> Vars; 6622280031Sdim SmallVector<Expr *, 8> PrivateCopies; 6623280031Sdim SmallVector<Expr *, 8> Inits; 6624276479Sdim bool IsImplicitClause = 6625276479Sdim StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid(); 6626276479Sdim auto ImplicitClauseLoc = DSAStack->getConstructLoc(); 6627276479Sdim 6628276479Sdim for (auto &RefExpr : VarList) { 6629276479Sdim assert(RefExpr && "NULL expr in OpenMP firstprivate clause."); 6630276479Sdim if (isa<DependentScopeDeclRefExpr>(RefExpr)) { 6631261991Sdim // It will be analyzed later. 6632276479Sdim Vars.push_back(RefExpr); 6633280031Sdim PrivateCopies.push_back(nullptr); 6634280031Sdim Inits.push_back(nullptr); 6635261991Sdim continue; 6636261991Sdim } 6637261991Sdim 6638280031Sdim SourceLocation ELoc = 6639280031Sdim IsImplicitClause ? ImplicitClauseLoc : RefExpr->getExprLoc(); 6640261991Sdim // OpenMP [2.1, C/C++] 6641261991Sdim // A list item is a variable name. 6642261991Sdim // OpenMP [2.9.3.3, Restrictions, p.1] 6643261991Sdim // A variable that is part of another variable (as an array or 6644261991Sdim // structure element) cannot appear in a private clause. 6645276479Sdim DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr); 6646261991Sdim if (!DE || !isa<VarDecl>(DE->getDecl())) { 6647276479Sdim Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange(); 6648261991Sdim continue; 6649261991Sdim } 6650261991Sdim Decl *D = DE->getDecl(); 6651261991Sdim VarDecl *VD = cast<VarDecl>(D); 6652261991Sdim 6653261991Sdim QualType Type = VD->getType(); 6654261991Sdim if (Type->isDependentType() || Type->isInstantiationDependentType()) { 6655261991Sdim // It will be analyzed later. 6656261991Sdim Vars.push_back(DE); 6657280031Sdim PrivateCopies.push_back(nullptr); 6658280031Sdim Inits.push_back(nullptr); 6659261991Sdim continue; 6660261991Sdim } 6661261991Sdim 6662261991Sdim // OpenMP [2.9.3.3, Restrictions, C/C++, p.3] 6663261991Sdim // A variable that appears in a private clause must not have an incomplete 6664261991Sdim // type or a reference type. 6665261991Sdim if (RequireCompleteType(ELoc, Type, 6666261991Sdim diag::err_omp_firstprivate_incomplete_type)) { 6667261991Sdim continue; 6668261991Sdim } 6669296417Sdim Type = Type.getNonReferenceType(); 6670261991Sdim 6671261991Sdim // OpenMP [2.9.3.4, Restrictions, C/C++, p.1] 6672261991Sdim // A variable of class type (or array thereof) that appears in a private 6673276479Sdim // clause requires an accessible, unambiguous copy constructor for the 6674261991Sdim // class type. 6675288943Sdim auto ElemType = Context.getBaseElementType(Type).getNonReferenceType(); 6676261991Sdim 6677276479Sdim // If an implicit firstprivate variable found it was checked already. 6678276479Sdim if (!IsImplicitClause) { 6679276479Sdim DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false); 6680288943Sdim bool IsConstant = ElemType.isConstant(Context); 6681261991Sdim // OpenMP [2.4.13, Data-sharing Attribute Clauses] 6682261991Sdim // A list item that specifies a given variable may not appear in more 6683261991Sdim // than one clause on the same directive, except that a variable may be 6684261991Sdim // specified in both firstprivate and lastprivate clauses. 6685261991Sdim if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate && 6686276479Sdim DVar.CKind != OMPC_lastprivate && DVar.RefExpr) { 6687261991Sdim Diag(ELoc, diag::err_omp_wrong_dsa) 6688276479Sdim << getOpenMPClauseName(DVar.CKind) 6689276479Sdim << getOpenMPClauseName(OMPC_firstprivate); 6690276479Sdim ReportOriginalDSA(*this, DSAStack, VD, DVar); 6691261991Sdim continue; 6692261991Sdim } 6693261991Sdim 6694261991Sdim // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 6695261991Sdim // in a Construct] 6696261991Sdim // Variables with the predetermined data-sharing attributes may not be 6697261991Sdim // listed in data-sharing attributes clauses, except for the cases 6698261991Sdim // listed below. For these exceptions only, listing a predetermined 6699261991Sdim // variable in a data-sharing attribute clause is allowed and overrides 6700261991Sdim // the variable's predetermined data-sharing attributes. 6701261991Sdim // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 6702261991Sdim // in a Construct, C/C++, p.2] 6703261991Sdim // Variables with const-qualified type having no mutable member may be 6704261991Sdim // listed in a firstprivate clause, even if they are static data members. 6705261991Sdim if (!(IsConstant || VD->isStaticDataMember()) && !DVar.RefExpr && 6706261991Sdim DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) { 6707261991Sdim Diag(ELoc, diag::err_omp_wrong_dsa) 6708276479Sdim << getOpenMPClauseName(DVar.CKind) 6709276479Sdim << getOpenMPClauseName(OMPC_firstprivate); 6710276479Sdim ReportOriginalDSA(*this, DSAStack, VD, DVar); 6711261991Sdim continue; 6712261991Sdim } 6713261991Sdim 6714276479Sdim OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective(); 6715261991Sdim // OpenMP [2.9.3.4, Restrictions, p.2] 6716261991Sdim // A list item that is private within a parallel region must not appear 6717261991Sdim // in a firstprivate clause on a worksharing construct if any of the 6718261991Sdim // worksharing regions arising from the worksharing construct ever bind 6719261991Sdim // to any of the parallel regions arising from the parallel construct. 6720276479Sdim if (isOpenMPWorksharingDirective(CurrDir) && 6721276479Sdim !isOpenMPParallelDirective(CurrDir)) { 6722276479Sdim DVar = DSAStack->getImplicitDSA(VD, true); 6723276479Sdim if (DVar.CKind != OMPC_shared && 6724276479Sdim (isOpenMPParallelDirective(DVar.DKind) || 6725276479Sdim DVar.DKind == OMPD_unknown)) { 6726276479Sdim Diag(ELoc, diag::err_omp_required_access) 6727276479Sdim << getOpenMPClauseName(OMPC_firstprivate) 6728276479Sdim << getOpenMPClauseName(OMPC_shared); 6729276479Sdim ReportOriginalDSA(*this, DSAStack, VD, DVar); 6730276479Sdim continue; 6731276479Sdim } 6732276479Sdim } 6733261991Sdim // OpenMP [2.9.3.4, Restrictions, p.3] 6734261991Sdim // A list item that appears in a reduction clause of a parallel construct 6735261991Sdim // must not appear in a firstprivate clause on a worksharing or task 6736261991Sdim // construct if any of the worksharing or task regions arising from the 6737261991Sdim // worksharing or task construct ever bind to any of the parallel regions 6738261991Sdim // arising from the parallel construct. 6739261991Sdim // OpenMP [2.9.3.4, Restrictions, p.4] 6740261991Sdim // A list item that appears in a reduction clause in worksharing 6741261991Sdim // construct must not appear in a firstprivate clause in a task construct 6742261991Sdim // encountered during execution of any of the worksharing regions arising 6743261991Sdim // from the worksharing construct. 6744276479Sdim if (CurrDir == OMPD_task) { 6745276479Sdim DVar = 6746276479Sdim DSAStack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_reduction), 6747276479Sdim [](OpenMPDirectiveKind K) -> bool { 6748276479Sdim return isOpenMPParallelDirective(K) || 6749276479Sdim isOpenMPWorksharingDirective(K); 6750276479Sdim }, 6751276479Sdim false); 6752276479Sdim if (DVar.CKind == OMPC_reduction && 6753276479Sdim (isOpenMPParallelDirective(DVar.DKind) || 6754276479Sdim isOpenMPWorksharingDirective(DVar.DKind))) { 6755276479Sdim Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate) 6756276479Sdim << getOpenMPDirectiveName(DVar.DKind); 6757276479Sdim ReportOriginalDSA(*this, DSAStack, VD, DVar); 6758276479Sdim continue; 6759276479Sdim } 6760276479Sdim } 6761296417Sdim 6762296417Sdim // OpenMP 4.5 [2.15.3.4, Restrictions, p.3] 6763296417Sdim // A list item that is private within a teams region must not appear in a 6764296417Sdim // firstprivate clause on a distribute construct if any of the distribute 6765296417Sdim // regions arising from the distribute construct ever bind to any of the 6766296417Sdim // teams regions arising from the teams construct. 6767296417Sdim // OpenMP 4.5 [2.15.3.4, Restrictions, p.3] 6768296417Sdim // A list item that appears in a reduction clause of a teams construct 6769296417Sdim // must not appear in a firstprivate clause on a distribute construct if 6770296417Sdim // any of the distribute regions arising from the distribute construct 6771296417Sdim // ever bind to any of the teams regions arising from the teams construct. 6772296417Sdim // OpenMP 4.5 [2.10.8, Distribute Construct, p.3] 6773296417Sdim // A list item may appear in a firstprivate or lastprivate clause but not 6774296417Sdim // both. 6775296417Sdim if (CurrDir == OMPD_distribute) { 6776296417Sdim DVar = DSAStack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_private), 6777296417Sdim [](OpenMPDirectiveKind K) -> bool { 6778296417Sdim return isOpenMPTeamsDirective(K); 6779296417Sdim }, 6780296417Sdim false); 6781296417Sdim if (DVar.CKind == OMPC_private && isOpenMPTeamsDirective(DVar.DKind)) { 6782296417Sdim Diag(ELoc, diag::err_omp_firstprivate_distribute_private_teams); 6783296417Sdim ReportOriginalDSA(*this, DSAStack, VD, DVar); 6784296417Sdim continue; 6785296417Sdim } 6786296417Sdim DVar = DSAStack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_reduction), 6787296417Sdim [](OpenMPDirectiveKind K) -> bool { 6788296417Sdim return isOpenMPTeamsDirective(K); 6789296417Sdim }, 6790296417Sdim false); 6791296417Sdim if (DVar.CKind == OMPC_reduction && 6792296417Sdim isOpenMPTeamsDirective(DVar.DKind)) { 6793296417Sdim Diag(ELoc, diag::err_omp_firstprivate_distribute_in_teams_reduction); 6794296417Sdim ReportOriginalDSA(*this, DSAStack, VD, DVar); 6795296417Sdim continue; 6796296417Sdim } 6797296417Sdim DVar = DSAStack->getTopDSA(VD, false); 6798296417Sdim if (DVar.CKind == OMPC_lastprivate) { 6799296417Sdim Diag(ELoc, diag::err_omp_firstprivate_and_lastprivate_in_distribute); 6800296417Sdim ReportOriginalDSA(*this, DSAStack, VD, DVar); 6801296417Sdim continue; 6802296417Sdim } 6803296417Sdim } 6804261991Sdim } 6805261991Sdim 6806288943Sdim // Variably modified types are not supported for tasks. 6807288943Sdim if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() && 6808288943Sdim DSAStack->getCurrentDirective() == OMPD_task) { 6809288943Sdim Diag(ELoc, diag::err_omp_variably_modified_type_not_supported) 6810288943Sdim << getOpenMPClauseName(OMPC_firstprivate) << Type 6811288943Sdim << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); 6812288943Sdim bool IsDecl = 6813288943Sdim VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 6814288943Sdim Diag(VD->getLocation(), 6815288943Sdim IsDecl ? diag::note_previous_decl : diag::note_defined_here) 6816288943Sdim << VD; 6817288943Sdim continue; 6818288943Sdim } 6819288943Sdim 6820280031Sdim Type = Type.getUnqualifiedType(); 6821296417Sdim auto VDPrivate = buildVarDecl(*this, ELoc, Type, VD->getName(), 6822296417Sdim VD->hasAttrs() ? &VD->getAttrs() : nullptr); 6823280031Sdim // Generate helper private variable and initialize it with the value of the 6824280031Sdim // original variable. The address of the original variable is replaced by 6825280031Sdim // the address of the new private variable in the CodeGen. This new variable 6826280031Sdim // is not added to IdResolver, so the code in the OpenMP region uses 6827280031Sdim // original variable for proper diagnostics and variable capturing. 6828280031Sdim Expr *VDInitRefExpr = nullptr; 6829280031Sdim // For arrays generate initializer for single element and replace it by the 6830280031Sdim // original array element in CodeGen. 6831288943Sdim if (Type->isArrayType()) { 6832288943Sdim auto VDInit = 6833288943Sdim buildVarDecl(*this, DE->getExprLoc(), ElemType, VD->getName()); 6834288943Sdim VDInitRefExpr = buildDeclRefExpr(*this, VDInit, ElemType, ELoc); 6835280031Sdim auto Init = DefaultLvalueConversion(VDInitRefExpr).get(); 6836288943Sdim ElemType = ElemType.getUnqualifiedType(); 6837288943Sdim auto *VDInitTemp = buildVarDecl(*this, DE->getLocStart(), ElemType, 6838288943Sdim ".firstprivate.temp"); 6839288943Sdim InitializedEntity Entity = 6840288943Sdim InitializedEntity::InitializeVariable(VDInitTemp); 6841280031Sdim InitializationKind Kind = InitializationKind::CreateCopy(ELoc, ELoc); 6842280031Sdim 6843280031Sdim InitializationSequence InitSeq(*this, Entity, Kind, Init); 6844280031Sdim ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Init); 6845280031Sdim if (Result.isInvalid()) 6846280031Sdim VDPrivate->setInvalidDecl(); 6847280031Sdim else 6848280031Sdim VDPrivate->setInit(Result.getAs<Expr>()); 6849296417Sdim // Remove temp variable declaration. 6850296417Sdim Context.Deallocate(VDInitTemp); 6851280031Sdim } else { 6852288943Sdim auto *VDInit = 6853288943Sdim buildVarDecl(*this, DE->getLocStart(), Type, ".firstprivate.temp"); 6854288943Sdim VDInitRefExpr = 6855288943Sdim buildDeclRefExpr(*this, VDInit, DE->getType(), DE->getExprLoc()); 6856288943Sdim AddInitializerToDecl(VDPrivate, 6857288943Sdim DefaultLvalueConversion(VDInitRefExpr).get(), 6858288943Sdim /*DirectInit=*/false, /*TypeMayContainAuto=*/false); 6859280031Sdim } 6860280031Sdim if (VDPrivate->isInvalidDecl()) { 6861280031Sdim if (IsImplicitClause) { 6862280031Sdim Diag(DE->getExprLoc(), 6863280031Sdim diag::note_omp_task_predetermined_firstprivate_here); 6864280031Sdim } 6865280031Sdim continue; 6866280031Sdim } 6867280031Sdim CurContext->addDecl(VDPrivate); 6868288943Sdim auto VDPrivateRefExpr = buildDeclRefExpr( 6869288943Sdim *this, VDPrivate, DE->getType().getUnqualifiedType(), DE->getExprLoc()); 6870261991Sdim DSAStack->addDSA(VD, DE, OMPC_firstprivate); 6871261991Sdim Vars.push_back(DE); 6872280031Sdim PrivateCopies.push_back(VDPrivateRefExpr); 6873280031Sdim Inits.push_back(VDInitRefExpr); 6874261991Sdim } 6875261991Sdim 6876276479Sdim if (Vars.empty()) 6877276479Sdim return nullptr; 6878261991Sdim 6879261991Sdim return OMPFirstprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, 6880280031Sdim Vars, PrivateCopies, Inits); 6881261991Sdim} 6882261991Sdim 6883276479SdimOMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, 6884276479Sdim SourceLocation StartLoc, 6885276479Sdim SourceLocation LParenLoc, 6886276479Sdim SourceLocation EndLoc) { 6887276479Sdim SmallVector<Expr *, 8> Vars; 6888288943Sdim SmallVector<Expr *, 8> SrcExprs; 6889288943Sdim SmallVector<Expr *, 8> DstExprs; 6890288943Sdim SmallVector<Expr *, 8> AssignmentOps; 6891276479Sdim for (auto &RefExpr : VarList) { 6892276479Sdim assert(RefExpr && "NULL expr in OpenMP lastprivate clause."); 6893276479Sdim if (isa<DependentScopeDeclRefExpr>(RefExpr)) { 6894276479Sdim // It will be analyzed later. 6895276479Sdim Vars.push_back(RefExpr); 6896288943Sdim SrcExprs.push_back(nullptr); 6897288943Sdim DstExprs.push_back(nullptr); 6898288943Sdim AssignmentOps.push_back(nullptr); 6899276479Sdim continue; 6900276479Sdim } 6901276479Sdim 6902276479Sdim SourceLocation ELoc = RefExpr->getExprLoc(); 6903276479Sdim // OpenMP [2.1, C/C++] 6904276479Sdim // A list item is a variable name. 6905276479Sdim // OpenMP [2.14.3.5, Restrictions, p.1] 6906276479Sdim // A variable that is part of another variable (as an array or structure 6907276479Sdim // element) cannot appear in a lastprivate clause. 6908276479Sdim DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr); 6909276479Sdim if (!DE || !isa<VarDecl>(DE->getDecl())) { 6910276479Sdim Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange(); 6911276479Sdim continue; 6912276479Sdim } 6913276479Sdim Decl *D = DE->getDecl(); 6914276479Sdim VarDecl *VD = cast<VarDecl>(D); 6915276479Sdim 6916276479Sdim QualType Type = VD->getType(); 6917276479Sdim if (Type->isDependentType() || Type->isInstantiationDependentType()) { 6918276479Sdim // It will be analyzed later. 6919276479Sdim Vars.push_back(DE); 6920288943Sdim SrcExprs.push_back(nullptr); 6921288943Sdim DstExprs.push_back(nullptr); 6922288943Sdim AssignmentOps.push_back(nullptr); 6923276479Sdim continue; 6924276479Sdim } 6925276479Sdim 6926276479Sdim // OpenMP [2.14.3.5, Restrictions, C/C++, p.2] 6927276479Sdim // A variable that appears in a lastprivate clause must not have an 6928276479Sdim // incomplete type or a reference type. 6929276479Sdim if (RequireCompleteType(ELoc, Type, 6930276479Sdim diag::err_omp_lastprivate_incomplete_type)) { 6931276479Sdim continue; 6932276479Sdim } 6933296417Sdim Type = Type.getNonReferenceType(); 6934276479Sdim 6935276479Sdim // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced 6936276479Sdim // in a Construct] 6937276479Sdim // Variables with the predetermined data-sharing attributes may not be 6938276479Sdim // listed in data-sharing attributes clauses, except for the cases 6939276479Sdim // listed below. 6940276479Sdim DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false); 6941276479Sdim if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate && 6942276479Sdim DVar.CKind != OMPC_firstprivate && 6943276479Sdim (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) { 6944276479Sdim Diag(ELoc, diag::err_omp_wrong_dsa) 6945276479Sdim << getOpenMPClauseName(DVar.CKind) 6946276479Sdim << getOpenMPClauseName(OMPC_lastprivate); 6947276479Sdim ReportOriginalDSA(*this, DSAStack, VD, DVar); 6948276479Sdim continue; 6949276479Sdim } 6950276479Sdim 6951276479Sdim OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective(); 6952276479Sdim // OpenMP [2.14.3.5, Restrictions, p.2] 6953276479Sdim // A list item that is private within a parallel region, or that appears in 6954276479Sdim // the reduction clause of a parallel construct, must not appear in a 6955276479Sdim // lastprivate clause on a worksharing construct if any of the corresponding 6956276479Sdim // worksharing regions ever binds to any of the corresponding parallel 6957276479Sdim // regions. 6958288943Sdim DSAStackTy::DSAVarData TopDVar = DVar; 6959276479Sdim if (isOpenMPWorksharingDirective(CurrDir) && 6960276479Sdim !isOpenMPParallelDirective(CurrDir)) { 6961276479Sdim DVar = DSAStack->getImplicitDSA(VD, true); 6962276479Sdim if (DVar.CKind != OMPC_shared) { 6963276479Sdim Diag(ELoc, diag::err_omp_required_access) 6964276479Sdim << getOpenMPClauseName(OMPC_lastprivate) 6965276479Sdim << getOpenMPClauseName(OMPC_shared); 6966276479Sdim ReportOriginalDSA(*this, DSAStack, VD, DVar); 6967276479Sdim continue; 6968276479Sdim } 6969276479Sdim } 6970276479Sdim // OpenMP [2.14.3.5, Restrictions, C++, p.1,2] 6971276479Sdim // A variable of class type (or array thereof) that appears in a 6972276479Sdim // lastprivate clause requires an accessible, unambiguous default 6973276479Sdim // constructor for the class type, unless the list item is also specified 6974276479Sdim // in a firstprivate clause. 6975276479Sdim // A variable of class type (or array thereof) that appears in a 6976276479Sdim // lastprivate clause requires an accessible, unambiguous copy assignment 6977276479Sdim // operator for the class type. 6978288943Sdim Type = Context.getBaseElementType(Type).getNonReferenceType(); 6979288943Sdim auto *SrcVD = buildVarDecl(*this, DE->getLocStart(), 6980296417Sdim Type.getUnqualifiedType(), ".lastprivate.src", 6981296417Sdim VD->hasAttrs() ? &VD->getAttrs() : nullptr); 6982288943Sdim auto *PseudoSrcExpr = buildDeclRefExpr( 6983288943Sdim *this, SrcVD, Type.getUnqualifiedType(), DE->getExprLoc()); 6984288943Sdim auto *DstVD = 6985296417Sdim buildVarDecl(*this, DE->getLocStart(), Type, ".lastprivate.dst", 6986296417Sdim VD->hasAttrs() ? &VD->getAttrs() : nullptr); 6987288943Sdim auto *PseudoDstExpr = 6988288943Sdim buildDeclRefExpr(*this, DstVD, Type, DE->getExprLoc()); 6989288943Sdim // For arrays generate assignment operation for single element and replace 6990288943Sdim // it by the original array element in CodeGen. 6991288943Sdim auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, 6992288943Sdim PseudoDstExpr, PseudoSrcExpr); 6993288943Sdim if (AssignmentOp.isInvalid()) 6994288943Sdim continue; 6995288943Sdim AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(), 6996288943Sdim /*DiscardedValue=*/true); 6997288943Sdim if (AssignmentOp.isInvalid()) 6998288943Sdim continue; 6999276479Sdim 7000296417Sdim // OpenMP 4.5 [2.10.8, Distribute Construct, p.3] 7001296417Sdim // A list item may appear in a firstprivate or lastprivate clause but not 7002296417Sdim // both. 7003296417Sdim if (CurrDir == OMPD_distribute) { 7004296417Sdim DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false); 7005296417Sdim if (DVar.CKind == OMPC_firstprivate) { 7006296417Sdim Diag(ELoc, diag::err_omp_firstprivate_and_lastprivate_in_distribute); 7007296417Sdim ReportOriginalDSA(*this, DSAStack, VD, DVar); 7008296417Sdim continue; 7009296417Sdim } 7010296417Sdim } 7011296417Sdim 7012288943Sdim if (TopDVar.CKind != OMPC_firstprivate) 7013276479Sdim DSAStack->addDSA(VD, DE, OMPC_lastprivate); 7014276479Sdim Vars.push_back(DE); 7015288943Sdim SrcExprs.push_back(PseudoSrcExpr); 7016288943Sdim DstExprs.push_back(PseudoDstExpr); 7017288943Sdim AssignmentOps.push_back(AssignmentOp.get()); 7018276479Sdim } 7019276479Sdim 7020276479Sdim if (Vars.empty()) 7021276479Sdim return nullptr; 7022276479Sdim 7023276479Sdim return OMPLastprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, 7024288943Sdim Vars, SrcExprs, DstExprs, AssignmentOps); 7025276479Sdim} 7026276479Sdim 7027261991SdimOMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList, 7028261991Sdim SourceLocation StartLoc, 7029261991Sdim SourceLocation LParenLoc, 7030261991Sdim SourceLocation EndLoc) { 7031261991Sdim SmallVector<Expr *, 8> Vars; 7032276479Sdim for (auto &RefExpr : VarList) { 7033276479Sdim assert(RefExpr && "NULL expr in OpenMP shared clause."); 7034276479Sdim if (isa<DependentScopeDeclRefExpr>(RefExpr)) { 7035261991Sdim // It will be analyzed later. 7036276479Sdim Vars.push_back(RefExpr); 7037261991Sdim continue; 7038261991Sdim } 7039261991Sdim 7040276479Sdim SourceLocation ELoc = RefExpr->getExprLoc(); 7041261991Sdim // OpenMP [2.1, C/C++] 7042261991Sdim // A list item is a variable name. 7043276479Sdim // OpenMP [2.14.3.2, Restrictions, p.1] 7044276479Sdim // A variable that is part of another variable (as an array or structure 7045276479Sdim // element) cannot appear in a shared unless it is a static data member 7046276479Sdim // of a C++ class. 7047276479Sdim DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr); 7048261991Sdim if (!DE || !isa<VarDecl>(DE->getDecl())) { 7049276479Sdim Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange(); 7050261991Sdim continue; 7051261991Sdim } 7052261991Sdim Decl *D = DE->getDecl(); 7053261991Sdim VarDecl *VD = cast<VarDecl>(D); 7054261991Sdim 7055261991Sdim QualType Type = VD->getType(); 7056261991Sdim if (Type->isDependentType() || Type->isInstantiationDependentType()) { 7057261991Sdim // It will be analyzed later. 7058261991Sdim Vars.push_back(DE); 7059261991Sdim continue; 7060261991Sdim } 7061261991Sdim 7062261991Sdim // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced 7063261991Sdim // in a Construct] 7064261991Sdim // Variables with the predetermined data-sharing attributes may not be 7065261991Sdim // listed in data-sharing attributes clauses, except for the cases 7066261991Sdim // listed below. For these exceptions only, listing a predetermined 7067261991Sdim // variable in a data-sharing attribute clause is allowed and overrides 7068261991Sdim // the variable's predetermined data-sharing attributes. 7069276479Sdim DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false); 7070276479Sdim if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared && 7071276479Sdim DVar.RefExpr) { 7072276479Sdim Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind) 7073276479Sdim << getOpenMPClauseName(OMPC_shared); 7074276479Sdim ReportOriginalDSA(*this, DSAStack, VD, DVar); 7075261991Sdim continue; 7076261991Sdim } 7077261991Sdim 7078261991Sdim DSAStack->addDSA(VD, DE, OMPC_shared); 7079261991Sdim Vars.push_back(DE); 7080261991Sdim } 7081261991Sdim 7082276479Sdim if (Vars.empty()) 7083276479Sdim return nullptr; 7084261991Sdim 7085261991Sdim return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars); 7086261991Sdim} 7087261991Sdim 7088276479Sdimnamespace { 7089276479Sdimclass DSARefChecker : public StmtVisitor<DSARefChecker, bool> { 7090276479Sdim DSAStackTy *Stack; 7091276479Sdim 7092276479Sdimpublic: 7093276479Sdim bool VisitDeclRefExpr(DeclRefExpr *E) { 7094276479Sdim if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) { 7095276479Sdim DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, false); 7096276479Sdim if (DVar.CKind == OMPC_shared && !DVar.RefExpr) 7097276479Sdim return false; 7098276479Sdim if (DVar.CKind != OMPC_unknown) 7099276479Sdim return true; 7100276479Sdim DSAStackTy::DSAVarData DVarPrivate = 7101276479Sdim Stack->hasDSA(VD, isOpenMPPrivate, MatchesAlways(), false); 7102276479Sdim if (DVarPrivate.CKind != OMPC_unknown) 7103276479Sdim return true; 7104276479Sdim return false; 7105276479Sdim } 7106276479Sdim return false; 7107276479Sdim } 7108276479Sdim bool VisitStmt(Stmt *S) { 7109276479Sdim for (auto Child : S->children()) { 7110276479Sdim if (Child && Visit(Child)) 7111276479Sdim return true; 7112276479Sdim } 7113276479Sdim return false; 7114276479Sdim } 7115276479Sdim explicit DSARefChecker(DSAStackTy *S) : Stack(S) {} 7116276479Sdim}; 7117276479Sdim} // namespace 7118276479Sdim 7119276479SdimOMPClause *Sema::ActOnOpenMPReductionClause( 7120276479Sdim ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, 7121276479Sdim SourceLocation ColonLoc, SourceLocation EndLoc, 7122276479Sdim CXXScopeSpec &ReductionIdScopeSpec, 7123276479Sdim const DeclarationNameInfo &ReductionId) { 7124276479Sdim // TODO: Allow scope specification search when 'declare reduction' is 7125276479Sdim // supported. 7126276479Sdim assert(ReductionIdScopeSpec.isEmpty() && 7127276479Sdim "No support for scoped reduction identifiers yet."); 7128276479Sdim 7129276479Sdim auto DN = ReductionId.getName(); 7130276479Sdim auto OOK = DN.getCXXOverloadedOperator(); 7131276479Sdim BinaryOperatorKind BOK = BO_Comma; 7132276479Sdim 7133276479Sdim // OpenMP [2.14.3.6, reduction clause] 7134276479Sdim // C 7135276479Sdim // reduction-identifier is either an identifier or one of the following 7136276479Sdim // operators: +, -, *, &, |, ^, && and || 7137276479Sdim // C++ 7138276479Sdim // reduction-identifier is either an id-expression or one of the following 7139276479Sdim // operators: +, -, *, &, |, ^, && and || 7140276479Sdim // FIXME: Only 'min' and 'max' identifiers are supported for now. 7141276479Sdim switch (OOK) { 7142276479Sdim case OO_Plus: 7143276479Sdim case OO_Minus: 7144288943Sdim BOK = BO_Add; 7145276479Sdim break; 7146276479Sdim case OO_Star: 7147288943Sdim BOK = BO_Mul; 7148276479Sdim break; 7149276479Sdim case OO_Amp: 7150288943Sdim BOK = BO_And; 7151276479Sdim break; 7152276479Sdim case OO_Pipe: 7153288943Sdim BOK = BO_Or; 7154276479Sdim break; 7155276479Sdim case OO_Caret: 7156288943Sdim BOK = BO_Xor; 7157276479Sdim break; 7158276479Sdim case OO_AmpAmp: 7159276479Sdim BOK = BO_LAnd; 7160276479Sdim break; 7161276479Sdim case OO_PipePipe: 7162276479Sdim BOK = BO_LOr; 7163276479Sdim break; 7164288943Sdim case OO_New: 7165288943Sdim case OO_Delete: 7166288943Sdim case OO_Array_New: 7167288943Sdim case OO_Array_Delete: 7168288943Sdim case OO_Slash: 7169288943Sdim case OO_Percent: 7170288943Sdim case OO_Tilde: 7171288943Sdim case OO_Exclaim: 7172288943Sdim case OO_Equal: 7173288943Sdim case OO_Less: 7174288943Sdim case OO_Greater: 7175288943Sdim case OO_LessEqual: 7176288943Sdim case OO_GreaterEqual: 7177288943Sdim case OO_PlusEqual: 7178288943Sdim case OO_MinusEqual: 7179288943Sdim case OO_StarEqual: 7180288943Sdim case OO_SlashEqual: 7181288943Sdim case OO_PercentEqual: 7182288943Sdim case OO_CaretEqual: 7183288943Sdim case OO_AmpEqual: 7184288943Sdim case OO_PipeEqual: 7185288943Sdim case OO_LessLess: 7186288943Sdim case OO_GreaterGreater: 7187288943Sdim case OO_LessLessEqual: 7188288943Sdim case OO_GreaterGreaterEqual: 7189288943Sdim case OO_EqualEqual: 7190288943Sdim case OO_ExclaimEqual: 7191288943Sdim case OO_PlusPlus: 7192288943Sdim case OO_MinusMinus: 7193288943Sdim case OO_Comma: 7194288943Sdim case OO_ArrowStar: 7195288943Sdim case OO_Arrow: 7196288943Sdim case OO_Call: 7197288943Sdim case OO_Subscript: 7198288943Sdim case OO_Conditional: 7199296417Sdim case OO_Coawait: 7200288943Sdim case NUM_OVERLOADED_OPERATORS: 7201288943Sdim llvm_unreachable("Unexpected reduction identifier"); 7202288943Sdim case OO_None: 7203276479Sdim if (auto II = DN.getAsIdentifierInfo()) { 7204276479Sdim if (II->isStr("max")) 7205276479Sdim BOK = BO_GT; 7206276479Sdim else if (II->isStr("min")) 7207276479Sdim BOK = BO_LT; 7208276479Sdim } 7209276479Sdim break; 7210276479Sdim } 7211276479Sdim SourceRange ReductionIdRange; 7212276479Sdim if (ReductionIdScopeSpec.isValid()) { 7213276479Sdim ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc()); 7214276479Sdim } 7215276479Sdim ReductionIdRange.setEnd(ReductionId.getEndLoc()); 7216276479Sdim if (BOK == BO_Comma) { 7217276479Sdim // Not allowed reduction identifier is found. 7218276479Sdim Diag(ReductionId.getLocStart(), diag::err_omp_unknown_reduction_identifier) 7219276479Sdim << ReductionIdRange; 7220276479Sdim return nullptr; 7221276479Sdim } 7222276479Sdim 7223276479Sdim SmallVector<Expr *, 8> Vars; 7224296417Sdim SmallVector<Expr *, 8> Privates; 7225288943Sdim SmallVector<Expr *, 8> LHSs; 7226288943Sdim SmallVector<Expr *, 8> RHSs; 7227288943Sdim SmallVector<Expr *, 8> ReductionOps; 7228276479Sdim for (auto RefExpr : VarList) { 7229276479Sdim assert(RefExpr && "nullptr expr in OpenMP reduction clause."); 7230276479Sdim if (isa<DependentScopeDeclRefExpr>(RefExpr)) { 7231276479Sdim // It will be analyzed later. 7232276479Sdim Vars.push_back(RefExpr); 7233296417Sdim Privates.push_back(nullptr); 7234288943Sdim LHSs.push_back(nullptr); 7235288943Sdim RHSs.push_back(nullptr); 7236288943Sdim ReductionOps.push_back(nullptr); 7237276479Sdim continue; 7238276479Sdim } 7239276479Sdim 7240276479Sdim if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() || 7241276479Sdim RefExpr->isInstantiationDependent() || 7242276479Sdim RefExpr->containsUnexpandedParameterPack()) { 7243276479Sdim // It will be analyzed later. 7244276479Sdim Vars.push_back(RefExpr); 7245296417Sdim Privates.push_back(nullptr); 7246288943Sdim LHSs.push_back(nullptr); 7247288943Sdim RHSs.push_back(nullptr); 7248288943Sdim ReductionOps.push_back(nullptr); 7249276479Sdim continue; 7250276479Sdim } 7251276479Sdim 7252276479Sdim auto ELoc = RefExpr->getExprLoc(); 7253276479Sdim auto ERange = RefExpr->getSourceRange(); 7254276479Sdim // OpenMP [2.1, C/C++] 7255276479Sdim // A list item is a variable or array section, subject to the restrictions 7256276479Sdim // specified in Section 2.4 on page 42 and in each of the sections 7257276479Sdim // describing clauses and directives for which a list appears. 7258276479Sdim // OpenMP [2.14.3.3, Restrictions, p.1] 7259276479Sdim // A variable that is part of another variable (as an array or 7260276479Sdim // structure element) cannot appear in a private clause. 7261296417Sdim auto *DE = dyn_cast<DeclRefExpr>(RefExpr); 7262296417Sdim auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr); 7263296417Sdim auto *OASE = dyn_cast<OMPArraySectionExpr>(RefExpr); 7264296417Sdim if (!ASE && !OASE && (!DE || !isa<VarDecl>(DE->getDecl()))) { 7265296417Sdim Diag(ELoc, diag::err_omp_expected_var_name_or_array_item) << ERange; 7266276479Sdim continue; 7267276479Sdim } 7268296417Sdim QualType Type; 7269296417Sdim VarDecl *VD = nullptr; 7270296417Sdim if (DE) { 7271296417Sdim auto D = DE->getDecl(); 7272296417Sdim VD = cast<VarDecl>(D); 7273296417Sdim Type = VD->getType(); 7274296417Sdim } else if (ASE) { 7275296417Sdim Type = ASE->getType(); 7276296417Sdim auto *Base = ASE->getBase()->IgnoreParenImpCasts(); 7277296417Sdim while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 7278296417Sdim Base = TempASE->getBase()->IgnoreParenImpCasts(); 7279296417Sdim DE = dyn_cast<DeclRefExpr>(Base); 7280296417Sdim if (DE) 7281296417Sdim VD = dyn_cast<VarDecl>(DE->getDecl()); 7282296417Sdim if (!VD) { 7283296417Sdim Diag(Base->getExprLoc(), diag::err_omp_expected_base_var_name) 7284296417Sdim << 0 << Base->getSourceRange(); 7285296417Sdim continue; 7286296417Sdim } 7287296417Sdim } else if (OASE) { 7288296417Sdim auto BaseType = OMPArraySectionExpr::getBaseOriginalType(OASE->getBase()); 7289296417Sdim if (auto *ATy = BaseType->getAsArrayTypeUnsafe()) 7290296417Sdim Type = ATy->getElementType(); 7291296417Sdim else 7292296417Sdim Type = BaseType->getPointeeType(); 7293296417Sdim auto *Base = OASE->getBase()->IgnoreParenImpCasts(); 7294296417Sdim while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 7295296417Sdim Base = TempOASE->getBase()->IgnoreParenImpCasts(); 7296296417Sdim while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 7297296417Sdim Base = TempASE->getBase()->IgnoreParenImpCasts(); 7298296417Sdim DE = dyn_cast<DeclRefExpr>(Base); 7299296417Sdim if (DE) 7300296417Sdim VD = dyn_cast<VarDecl>(DE->getDecl()); 7301296417Sdim if (!VD) { 7302296417Sdim Diag(Base->getExprLoc(), diag::err_omp_expected_base_var_name) 7303296417Sdim << 1 << Base->getSourceRange(); 7304296417Sdim continue; 7305296417Sdim } 7306296417Sdim } 7307296417Sdim 7308276479Sdim // OpenMP [2.9.3.3, Restrictions, C/C++, p.3] 7309276479Sdim // A variable that appears in a private clause must not have an incomplete 7310276479Sdim // type or a reference type. 7311276479Sdim if (RequireCompleteType(ELoc, Type, 7312276479Sdim diag::err_omp_reduction_incomplete_type)) 7313276479Sdim continue; 7314276479Sdim // OpenMP [2.14.3.6, reduction clause, Restrictions] 7315276479Sdim // Arrays may not appear in a reduction clause. 7316276479Sdim if (Type.getNonReferenceType()->isArrayType()) { 7317276479Sdim Diag(ELoc, diag::err_omp_reduction_type_array) << Type << ERange; 7318296417Sdim if (!ASE && !OASE) { 7319296417Sdim bool IsDecl = VD->isThisDeclarationADefinition(Context) == 7320296417Sdim VarDecl::DeclarationOnly; 7321296417Sdim Diag(VD->getLocation(), 7322296417Sdim IsDecl ? diag::note_previous_decl : diag::note_defined_here) 7323296417Sdim << VD; 7324296417Sdim } 7325276479Sdim continue; 7326276479Sdim } 7327276479Sdim // OpenMP [2.14.3.6, reduction clause, Restrictions] 7328276479Sdim // A list item that appears in a reduction clause must not be 7329276479Sdim // const-qualified. 7330276479Sdim if (Type.getNonReferenceType().isConstant(Context)) { 7331296417Sdim Diag(ELoc, diag::err_omp_const_reduction_list_item) 7332276479Sdim << getOpenMPClauseName(OMPC_reduction) << Type << ERange; 7333296417Sdim if (!ASE && !OASE) { 7334296417Sdim bool IsDecl = VD->isThisDeclarationADefinition(Context) == 7335296417Sdim VarDecl::DeclarationOnly; 7336296417Sdim Diag(VD->getLocation(), 7337296417Sdim IsDecl ? diag::note_previous_decl : diag::note_defined_here) 7338296417Sdim << VD; 7339296417Sdim } 7340276479Sdim continue; 7341276479Sdim } 7342276479Sdim // OpenMP [2.9.3.6, Restrictions, C/C++, p.4] 7343276479Sdim // If a list-item is a reference type then it must bind to the same object 7344276479Sdim // for all threads of the team. 7345296417Sdim if (!ASE && !OASE) { 7346296417Sdim VarDecl *VDDef = VD->getDefinition(); 7347296417Sdim if (Type->isReferenceType() && VDDef) { 7348296417Sdim DSARefChecker Check(DSAStack); 7349296417Sdim if (Check.Visit(VDDef->getInit())) { 7350296417Sdim Diag(ELoc, diag::err_omp_reduction_ref_type_arg) << ERange; 7351296417Sdim Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef; 7352296417Sdim continue; 7353296417Sdim } 7354276479Sdim } 7355276479Sdim } 7356276479Sdim // OpenMP [2.14.3.6, reduction clause, Restrictions] 7357276479Sdim // The type of a list item that appears in a reduction clause must be valid 7358276479Sdim // for the reduction-identifier. For a max or min reduction in C, the type 7359276479Sdim // of the list item must be an allowed arithmetic data type: char, int, 7360276479Sdim // float, double, or _Bool, possibly modified with long, short, signed, or 7361276479Sdim // unsigned. For a max or min reduction in C++, the type of the list item 7362276479Sdim // must be an allowed arithmetic data type: char, wchar_t, int, float, 7363276479Sdim // double, or bool, possibly modified with long, short, signed, or unsigned. 7364276479Sdim if ((BOK == BO_GT || BOK == BO_LT) && 7365276479Sdim !(Type->isScalarType() || 7366276479Sdim (getLangOpts().CPlusPlus && Type->isArithmeticType()))) { 7367276479Sdim Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg) 7368276479Sdim << getLangOpts().CPlusPlus; 7369296417Sdim if (!ASE && !OASE) { 7370296417Sdim bool IsDecl = VD->isThisDeclarationADefinition(Context) == 7371296417Sdim VarDecl::DeclarationOnly; 7372296417Sdim Diag(VD->getLocation(), 7373296417Sdim IsDecl ? diag::note_previous_decl : diag::note_defined_here) 7374296417Sdim << VD; 7375296417Sdim } 7376276479Sdim continue; 7377276479Sdim } 7378276479Sdim if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) && 7379276479Sdim !getLangOpts().CPlusPlus && Type->isFloatingType()) { 7380276479Sdim Diag(ELoc, diag::err_omp_clause_floating_type_arg); 7381296417Sdim if (!ASE && !OASE) { 7382296417Sdim bool IsDecl = VD->isThisDeclarationADefinition(Context) == 7383296417Sdim VarDecl::DeclarationOnly; 7384296417Sdim Diag(VD->getLocation(), 7385296417Sdim IsDecl ? diag::note_previous_decl : diag::note_defined_here) 7386296417Sdim << VD; 7387296417Sdim } 7388276479Sdim continue; 7389276479Sdim } 7390276479Sdim // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced 7391276479Sdim // in a Construct] 7392276479Sdim // Variables with the predetermined data-sharing attributes may not be 7393276479Sdim // listed in data-sharing attributes clauses, except for the cases 7394276479Sdim // listed below. For these exceptions only, listing a predetermined 7395276479Sdim // variable in a data-sharing attribute clause is allowed and overrides 7396276479Sdim // the variable's predetermined data-sharing attributes. 7397276479Sdim // OpenMP [2.14.3.6, Restrictions, p.3] 7398276479Sdim // Any number of reduction clauses can be specified on the directive, 7399276479Sdim // but a list item can appear only once in the reduction clauses for that 7400276479Sdim // directive. 7401296417Sdim DSAStackTy::DSAVarData DVar; 7402296417Sdim DVar = DSAStack->getTopDSA(VD, false); 7403276479Sdim if (DVar.CKind == OMPC_reduction) { 7404276479Sdim Diag(ELoc, diag::err_omp_once_referenced) 7405276479Sdim << getOpenMPClauseName(OMPC_reduction); 7406276479Sdim if (DVar.RefExpr) { 7407276479Sdim Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced); 7408276479Sdim } 7409276479Sdim } else if (DVar.CKind != OMPC_unknown) { 7410276479Sdim Diag(ELoc, diag::err_omp_wrong_dsa) 7411276479Sdim << getOpenMPClauseName(DVar.CKind) 7412276479Sdim << getOpenMPClauseName(OMPC_reduction); 7413276479Sdim ReportOriginalDSA(*this, DSAStack, VD, DVar); 7414276479Sdim continue; 7415276479Sdim } 7416276479Sdim 7417276479Sdim // OpenMP [2.14.3.6, Restrictions, p.1] 7418276479Sdim // A list item that appears in a reduction clause of a worksharing 7419276479Sdim // construct must be shared in the parallel regions to which any of the 7420276479Sdim // worksharing regions arising from the worksharing construct bind. 7421276479Sdim OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective(); 7422276479Sdim if (isOpenMPWorksharingDirective(CurrDir) && 7423276479Sdim !isOpenMPParallelDirective(CurrDir)) { 7424276479Sdim DVar = DSAStack->getImplicitDSA(VD, true); 7425276479Sdim if (DVar.CKind != OMPC_shared) { 7426276479Sdim Diag(ELoc, diag::err_omp_required_access) 7427276479Sdim << getOpenMPClauseName(OMPC_reduction) 7428276479Sdim << getOpenMPClauseName(OMPC_shared); 7429276479Sdim ReportOriginalDSA(*this, DSAStack, VD, DVar); 7430276479Sdim continue; 7431276479Sdim } 7432276479Sdim } 7433296417Sdim 7434288943Sdim Type = Type.getNonLValueExprType(Context).getUnqualifiedType(); 7435296417Sdim auto *LHSVD = buildVarDecl(*this, ELoc, Type, ".reduction.lhs", 7436296417Sdim VD->hasAttrs() ? &VD->getAttrs() : nullptr); 7437296417Sdim auto *RHSVD = buildVarDecl(*this, ELoc, Type, VD->getName(), 7438296417Sdim VD->hasAttrs() ? &VD->getAttrs() : nullptr); 7439296417Sdim auto PrivateTy = Type; 7440296417Sdim if (OASE) { 7441296417Sdim // For array sections only: 7442296417Sdim // Create pseudo array type for private copy. The size for this array will 7443296417Sdim // be generated during codegen. 7444296417Sdim // For array subscripts or single variables Private Ty is the same as Type 7445296417Sdim // (type of the variable or single array element). 7446296417Sdim PrivateTy = Context.getVariableArrayType( 7447296417Sdim Type, new (Context) OpaqueValueExpr(SourceLocation(), 7448296417Sdim Context.getSizeType(), VK_RValue), 7449296417Sdim ArrayType::Normal, /*IndexTypeQuals=*/0, SourceRange()); 7450296417Sdim } 7451296417Sdim // Private copy. 7452296417Sdim auto *PrivateVD = buildVarDecl(*this, ELoc, PrivateTy, VD->getName(), 7453296417Sdim VD->hasAttrs() ? &VD->getAttrs() : nullptr); 7454288943Sdim // Add initializer for private variable. 7455288943Sdim Expr *Init = nullptr; 7456288943Sdim switch (BOK) { 7457288943Sdim case BO_Add: 7458288943Sdim case BO_Xor: 7459288943Sdim case BO_Or: 7460288943Sdim case BO_LOr: 7461288943Sdim // '+', '-', '^', '|', '||' reduction ops - initializer is '0'. 7462288943Sdim if (Type->isScalarType() || Type->isAnyComplexType()) { 7463288943Sdim Init = ActOnIntegerConstant(ELoc, /*Val=*/0).get(); 7464276479Sdim } 7465288943Sdim break; 7466288943Sdim case BO_Mul: 7467288943Sdim case BO_LAnd: 7468288943Sdim if (Type->isScalarType() || Type->isAnyComplexType()) { 7469288943Sdim // '*' and '&&' reduction ops - initializer is '1'. 7470288943Sdim Init = ActOnIntegerConstant(ELoc, /*Val=*/1).get(); 7471288943Sdim } 7472288943Sdim break; 7473288943Sdim case BO_And: { 7474288943Sdim // '&' reduction op - initializer is '~0'. 7475288943Sdim QualType OrigType = Type; 7476288943Sdim if (auto *ComplexTy = OrigType->getAs<ComplexType>()) { 7477288943Sdim Type = ComplexTy->getElementType(); 7478288943Sdim } 7479288943Sdim if (Type->isRealFloatingType()) { 7480288943Sdim llvm::APFloat InitValue = 7481288943Sdim llvm::APFloat::getAllOnesValue(Context.getTypeSize(Type), 7482288943Sdim /*isIEEE=*/true); 7483288943Sdim Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true, 7484288943Sdim Type, ELoc); 7485288943Sdim } else if (Type->isScalarType()) { 7486288943Sdim auto Size = Context.getTypeSize(Type); 7487288943Sdim QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0); 7488288943Sdim llvm::APInt InitValue = llvm::APInt::getAllOnesValue(Size); 7489288943Sdim Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc); 7490288943Sdim } 7491288943Sdim if (Init && OrigType->isAnyComplexType()) { 7492288943Sdim // Init = 0xFFFF + 0xFFFFi; 7493288943Sdim auto *Im = new (Context) ImaginaryLiteral(Init, OrigType); 7494288943Sdim Init = CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get(); 7495288943Sdim } 7496288943Sdim Type = OrigType; 7497288943Sdim break; 7498288943Sdim } 7499288943Sdim case BO_LT: 7500288943Sdim case BO_GT: { 7501288943Sdim // 'min' reduction op - initializer is 'Largest representable number in 7502288943Sdim // the reduction list item type'. 7503288943Sdim // 'max' reduction op - initializer is 'Least representable number in 7504288943Sdim // the reduction list item type'. 7505288943Sdim if (Type->isIntegerType() || Type->isPointerType()) { 7506288943Sdim bool IsSigned = Type->hasSignedIntegerRepresentation(); 7507288943Sdim auto Size = Context.getTypeSize(Type); 7508288943Sdim QualType IntTy = 7509288943Sdim Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned); 7510288943Sdim llvm::APInt InitValue = 7511288943Sdim (BOK != BO_LT) 7512288943Sdim ? IsSigned ? llvm::APInt::getSignedMinValue(Size) 7513288943Sdim : llvm::APInt::getMinValue(Size) 7514288943Sdim : IsSigned ? llvm::APInt::getSignedMaxValue(Size) 7515288943Sdim : llvm::APInt::getMaxValue(Size); 7516288943Sdim Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc); 7517288943Sdim if (Type->isPointerType()) { 7518288943Sdim // Cast to pointer type. 7519288943Sdim auto CastExpr = BuildCStyleCastExpr( 7520288943Sdim SourceLocation(), Context.getTrivialTypeSourceInfo(Type, ELoc), 7521288943Sdim SourceLocation(), Init); 7522288943Sdim if (CastExpr.isInvalid()) 7523288943Sdim continue; 7524288943Sdim Init = CastExpr.get(); 7525276479Sdim } 7526288943Sdim } else if (Type->isRealFloatingType()) { 7527288943Sdim llvm::APFloat InitValue = llvm::APFloat::getLargest( 7528288943Sdim Context.getFloatTypeSemantics(Type), BOK != BO_LT); 7529288943Sdim Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true, 7530288943Sdim Type, ELoc); 7531276479Sdim } 7532288943Sdim break; 7533276479Sdim } 7534288943Sdim case BO_PtrMemD: 7535288943Sdim case BO_PtrMemI: 7536288943Sdim case BO_MulAssign: 7537288943Sdim case BO_Div: 7538288943Sdim case BO_Rem: 7539288943Sdim case BO_Sub: 7540288943Sdim case BO_Shl: 7541288943Sdim case BO_Shr: 7542288943Sdim case BO_LE: 7543288943Sdim case BO_GE: 7544288943Sdim case BO_EQ: 7545288943Sdim case BO_NE: 7546288943Sdim case BO_AndAssign: 7547288943Sdim case BO_XorAssign: 7548288943Sdim case BO_OrAssign: 7549288943Sdim case BO_Assign: 7550288943Sdim case BO_AddAssign: 7551288943Sdim case BO_SubAssign: 7552288943Sdim case BO_DivAssign: 7553288943Sdim case BO_RemAssign: 7554288943Sdim case BO_ShlAssign: 7555288943Sdim case BO_ShrAssign: 7556288943Sdim case BO_Comma: 7557288943Sdim llvm_unreachable("Unexpected reduction operation"); 7558288943Sdim } 7559288943Sdim if (Init) { 7560288943Sdim AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false, 7561288943Sdim /*TypeMayContainAuto=*/false); 7562296417Sdim } else 7563288943Sdim ActOnUninitializedDecl(RHSVD, /*TypeMayContainAuto=*/false); 7564288943Sdim if (!RHSVD->hasInit()) { 7565288943Sdim Diag(ELoc, diag::err_omp_reduction_id_not_compatible) << Type 7566288943Sdim << ReductionIdRange; 7567296417Sdim if (VD) { 7568296417Sdim bool IsDecl = VD->isThisDeclarationADefinition(Context) == 7569296417Sdim VarDecl::DeclarationOnly; 7570296417Sdim Diag(VD->getLocation(), 7571296417Sdim IsDecl ? diag::note_previous_decl : diag::note_defined_here) 7572296417Sdim << VD; 7573296417Sdim } 7574288943Sdim continue; 7575288943Sdim } 7576296417Sdim // Store initializer for single element in private copy. Will be used during 7577296417Sdim // codegen. 7578296417Sdim PrivateVD->setInit(RHSVD->getInit()); 7579296417Sdim PrivateVD->setInitStyle(RHSVD->getInitStyle()); 7580288943Sdim auto *LHSDRE = buildDeclRefExpr(*this, LHSVD, Type, ELoc); 7581288943Sdim auto *RHSDRE = buildDeclRefExpr(*this, RHSVD, Type, ELoc); 7582296417Sdim auto *PrivateDRE = buildDeclRefExpr(*this, PrivateVD, PrivateTy, ELoc); 7583288943Sdim ExprResult ReductionOp = 7584288943Sdim BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(), BOK, 7585288943Sdim LHSDRE, RHSDRE); 7586288943Sdim if (ReductionOp.isUsable()) { 7587288943Sdim if (BOK != BO_LT && BOK != BO_GT) { 7588288943Sdim ReductionOp = 7589288943Sdim BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(), 7590288943Sdim BO_Assign, LHSDRE, ReductionOp.get()); 7591288943Sdim } else { 7592288943Sdim auto *ConditionalOp = new (Context) ConditionalOperator( 7593288943Sdim ReductionOp.get(), SourceLocation(), LHSDRE, SourceLocation(), 7594288943Sdim RHSDRE, Type, VK_LValue, OK_Ordinary); 7595288943Sdim ReductionOp = 7596288943Sdim BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(), 7597288943Sdim BO_Assign, LHSDRE, ConditionalOp); 7598288943Sdim } 7599296417Sdim ReductionOp = ActOnFinishFullExpr(ReductionOp.get()); 7600288943Sdim } 7601288943Sdim if (ReductionOp.isInvalid()) 7602288943Sdim continue; 7603276479Sdim 7604276479Sdim DSAStack->addDSA(VD, DE, OMPC_reduction); 7605296417Sdim Vars.push_back(RefExpr); 7606296417Sdim Privates.push_back(PrivateDRE); 7607288943Sdim LHSs.push_back(LHSDRE); 7608288943Sdim RHSs.push_back(RHSDRE); 7609288943Sdim ReductionOps.push_back(ReductionOp.get()); 7610276479Sdim } 7611276479Sdim 7612276479Sdim if (Vars.empty()) 7613276479Sdim return nullptr; 7614276479Sdim 7615276479Sdim return OMPReductionClause::Create( 7616276479Sdim Context, StartLoc, LParenLoc, ColonLoc, EndLoc, Vars, 7617296417Sdim ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId, Privates, 7618296417Sdim LHSs, RHSs, ReductionOps); 7619276479Sdim} 7620276479Sdim 7621296417SdimOMPClause *Sema::ActOnOpenMPLinearClause( 7622296417Sdim ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc, 7623296417Sdim SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind, 7624296417Sdim SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation EndLoc) { 7625276479Sdim SmallVector<Expr *, 8> Vars; 7626296417Sdim SmallVector<Expr *, 8> Privates; 7627288943Sdim SmallVector<Expr *, 8> Inits; 7628296417Sdim if ((!LangOpts.CPlusPlus && LinKind != OMPC_LINEAR_val) || 7629296417Sdim LinKind == OMPC_LINEAR_unknown) { 7630296417Sdim Diag(LinLoc, diag::err_omp_wrong_linear_modifier) << LangOpts.CPlusPlus; 7631296417Sdim LinKind = OMPC_LINEAR_val; 7632296417Sdim } 7633276479Sdim for (auto &RefExpr : VarList) { 7634276479Sdim assert(RefExpr && "NULL expr in OpenMP linear clause."); 7635276479Sdim if (isa<DependentScopeDeclRefExpr>(RefExpr)) { 7636276479Sdim // It will be analyzed later. 7637276479Sdim Vars.push_back(RefExpr); 7638296417Sdim Privates.push_back(nullptr); 7639288943Sdim Inits.push_back(nullptr); 7640276479Sdim continue; 7641276479Sdim } 7642276479Sdim 7643276479Sdim // OpenMP [2.14.3.7, linear clause] 7644276479Sdim // A list item that appears in a linear clause is subject to the private 7645276479Sdim // clause semantics described in Section 2.14.3.3 on page 159 except as 7646276479Sdim // noted. In addition, the value of the new list item on each iteration 7647276479Sdim // of the associated loop(s) corresponds to the value of the original 7648276479Sdim // list item before entering the construct plus the logical number of 7649276479Sdim // the iteration times linear-step. 7650276479Sdim 7651276479Sdim SourceLocation ELoc = RefExpr->getExprLoc(); 7652276479Sdim // OpenMP [2.1, C/C++] 7653276479Sdim // A list item is a variable name. 7654276479Sdim // OpenMP [2.14.3.3, Restrictions, p.1] 7655276479Sdim // A variable that is part of another variable (as an array or 7656276479Sdim // structure element) cannot appear in a private clause. 7657276479Sdim DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr); 7658276479Sdim if (!DE || !isa<VarDecl>(DE->getDecl())) { 7659276479Sdim Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange(); 7660276479Sdim continue; 7661276479Sdim } 7662276479Sdim 7663276479Sdim VarDecl *VD = cast<VarDecl>(DE->getDecl()); 7664276479Sdim 7665276479Sdim // OpenMP [2.14.3.7, linear clause] 7666276479Sdim // A list-item cannot appear in more than one linear clause. 7667276479Sdim // A list-item that appears in a linear clause cannot appear in any 7668276479Sdim // other data-sharing attribute clause. 7669276479Sdim DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false); 7670276479Sdim if (DVar.RefExpr) { 7671276479Sdim Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind) 7672276479Sdim << getOpenMPClauseName(OMPC_linear); 7673276479Sdim ReportOriginalDSA(*this, DSAStack, VD, DVar); 7674276479Sdim continue; 7675276479Sdim } 7676276479Sdim 7677276479Sdim QualType QType = VD->getType(); 7678276479Sdim if (QType->isDependentType() || QType->isInstantiationDependentType()) { 7679276479Sdim // It will be analyzed later. 7680276479Sdim Vars.push_back(DE); 7681296417Sdim Privates.push_back(nullptr); 7682288943Sdim Inits.push_back(nullptr); 7683276479Sdim continue; 7684276479Sdim } 7685276479Sdim 7686276479Sdim // A variable must not have an incomplete type or a reference type. 7687276479Sdim if (RequireCompleteType(ELoc, QType, 7688276479Sdim diag::err_omp_linear_incomplete_type)) { 7689276479Sdim continue; 7690276479Sdim } 7691296417Sdim if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) && 7692296417Sdim !QType->isReferenceType()) { 7693296417Sdim Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference) 7694296417Sdim << QType << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind); 7695276479Sdim continue; 7696276479Sdim } 7697296417Sdim QType = QType.getNonReferenceType(); 7698276479Sdim 7699276479Sdim // A list item must not be const-qualified. 7700276479Sdim if (QType.isConstant(Context)) { 7701276479Sdim Diag(ELoc, diag::err_omp_const_variable) 7702276479Sdim << getOpenMPClauseName(OMPC_linear); 7703276479Sdim bool IsDecl = 7704276479Sdim VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 7705276479Sdim Diag(VD->getLocation(), 7706276479Sdim IsDecl ? diag::note_previous_decl : diag::note_defined_here) 7707276479Sdim << VD; 7708276479Sdim continue; 7709276479Sdim } 7710276479Sdim 7711276479Sdim // A list item must be of integral or pointer type. 7712276479Sdim QType = QType.getUnqualifiedType().getCanonicalType(); 7713276479Sdim const Type *Ty = QType.getTypePtrOrNull(); 7714276479Sdim if (!Ty || (!Ty->isDependentType() && !Ty->isIntegralType(Context) && 7715276479Sdim !Ty->isPointerType())) { 7716276479Sdim Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << QType; 7717276479Sdim bool IsDecl = 7718276479Sdim VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 7719276479Sdim Diag(VD->getLocation(), 7720276479Sdim IsDecl ? diag::note_previous_decl : diag::note_defined_here) 7721276479Sdim << VD; 7722276479Sdim continue; 7723276479Sdim } 7724276479Sdim 7725296417Sdim // Build private copy of original var. 7726296417Sdim auto *Private = buildVarDecl(*this, ELoc, QType, VD->getName(), 7727296417Sdim VD->hasAttrs() ? &VD->getAttrs() : nullptr); 7728296417Sdim auto *PrivateRef = buildDeclRefExpr( 7729296417Sdim *this, Private, DE->getType().getUnqualifiedType(), DE->getExprLoc()); 7730288943Sdim // Build var to save initial value. 7731288943Sdim VarDecl *Init = buildVarDecl(*this, ELoc, QType, ".linear.start"); 7732296417Sdim Expr *InitExpr; 7733296417Sdim if (LinKind == OMPC_LINEAR_uval) 7734296417Sdim InitExpr = VD->getInit(); 7735296417Sdim else 7736296417Sdim InitExpr = DE; 7737296417Sdim AddInitializerToDecl(Init, DefaultLvalueConversion(InitExpr).get(), 7738288943Sdim /*DirectInit*/ false, /*TypeMayContainAuto*/ false); 7739288943Sdim auto InitRef = buildDeclRefExpr( 7740288943Sdim *this, Init, DE->getType().getUnqualifiedType(), DE->getExprLoc()); 7741276479Sdim DSAStack->addDSA(VD, DE, OMPC_linear); 7742276479Sdim Vars.push_back(DE); 7743296417Sdim Privates.push_back(PrivateRef); 7744288943Sdim Inits.push_back(InitRef); 7745276479Sdim } 7746276479Sdim 7747276479Sdim if (Vars.empty()) 7748276479Sdim return nullptr; 7749276479Sdim 7750276479Sdim Expr *StepExpr = Step; 7751288943Sdim Expr *CalcStepExpr = nullptr; 7752276479Sdim if (Step && !Step->isValueDependent() && !Step->isTypeDependent() && 7753276479Sdim !Step->isInstantiationDependent() && 7754276479Sdim !Step->containsUnexpandedParameterPack()) { 7755276479Sdim SourceLocation StepLoc = Step->getLocStart(); 7756276479Sdim ExprResult Val = PerformOpenMPImplicitIntegerConversion(StepLoc, Step); 7757276479Sdim if (Val.isInvalid()) 7758276479Sdim return nullptr; 7759276479Sdim StepExpr = Val.get(); 7760276479Sdim 7761288943Sdim // Build var to save the step value. 7762288943Sdim VarDecl *SaveVar = 7763288943Sdim buildVarDecl(*this, StepLoc, StepExpr->getType(), ".linear.step"); 7764288943Sdim ExprResult SaveRef = 7765288943Sdim buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc); 7766288943Sdim ExprResult CalcStep = 7767288943Sdim BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr); 7768296417Sdim CalcStep = ActOnFinishFullExpr(CalcStep.get()); 7769288943Sdim 7770276479Sdim // Warn about zero linear step (it would be probably better specified as 7771276479Sdim // making corresponding variables 'const'). 7772276479Sdim llvm::APSInt Result; 7773288943Sdim bool IsConstant = StepExpr->isIntegerConstantExpr(Result, Context); 7774288943Sdim if (IsConstant && !Result.isNegative() && !Result.isStrictlyPositive()) 7775276479Sdim Diag(StepLoc, diag::warn_omp_linear_step_zero) << Vars[0] 7776276479Sdim << (Vars.size() > 1); 7777288943Sdim if (!IsConstant && CalcStep.isUsable()) { 7778288943Sdim // Calculate the step beforehand instead of doing this on each iteration. 7779288943Sdim // (This is not used if the number of iterations may be kfold-ed). 7780288943Sdim CalcStepExpr = CalcStep.get(); 7781288943Sdim } 7782276479Sdim } 7783276479Sdim 7784296417Sdim return OMPLinearClause::Create(Context, StartLoc, LParenLoc, LinKind, LinLoc, 7785296417Sdim ColonLoc, EndLoc, Vars, Privates, Inits, 7786296417Sdim StepExpr, CalcStepExpr); 7787276479Sdim} 7788276479Sdim 7789288943Sdimstatic bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, 7790288943Sdim Expr *NumIterations, Sema &SemaRef, 7791288943Sdim Scope *S) { 7792288943Sdim // Walk the vars and build update/final expressions for the CodeGen. 7793288943Sdim SmallVector<Expr *, 8> Updates; 7794288943Sdim SmallVector<Expr *, 8> Finals; 7795288943Sdim Expr *Step = Clause.getStep(); 7796288943Sdim Expr *CalcStep = Clause.getCalcStep(); 7797288943Sdim // OpenMP [2.14.3.7, linear clause] 7798288943Sdim // If linear-step is not specified it is assumed to be 1. 7799288943Sdim if (Step == nullptr) 7800288943Sdim Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(); 7801288943Sdim else if (CalcStep) 7802288943Sdim Step = cast<BinaryOperator>(CalcStep)->getLHS(); 7803288943Sdim bool HasErrors = false; 7804288943Sdim auto CurInit = Clause.inits().begin(); 7805296417Sdim auto CurPrivate = Clause.privates().begin(); 7806296417Sdim auto LinKind = Clause.getModifier(); 7807288943Sdim for (auto &RefExpr : Clause.varlists()) { 7808288943Sdim Expr *InitExpr = *CurInit; 7809288943Sdim 7810288943Sdim // Build privatized reference to the current linear var. 7811288943Sdim auto DE = cast<DeclRefExpr>(RefExpr); 7812296417Sdim Expr *CapturedRef; 7813296417Sdim if (LinKind == OMPC_LINEAR_uval) 7814296417Sdim CapturedRef = cast<VarDecl>(DE->getDecl())->getInit(); 7815296417Sdim else 7816296417Sdim CapturedRef = 7817296417Sdim buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()), 7818296417Sdim DE->getType().getUnqualifiedType(), DE->getExprLoc(), 7819296417Sdim /*RefersToCapture=*/true); 7820288943Sdim 7821288943Sdim // Build update: Var = InitExpr + IV * Step 7822288943Sdim ExprResult Update = 7823296417Sdim BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, 7824288943Sdim InitExpr, IV, Step, /* Subtract */ false); 7825296417Sdim Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getLocStart(), 7826296417Sdim /*DiscardedValue=*/true); 7827288943Sdim 7828288943Sdim // Build final: Var = InitExpr + NumIterations * Step 7829288943Sdim ExprResult Final = 7830296417Sdim BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), CapturedRef, 7831288943Sdim InitExpr, NumIterations, Step, /* Subtract */ false); 7832296417Sdim Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getLocStart(), 7833296417Sdim /*DiscardedValue=*/true); 7834288943Sdim if (!Update.isUsable() || !Final.isUsable()) { 7835288943Sdim Updates.push_back(nullptr); 7836288943Sdim Finals.push_back(nullptr); 7837288943Sdim HasErrors = true; 7838288943Sdim } else { 7839288943Sdim Updates.push_back(Update.get()); 7840288943Sdim Finals.push_back(Final.get()); 7841288943Sdim } 7842296417Sdim ++CurInit, ++CurPrivate; 7843288943Sdim } 7844288943Sdim Clause.setUpdates(Updates); 7845288943Sdim Clause.setFinals(Finals); 7846288943Sdim return HasErrors; 7847288943Sdim} 7848288943Sdim 7849276479SdimOMPClause *Sema::ActOnOpenMPAlignedClause( 7850276479Sdim ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc, 7851276479Sdim SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) { 7852276479Sdim 7853276479Sdim SmallVector<Expr *, 8> Vars; 7854276479Sdim for (auto &RefExpr : VarList) { 7855276479Sdim assert(RefExpr && "NULL expr in OpenMP aligned clause."); 7856276479Sdim if (isa<DependentScopeDeclRefExpr>(RefExpr)) { 7857276479Sdim // It will be analyzed later. 7858276479Sdim Vars.push_back(RefExpr); 7859276479Sdim continue; 7860276479Sdim } 7861276479Sdim 7862276479Sdim SourceLocation ELoc = RefExpr->getExprLoc(); 7863276479Sdim // OpenMP [2.1, C/C++] 7864276479Sdim // A list item is a variable name. 7865276479Sdim DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr); 7866276479Sdim if (!DE || !isa<VarDecl>(DE->getDecl())) { 7867276479Sdim Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange(); 7868276479Sdim continue; 7869276479Sdim } 7870276479Sdim 7871276479Sdim VarDecl *VD = cast<VarDecl>(DE->getDecl()); 7872276479Sdim 7873276479Sdim // OpenMP [2.8.1, simd construct, Restrictions] 7874276479Sdim // The type of list items appearing in the aligned clause must be 7875276479Sdim // array, pointer, reference to array, or reference to pointer. 7876288943Sdim QualType QType = VD->getType(); 7877288943Sdim QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType(); 7878276479Sdim const Type *Ty = QType.getTypePtrOrNull(); 7879276479Sdim if (!Ty || (!Ty->isDependentType() && !Ty->isArrayType() && 7880276479Sdim !Ty->isPointerType())) { 7881276479Sdim Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr) 7882276479Sdim << QType << getLangOpts().CPlusPlus << RefExpr->getSourceRange(); 7883276479Sdim bool IsDecl = 7884276479Sdim VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 7885276479Sdim Diag(VD->getLocation(), 7886276479Sdim IsDecl ? diag::note_previous_decl : diag::note_defined_here) 7887276479Sdim << VD; 7888276479Sdim continue; 7889276479Sdim } 7890276479Sdim 7891276479Sdim // OpenMP [2.8.1, simd construct, Restrictions] 7892276479Sdim // A list-item cannot appear in more than one aligned clause. 7893276479Sdim if (DeclRefExpr *PrevRef = DSAStack->addUniqueAligned(VD, DE)) { 7894276479Sdim Diag(ELoc, diag::err_omp_aligned_twice) << RefExpr->getSourceRange(); 7895276479Sdim Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa) 7896276479Sdim << getOpenMPClauseName(OMPC_aligned); 7897276479Sdim continue; 7898276479Sdim } 7899276479Sdim 7900276479Sdim Vars.push_back(DE); 7901276479Sdim } 7902276479Sdim 7903276479Sdim // OpenMP [2.8.1, simd construct, Description] 7904276479Sdim // The parameter of the aligned clause, alignment, must be a constant 7905276479Sdim // positive integer expression. 7906276479Sdim // If no optional parameter is specified, implementation-defined default 7907276479Sdim // alignments for SIMD instructions on the target platforms are assumed. 7908276479Sdim if (Alignment != nullptr) { 7909276479Sdim ExprResult AlignResult = 7910276479Sdim VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned); 7911276479Sdim if (AlignResult.isInvalid()) 7912276479Sdim return nullptr; 7913276479Sdim Alignment = AlignResult.get(); 7914276479Sdim } 7915276479Sdim if (Vars.empty()) 7916276479Sdim return nullptr; 7917276479Sdim 7918276479Sdim return OMPAlignedClause::Create(Context, StartLoc, LParenLoc, ColonLoc, 7919276479Sdim EndLoc, Vars, Alignment); 7920276479Sdim} 7921276479Sdim 7922276479SdimOMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList, 7923276479Sdim SourceLocation StartLoc, 7924276479Sdim SourceLocation LParenLoc, 7925276479Sdim SourceLocation EndLoc) { 7926276479Sdim SmallVector<Expr *, 8> Vars; 7927288943Sdim SmallVector<Expr *, 8> SrcExprs; 7928288943Sdim SmallVector<Expr *, 8> DstExprs; 7929288943Sdim SmallVector<Expr *, 8> AssignmentOps; 7930276479Sdim for (auto &RefExpr : VarList) { 7931276479Sdim assert(RefExpr && "NULL expr in OpenMP copyin clause."); 7932276479Sdim if (isa<DependentScopeDeclRefExpr>(RefExpr)) { 7933276479Sdim // It will be analyzed later. 7934276479Sdim Vars.push_back(RefExpr); 7935288943Sdim SrcExprs.push_back(nullptr); 7936288943Sdim DstExprs.push_back(nullptr); 7937288943Sdim AssignmentOps.push_back(nullptr); 7938276479Sdim continue; 7939276479Sdim } 7940276479Sdim 7941276479Sdim SourceLocation ELoc = RefExpr->getExprLoc(); 7942276479Sdim // OpenMP [2.1, C/C++] 7943276479Sdim // A list item is a variable name. 7944276479Sdim // OpenMP [2.14.4.1, Restrictions, p.1] 7945276479Sdim // A list item that appears in a copyin clause must be threadprivate. 7946276479Sdim DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr); 7947276479Sdim if (!DE || !isa<VarDecl>(DE->getDecl())) { 7948276479Sdim Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange(); 7949276479Sdim continue; 7950276479Sdim } 7951276479Sdim 7952276479Sdim Decl *D = DE->getDecl(); 7953276479Sdim VarDecl *VD = cast<VarDecl>(D); 7954276479Sdim 7955276479Sdim QualType Type = VD->getType(); 7956276479Sdim if (Type->isDependentType() || Type->isInstantiationDependentType()) { 7957276479Sdim // It will be analyzed later. 7958276479Sdim Vars.push_back(DE); 7959288943Sdim SrcExprs.push_back(nullptr); 7960288943Sdim DstExprs.push_back(nullptr); 7961288943Sdim AssignmentOps.push_back(nullptr); 7962276479Sdim continue; 7963276479Sdim } 7964276479Sdim 7965276479Sdim // OpenMP [2.14.4.1, Restrictions, C/C++, p.1] 7966276479Sdim // A list item that appears in a copyin clause must be threadprivate. 7967276479Sdim if (!DSAStack->isThreadPrivate(VD)) { 7968276479Sdim Diag(ELoc, diag::err_omp_required_access) 7969276479Sdim << getOpenMPClauseName(OMPC_copyin) 7970276479Sdim << getOpenMPDirectiveName(OMPD_threadprivate); 7971276479Sdim continue; 7972276479Sdim } 7973276479Sdim 7974276479Sdim // OpenMP [2.14.4.1, Restrictions, C/C++, p.2] 7975276479Sdim // A variable of class type (or array thereof) that appears in a 7976276479Sdim // copyin clause requires an accessible, unambiguous copy assignment 7977276479Sdim // operator for the class type. 7978288943Sdim auto ElemType = Context.getBaseElementType(Type).getNonReferenceType(); 7979296417Sdim auto *SrcVD = 7980296417Sdim buildVarDecl(*this, DE->getLocStart(), ElemType.getUnqualifiedType(), 7981296417Sdim ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr); 7982288943Sdim auto *PseudoSrcExpr = buildDeclRefExpr( 7983288943Sdim *this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc()); 7984288943Sdim auto *DstVD = 7985296417Sdim buildVarDecl(*this, DE->getLocStart(), ElemType, ".copyin.dst", 7986296417Sdim VD->hasAttrs() ? &VD->getAttrs() : nullptr); 7987288943Sdim auto *PseudoDstExpr = 7988288943Sdim buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc()); 7989288943Sdim // For arrays generate assignment operation for single element and replace 7990288943Sdim // it by the original array element in CodeGen. 7991288943Sdim auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, 7992288943Sdim PseudoDstExpr, PseudoSrcExpr); 7993288943Sdim if (AssignmentOp.isInvalid()) 7994288943Sdim continue; 7995288943Sdim AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(), 7996288943Sdim /*DiscardedValue=*/true); 7997288943Sdim if (AssignmentOp.isInvalid()) 7998288943Sdim continue; 7999276479Sdim 8000276479Sdim DSAStack->addDSA(VD, DE, OMPC_copyin); 8001276479Sdim Vars.push_back(DE); 8002288943Sdim SrcExprs.push_back(PseudoSrcExpr); 8003288943Sdim DstExprs.push_back(PseudoDstExpr); 8004288943Sdim AssignmentOps.push_back(AssignmentOp.get()); 8005276479Sdim } 8006276479Sdim 8007276479Sdim if (Vars.empty()) 8008276479Sdim return nullptr; 8009276479Sdim 8010288943Sdim return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars, 8011288943Sdim SrcExprs, DstExprs, AssignmentOps); 8012276479Sdim} 8013276479Sdim 8014276479SdimOMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, 8015276479Sdim SourceLocation StartLoc, 8016276479Sdim SourceLocation LParenLoc, 8017276479Sdim SourceLocation EndLoc) { 8018276479Sdim SmallVector<Expr *, 8> Vars; 8019288943Sdim SmallVector<Expr *, 8> SrcExprs; 8020288943Sdim SmallVector<Expr *, 8> DstExprs; 8021288943Sdim SmallVector<Expr *, 8> AssignmentOps; 8022276479Sdim for (auto &RefExpr : VarList) { 8023276479Sdim assert(RefExpr && "NULL expr in OpenMP copyprivate clause."); 8024276479Sdim if (isa<DependentScopeDeclRefExpr>(RefExpr)) { 8025276479Sdim // It will be analyzed later. 8026276479Sdim Vars.push_back(RefExpr); 8027288943Sdim SrcExprs.push_back(nullptr); 8028288943Sdim DstExprs.push_back(nullptr); 8029288943Sdim AssignmentOps.push_back(nullptr); 8030276479Sdim continue; 8031276479Sdim } 8032276479Sdim 8033276479Sdim SourceLocation ELoc = RefExpr->getExprLoc(); 8034276479Sdim // OpenMP [2.1, C/C++] 8035276479Sdim // A list item is a variable name. 8036276479Sdim // OpenMP [2.14.4.1, Restrictions, p.1] 8037276479Sdim // A list item that appears in a copyin clause must be threadprivate. 8038276479Sdim DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr); 8039276479Sdim if (!DE || !isa<VarDecl>(DE->getDecl())) { 8040276479Sdim Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange(); 8041276479Sdim continue; 8042276479Sdim } 8043276479Sdim 8044276479Sdim Decl *D = DE->getDecl(); 8045276479Sdim VarDecl *VD = cast<VarDecl>(D); 8046276479Sdim 8047276479Sdim QualType Type = VD->getType(); 8048276479Sdim if (Type->isDependentType() || Type->isInstantiationDependentType()) { 8049276479Sdim // It will be analyzed later. 8050276479Sdim Vars.push_back(DE); 8051288943Sdim SrcExprs.push_back(nullptr); 8052288943Sdim DstExprs.push_back(nullptr); 8053288943Sdim AssignmentOps.push_back(nullptr); 8054276479Sdim continue; 8055276479Sdim } 8056276479Sdim 8057276479Sdim // OpenMP [2.14.4.2, Restrictions, p.2] 8058276479Sdim // A list item that appears in a copyprivate clause may not appear in a 8059276479Sdim // private or firstprivate clause on the single construct. 8060276479Sdim if (!DSAStack->isThreadPrivate(VD)) { 8061276479Sdim auto DVar = DSAStack->getTopDSA(VD, false); 8062288943Sdim if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate && 8063288943Sdim DVar.RefExpr) { 8064276479Sdim Diag(ELoc, diag::err_omp_wrong_dsa) 8065276479Sdim << getOpenMPClauseName(DVar.CKind) 8066276479Sdim << getOpenMPClauseName(OMPC_copyprivate); 8067276479Sdim ReportOriginalDSA(*this, DSAStack, VD, DVar); 8068276479Sdim continue; 8069276479Sdim } 8070276479Sdim 8071276479Sdim // OpenMP [2.11.4.2, Restrictions, p.1] 8072276479Sdim // All list items that appear in a copyprivate clause must be either 8073276479Sdim // threadprivate or private in the enclosing context. 8074276479Sdim if (DVar.CKind == OMPC_unknown) { 8075276479Sdim DVar = DSAStack->getImplicitDSA(VD, false); 8076276479Sdim if (DVar.CKind == OMPC_shared) { 8077276479Sdim Diag(ELoc, diag::err_omp_required_access) 8078276479Sdim << getOpenMPClauseName(OMPC_copyprivate) 8079276479Sdim << "threadprivate or private in the enclosing context"; 8080276479Sdim ReportOriginalDSA(*this, DSAStack, VD, DVar); 8081276479Sdim continue; 8082276479Sdim } 8083276479Sdim } 8084276479Sdim } 8085276479Sdim 8086288943Sdim // Variably modified types are not supported. 8087288943Sdim if (!Type->isAnyPointerType() && Type->isVariablyModifiedType()) { 8088288943Sdim Diag(ELoc, diag::err_omp_variably_modified_type_not_supported) 8089288943Sdim << getOpenMPClauseName(OMPC_copyprivate) << Type 8090288943Sdim << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); 8091288943Sdim bool IsDecl = 8092288943Sdim VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; 8093288943Sdim Diag(VD->getLocation(), 8094288943Sdim IsDecl ? diag::note_previous_decl : diag::note_defined_here) 8095288943Sdim << VD; 8096288943Sdim continue; 8097288943Sdim } 8098288943Sdim 8099276479Sdim // OpenMP [2.14.4.1, Restrictions, C/C++, p.2] 8100276479Sdim // A variable of class type (or array thereof) that appears in a 8101276479Sdim // copyin clause requires an accessible, unambiguous copy assignment 8102276479Sdim // operator for the class type. 8103296417Sdim Type = Context.getBaseElementType(Type.getNonReferenceType()) 8104296417Sdim .getUnqualifiedType(); 8105288943Sdim auto *SrcVD = 8106296417Sdim buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.src", 8107296417Sdim VD->hasAttrs() ? &VD->getAttrs() : nullptr); 8108288943Sdim auto *PseudoSrcExpr = 8109288943Sdim buildDeclRefExpr(*this, SrcVD, Type, DE->getExprLoc()); 8110288943Sdim auto *DstVD = 8111296417Sdim buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.dst", 8112296417Sdim VD->hasAttrs() ? &VD->getAttrs() : nullptr); 8113288943Sdim auto *PseudoDstExpr = 8114288943Sdim buildDeclRefExpr(*this, DstVD, Type, DE->getExprLoc()); 8115288943Sdim auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, 8116288943Sdim PseudoDstExpr, PseudoSrcExpr); 8117288943Sdim if (AssignmentOp.isInvalid()) 8118288943Sdim continue; 8119288943Sdim AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(), 8120288943Sdim /*DiscardedValue=*/true); 8121288943Sdim if (AssignmentOp.isInvalid()) 8122288943Sdim continue; 8123276479Sdim 8124276479Sdim // No need to mark vars as copyprivate, they are already threadprivate or 8125276479Sdim // implicitly private. 8126276479Sdim Vars.push_back(DE); 8127288943Sdim SrcExprs.push_back(PseudoSrcExpr); 8128288943Sdim DstExprs.push_back(PseudoDstExpr); 8129288943Sdim AssignmentOps.push_back(AssignmentOp.get()); 8130276479Sdim } 8131276479Sdim 8132276479Sdim if (Vars.empty()) 8133276479Sdim return nullptr; 8134276479Sdim 8135288943Sdim return OMPCopyprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, 8136288943Sdim Vars, SrcExprs, DstExprs, AssignmentOps); 8137276479Sdim} 8138276479Sdim 8139276479SdimOMPClause *Sema::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList, 8140276479Sdim SourceLocation StartLoc, 8141276479Sdim SourceLocation LParenLoc, 8142276479Sdim SourceLocation EndLoc) { 8143276479Sdim if (VarList.empty()) 8144276479Sdim return nullptr; 8145276479Sdim 8146276479Sdim return OMPFlushClause::Create(Context, StartLoc, LParenLoc, EndLoc, VarList); 8147276479Sdim} 8148276479Sdim 8149288943SdimOMPClause * 8150288943SdimSema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, 8151288943Sdim SourceLocation DepLoc, SourceLocation ColonLoc, 8152288943Sdim ArrayRef<Expr *> VarList, SourceLocation StartLoc, 8153288943Sdim SourceLocation LParenLoc, SourceLocation EndLoc) { 8154296417Sdim if (DSAStack->getCurrentDirective() == OMPD_ordered && 8155296417Sdim DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) { 8156296417Sdim Diag(DepLoc, diag::err_omp_unexpected_clause_value) 8157296417Sdim << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend); 8158296417Sdim return nullptr; 8159296417Sdim } 8160296417Sdim if (DSAStack->getCurrentDirective() != OMPD_ordered && 8161296417Sdim (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source || 8162296417Sdim DepKind == OMPC_DEPEND_sink)) { 8163296417Sdim unsigned Except[] = {OMPC_DEPEND_source, OMPC_DEPEND_sink}; 8164296417Sdim Diag(DepLoc, diag::err_omp_unexpected_clause_value) 8165296417Sdim << getListOfPossibleValues(OMPC_depend, /*First=*/0, 8166296417Sdim /*Last=*/OMPC_DEPEND_unknown, Except) 8167296417Sdim << getOpenMPClauseName(OMPC_depend); 8168296417Sdim return nullptr; 8169296417Sdim } 8170296417Sdim SmallVector<Expr *, 8> Vars; 8171296417Sdim llvm::APSInt DepCounter(/*BitWidth=*/32); 8172296417Sdim llvm::APSInt TotalDepCount(/*BitWidth=*/32); 8173296417Sdim if (DepKind == OMPC_DEPEND_sink) { 8174296417Sdim if (auto *OrderedCountExpr = DSAStack->getParentOrderedRegionParam()) { 8175296417Sdim TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Context); 8176296417Sdim TotalDepCount.setIsUnsigned(/*Val=*/true); 8177296417Sdim } 8178296417Sdim } 8179296417Sdim if ((DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) || 8180296417Sdim DSAStack->getParentOrderedRegionParam()) { 8181296417Sdim for (auto &RefExpr : VarList) { 8182296417Sdim assert(RefExpr && "NULL expr in OpenMP shared clause."); 8183296417Sdim if (isa<DependentScopeDeclRefExpr>(RefExpr) || 8184296417Sdim (DepKind == OMPC_DEPEND_sink && CurContext->isDependentContext())) { 8185296417Sdim // It will be analyzed later. 8186296417Sdim Vars.push_back(RefExpr); 8187296417Sdim continue; 8188288943Sdim } 8189296417Sdim 8190296417Sdim SourceLocation ELoc = RefExpr->getExprLoc(); 8191296417Sdim auto *SimpleExpr = RefExpr->IgnoreParenCasts(); 8192296417Sdim if (DepKind == OMPC_DEPEND_sink) { 8193296417Sdim if (DepCounter >= TotalDepCount) { 8194296417Sdim Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr); 8195296417Sdim continue; 8196296417Sdim } 8197296417Sdim ++DepCounter; 8198296417Sdim // OpenMP [2.13.9, Summary] 8199296417Sdim // depend(dependence-type : vec), where dependence-type is: 8200296417Sdim // 'sink' and where vec is the iteration vector, which has the form: 8201296417Sdim // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn] 8202296417Sdim // where n is the value specified by the ordered clause in the loop 8203296417Sdim // directive, xi denotes the loop iteration variable of the i-th nested 8204296417Sdim // loop associated with the loop directive, and di is a constant 8205296417Sdim // non-negative integer. 8206296417Sdim SimpleExpr = SimpleExpr->IgnoreImplicit(); 8207296417Sdim auto *DE = dyn_cast<DeclRefExpr>(SimpleExpr); 8208296417Sdim if (!DE) { 8209296417Sdim OverloadedOperatorKind OOK = OO_None; 8210296417Sdim SourceLocation OOLoc; 8211296417Sdim Expr *LHS, *RHS; 8212296417Sdim if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) { 8213296417Sdim OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode()); 8214296417Sdim OOLoc = BO->getOperatorLoc(); 8215296417Sdim LHS = BO->getLHS()->IgnoreParenImpCasts(); 8216296417Sdim RHS = BO->getRHS()->IgnoreParenImpCasts(); 8217296417Sdim } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) { 8218296417Sdim OOK = OCE->getOperator(); 8219296417Sdim OOLoc = OCE->getOperatorLoc(); 8220296417Sdim LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 8221296417Sdim RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 8222296417Sdim } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) { 8223296417Sdim OOK = MCE->getMethodDecl() 8224296417Sdim ->getNameInfo() 8225296417Sdim .getName() 8226296417Sdim .getCXXOverloadedOperator(); 8227296417Sdim OOLoc = MCE->getCallee()->getExprLoc(); 8228296417Sdim LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts(); 8229296417Sdim RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 8230296417Sdim } else { 8231296417Sdim Diag(ELoc, diag::err_omp_depend_sink_wrong_expr); 8232296417Sdim continue; 8233296417Sdim } 8234296417Sdim DE = dyn_cast<DeclRefExpr>(LHS); 8235296417Sdim if (!DE) { 8236296417Sdim Diag(LHS->getExprLoc(), 8237296417Sdim diag::err_omp_depend_sink_expected_loop_iteration) 8238296417Sdim << DSAStack->getParentLoopControlVariable( 8239296417Sdim DepCounter.getZExtValue()); 8240296417Sdim continue; 8241296417Sdim } 8242296417Sdim if (OOK != OO_Plus && OOK != OO_Minus) { 8243296417Sdim Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus); 8244296417Sdim continue; 8245296417Sdim } 8246296417Sdim ExprResult Res = VerifyPositiveIntegerConstantInClause( 8247296417Sdim RHS, OMPC_depend, /*StrictlyPositive=*/false); 8248296417Sdim if (Res.isInvalid()) 8249296417Sdim continue; 8250296417Sdim } 8251296417Sdim auto *VD = dyn_cast<VarDecl>(DE->getDecl()); 8252296417Sdim if (!CurContext->isDependentContext() && 8253296417Sdim DSAStack->getParentOrderedRegionParam() && 8254296417Sdim (!VD || DepCounter != DSAStack->isParentLoopControlVariable(VD))) { 8255296417Sdim Diag(DE->getExprLoc(), 8256296417Sdim diag::err_omp_depend_sink_expected_loop_iteration) 8257296417Sdim << DSAStack->getParentLoopControlVariable( 8258296417Sdim DepCounter.getZExtValue()); 8259296417Sdim continue; 8260296417Sdim } 8261296417Sdim } else { 8262296417Sdim // OpenMP [2.11.1.1, Restrictions, p.3] 8263296417Sdim // A variable that is part of another variable (such as a field of a 8264296417Sdim // structure) but is not an array element or an array section cannot 8265296417Sdim // appear in a depend clause. 8266296417Sdim auto *DE = dyn_cast<DeclRefExpr>(SimpleExpr); 8267296417Sdim auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr); 8268296417Sdim auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr); 8269296417Sdim if (!RefExpr->IgnoreParenImpCasts()->isLValue() || 8270296417Sdim (!ASE && !DE && !OASE) || (DE && !isa<VarDecl>(DE->getDecl())) || 8271296417Sdim (ASE && !ASE->getBase()->getType()->isAnyPointerType() && 8272296417Sdim !ASE->getBase()->getType()->isArrayType())) { 8273296417Sdim Diag(ELoc, diag::err_omp_expected_var_name_or_array_item) 8274296417Sdim << RefExpr->getSourceRange(); 8275296417Sdim continue; 8276296417Sdim } 8277296417Sdim } 8278296417Sdim 8279296417Sdim Vars.push_back(RefExpr->IgnoreParenImpCasts()); 8280288943Sdim } 8281296417Sdim 8282296417Sdim if (!CurContext->isDependentContext() && DepKind == OMPC_DEPEND_sink && 8283296417Sdim TotalDepCount > VarList.size() && 8284296417Sdim DSAStack->getParentOrderedRegionParam()) { 8285296417Sdim Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration) 8286296417Sdim << DSAStack->getParentLoopControlVariable(VarList.size() + 1); 8287296417Sdim } 8288296417Sdim if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink && 8289296417Sdim Vars.empty()) 8290296417Sdim return nullptr; 8291296417Sdim } 8292296417Sdim 8293296417Sdim return OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc, DepKind, 8294296417Sdim DepLoc, ColonLoc, Vars); 8295296417Sdim} 8296296417Sdim 8297296417SdimOMPClause *Sema::ActOnOpenMPDeviceClause(Expr *Device, SourceLocation StartLoc, 8298296417Sdim SourceLocation LParenLoc, 8299296417Sdim SourceLocation EndLoc) { 8300296417Sdim Expr *ValExpr = Device; 8301296417Sdim 8302296417Sdim // OpenMP [2.9.1, Restrictions] 8303296417Sdim // The device expression must evaluate to a non-negative integer value. 8304296417Sdim if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_device, 8305296417Sdim /*StrictlyPositive=*/false)) 8306288943Sdim return nullptr; 8307296417Sdim 8308296417Sdim return new (Context) OMPDeviceClause(ValExpr, StartLoc, LParenLoc, EndLoc); 8309296417Sdim} 8310296417Sdim 8311296417Sdimstatic bool IsCXXRecordForMappable(Sema &SemaRef, SourceLocation Loc, 8312296417Sdim DSAStackTy *Stack, CXXRecordDecl *RD) { 8313296417Sdim if (!RD || RD->isInvalidDecl()) 8314296417Sdim return true; 8315296417Sdim 8316296417Sdim if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) 8317296417Sdim if (auto *CTD = CTSD->getSpecializedTemplate()) 8318296417Sdim RD = CTD->getTemplatedDecl(); 8319296417Sdim auto QTy = SemaRef.Context.getRecordType(RD); 8320296417Sdim if (RD->isDynamicClass()) { 8321296417Sdim SemaRef.Diag(Loc, diag::err_omp_not_mappable_type) << QTy; 8322296417Sdim SemaRef.Diag(RD->getLocation(), diag::note_omp_polymorphic_in_target); 8323296417Sdim return false; 8324288943Sdim } 8325296417Sdim auto *DC = RD; 8326296417Sdim bool IsCorrect = true; 8327296417Sdim for (auto *I : DC->decls()) { 8328296417Sdim if (I) { 8329296417Sdim if (auto *MD = dyn_cast<CXXMethodDecl>(I)) { 8330296417Sdim if (MD->isStatic()) { 8331296417Sdim SemaRef.Diag(Loc, diag::err_omp_not_mappable_type) << QTy; 8332296417Sdim SemaRef.Diag(MD->getLocation(), 8333296417Sdim diag::note_omp_static_member_in_target); 8334296417Sdim IsCorrect = false; 8335296417Sdim } 8336296417Sdim } else if (auto *VD = dyn_cast<VarDecl>(I)) { 8337296417Sdim if (VD->isStaticDataMember()) { 8338296417Sdim SemaRef.Diag(Loc, diag::err_omp_not_mappable_type) << QTy; 8339296417Sdim SemaRef.Diag(VD->getLocation(), 8340296417Sdim diag::note_omp_static_member_in_target); 8341296417Sdim IsCorrect = false; 8342296417Sdim } 8343296417Sdim } 8344296417Sdim } 8345296417Sdim } 8346296417Sdim 8347296417Sdim for (auto &I : RD->bases()) { 8348296417Sdim if (!IsCXXRecordForMappable(SemaRef, I.getLocStart(), Stack, 8349296417Sdim I.getType()->getAsCXXRecordDecl())) 8350296417Sdim IsCorrect = false; 8351296417Sdim } 8352296417Sdim return IsCorrect; 8353296417Sdim} 8354296417Sdim 8355296417Sdimstatic bool CheckTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef, 8356296417Sdim DSAStackTy *Stack, QualType QTy) { 8357296417Sdim NamedDecl *ND; 8358296417Sdim if (QTy->isIncompleteType(&ND)) { 8359296417Sdim SemaRef.Diag(SL, diag::err_incomplete_type) << QTy << SR; 8360296417Sdim return false; 8361296417Sdim } else if (CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(ND)) { 8362296417Sdim if (!RD->isInvalidDecl() && 8363296417Sdim !IsCXXRecordForMappable(SemaRef, SL, Stack, RD)) 8364296417Sdim return false; 8365296417Sdim } 8366296417Sdim return true; 8367296417Sdim} 8368296417Sdim 8369296417SdimOMPClause *Sema::ActOnOpenMPMapClause( 8370296417Sdim OpenMPMapClauseKind MapTypeModifier, OpenMPMapClauseKind MapType, 8371296417Sdim SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList, 8372296417Sdim SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { 8373296417Sdim SmallVector<Expr *, 4> Vars; 8374296417Sdim 8375296417Sdim for (auto &RE : VarList) { 8376296417Sdim assert(RE && "Null expr in omp map"); 8377296417Sdim if (isa<DependentScopeDeclRefExpr>(RE)) { 8378288943Sdim // It will be analyzed later. 8379296417Sdim Vars.push_back(RE); 8380288943Sdim continue; 8381288943Sdim } 8382296417Sdim SourceLocation ELoc = RE->getExprLoc(); 8383288943Sdim 8384296417Sdim // OpenMP [2.14.5, Restrictions] 8385296417Sdim // A variable that is part of another variable (such as field of a 8386288943Sdim // structure) but is not an array element or an array section cannot appear 8387296417Sdim // in a map clause. 8388296417Sdim auto *VE = RE->IgnoreParenLValueCasts(); 8389296417Sdim 8390296417Sdim if (VE->isValueDependent() || VE->isTypeDependent() || 8391296417Sdim VE->isInstantiationDependent() || 8392296417Sdim VE->containsUnexpandedParameterPack()) { 8393296417Sdim // It will be analyzed later. 8394296417Sdim Vars.push_back(RE); 8395296417Sdim continue; 8396296417Sdim } 8397296417Sdim 8398296417Sdim auto *SimpleExpr = RE->IgnoreParenCasts(); 8399296417Sdim auto *DE = dyn_cast<DeclRefExpr>(SimpleExpr); 8400296417Sdim auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr); 8401296417Sdim auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr); 8402296417Sdim 8403296417Sdim if (!RE->IgnoreParenImpCasts()->isLValue() || 8404296417Sdim (!OASE && !ASE && !DE) || 8405288943Sdim (DE && !isa<VarDecl>(DE->getDecl())) || 8406288943Sdim (ASE && !ASE->getBase()->getType()->isAnyPointerType() && 8407288943Sdim !ASE->getBase()->getType()->isArrayType())) { 8408288943Sdim Diag(ELoc, diag::err_omp_expected_var_name_or_array_item) 8409296417Sdim << RE->getSourceRange(); 8410288943Sdim continue; 8411288943Sdim } 8412288943Sdim 8413296417Sdim Decl *D = nullptr; 8414296417Sdim if (DE) { 8415296417Sdim D = DE->getDecl(); 8416296417Sdim } else if (ASE) { 8417296417Sdim auto *B = ASE->getBase()->IgnoreParenCasts(); 8418296417Sdim D = dyn_cast<DeclRefExpr>(B)->getDecl(); 8419296417Sdim } else if (OASE) { 8420296417Sdim auto *B = OASE->getBase(); 8421296417Sdim D = dyn_cast<DeclRefExpr>(B)->getDecl(); 8422296417Sdim } 8423296417Sdim assert(D && "Null decl on map clause."); 8424296417Sdim auto *VD = cast<VarDecl>(D); 8425296417Sdim 8426296417Sdim // OpenMP [2.14.5, Restrictions, p.8] 8427296417Sdim // threadprivate variables cannot appear in a map clause. 8428296417Sdim if (DSAStack->isThreadPrivate(VD)) { 8429296417Sdim auto DVar = DSAStack->getTopDSA(VD, false); 8430296417Sdim Diag(ELoc, diag::err_omp_threadprivate_in_map); 8431296417Sdim ReportOriginalDSA(*this, DSAStack, VD, DVar); 8432296417Sdim continue; 8433296417Sdim } 8434296417Sdim 8435296417Sdim // OpenMP [2.14.5, Restrictions, p.2] 8436296417Sdim // At most one list item can be an array item derived from a given variable 8437296417Sdim // in map clauses of the same construct. 8438296417Sdim // OpenMP [2.14.5, Restrictions, p.3] 8439296417Sdim // List items of map clauses in the same construct must not share original 8440296417Sdim // storage. 8441296417Sdim // OpenMP [2.14.5, Restrictions, C/C++, p.2] 8442296417Sdim // A variable for which the type is pointer, reference to array, or 8443296417Sdim // reference to pointer and an array section derived from that variable 8444296417Sdim // must not appear as list items of map clauses of the same construct. 8445296417Sdim DSAStackTy::MapInfo MI = DSAStack->IsMappedInCurrentRegion(VD); 8446296417Sdim if (MI.RefExpr) { 8447296417Sdim Diag(ELoc, diag::err_omp_map_shared_storage) << ELoc; 8448296417Sdim Diag(MI.RefExpr->getExprLoc(), diag::note_used_here) 8449296417Sdim << MI.RefExpr->getSourceRange(); 8450296417Sdim continue; 8451296417Sdim } 8452296417Sdim 8453296417Sdim // OpenMP [2.14.5, Restrictions, C/C++, p.3,4] 8454296417Sdim // A variable for which the type is pointer, reference to array, or 8455296417Sdim // reference to pointer must not appear as a list item if the enclosing 8456296417Sdim // device data environment already contains an array section derived from 8457296417Sdim // that variable. 8458296417Sdim // An array section derived from a variable for which the type is pointer, 8459296417Sdim // reference to array, or reference to pointer must not appear as a list 8460296417Sdim // item if the enclosing device data environment already contains that 8461296417Sdim // variable. 8462296417Sdim QualType Type = VD->getType(); 8463296417Sdim MI = DSAStack->getMapInfoForVar(VD); 8464296417Sdim if (MI.RefExpr && (isa<DeclRefExpr>(MI.RefExpr->IgnoreParenLValueCasts()) != 8465296417Sdim isa<DeclRefExpr>(VE)) && 8466296417Sdim (Type->isPointerType() || Type->isReferenceType())) { 8467296417Sdim Diag(ELoc, diag::err_omp_map_shared_storage) << ELoc; 8468296417Sdim Diag(MI.RefExpr->getExprLoc(), diag::note_used_here) 8469296417Sdim << MI.RefExpr->getSourceRange(); 8470296417Sdim continue; 8471296417Sdim } 8472296417Sdim 8473296417Sdim // OpenMP [2.14.5, Restrictions, C/C++, p.7] 8474296417Sdim // A list item must have a mappable type. 8475296417Sdim if (!CheckTypeMappable(VE->getExprLoc(), VE->getSourceRange(), *this, 8476296417Sdim DSAStack, Type)) 8477296417Sdim continue; 8478296417Sdim 8479296417Sdim Vars.push_back(RE); 8480296417Sdim MI.RefExpr = RE; 8481296417Sdim DSAStack->addMapInfoForVar(VD, MI); 8482288943Sdim } 8483288943Sdim if (Vars.empty()) 8484288943Sdim return nullptr; 8485288943Sdim 8486296417Sdim return OMPMapClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars, 8487296417Sdim MapTypeModifier, MapType, MapLoc); 8488288943Sdim} 8489288943Sdim 8490296417SdimOMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams, 8491296417Sdim SourceLocation StartLoc, 8492296417Sdim SourceLocation LParenLoc, 8493296417Sdim SourceLocation EndLoc) { 8494296417Sdim Expr *ValExpr = NumTeams; 8495296417Sdim 8496296417Sdim // OpenMP [teams Constrcut, Restrictions] 8497296417Sdim // The num_teams expression must evaluate to a positive integer value. 8498296417Sdim if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_num_teams, 8499296417Sdim /*StrictlyPositive=*/true)) 8500296417Sdim return nullptr; 8501296417Sdim 8502296417Sdim return new (Context) OMPNumTeamsClause(ValExpr, StartLoc, LParenLoc, EndLoc); 8503296417Sdim} 8504296417Sdim 8505296417SdimOMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit, 8506296417Sdim SourceLocation StartLoc, 8507296417Sdim SourceLocation LParenLoc, 8508296417Sdim SourceLocation EndLoc) { 8509296417Sdim Expr *ValExpr = ThreadLimit; 8510296417Sdim 8511296417Sdim // OpenMP [teams Constrcut, Restrictions] 8512296417Sdim // The thread_limit expression must evaluate to a positive integer value. 8513296417Sdim if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_thread_limit, 8514296417Sdim /*StrictlyPositive=*/true)) 8515296417Sdim return nullptr; 8516296417Sdim 8517296417Sdim return new (Context) OMPThreadLimitClause(ValExpr, StartLoc, LParenLoc, 8518296417Sdim EndLoc); 8519296417Sdim} 8520296417Sdim 8521296417SdimOMPClause *Sema::ActOnOpenMPPriorityClause(Expr *Priority, 8522296417Sdim SourceLocation StartLoc, 8523296417Sdim SourceLocation LParenLoc, 8524296417Sdim SourceLocation EndLoc) { 8525296417Sdim Expr *ValExpr = Priority; 8526296417Sdim 8527296417Sdim // OpenMP [2.9.1, task Constrcut] 8528296417Sdim // The priority-value is a non-negative numerical scalar expression. 8529296417Sdim if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_priority, 8530296417Sdim /*StrictlyPositive=*/false)) 8531296417Sdim return nullptr; 8532296417Sdim 8533296417Sdim return new (Context) OMPPriorityClause(ValExpr, StartLoc, LParenLoc, EndLoc); 8534296417Sdim} 8535296417Sdim 8536296417SdimOMPClause *Sema::ActOnOpenMPGrainsizeClause(Expr *Grainsize, 8537296417Sdim SourceLocation StartLoc, 8538296417Sdim SourceLocation LParenLoc, 8539296417Sdim SourceLocation EndLoc) { 8540296417Sdim Expr *ValExpr = Grainsize; 8541296417Sdim 8542296417Sdim // OpenMP [2.9.2, taskloop Constrcut] 8543296417Sdim // The parameter of the grainsize clause must be a positive integer 8544296417Sdim // expression. 8545296417Sdim if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_grainsize, 8546296417Sdim /*StrictlyPositive=*/true)) 8547296417Sdim return nullptr; 8548296417Sdim 8549296417Sdim return new (Context) OMPGrainsizeClause(ValExpr, StartLoc, LParenLoc, EndLoc); 8550296417Sdim} 8551296417Sdim 8552296417SdimOMPClause *Sema::ActOnOpenMPNumTasksClause(Expr *NumTasks, 8553296417Sdim SourceLocation StartLoc, 8554296417Sdim SourceLocation LParenLoc, 8555296417Sdim SourceLocation EndLoc) { 8556296417Sdim Expr *ValExpr = NumTasks; 8557296417Sdim 8558296417Sdim // OpenMP [2.9.2, taskloop Constrcut] 8559296417Sdim // The parameter of the num_tasks clause must be a positive integer 8560296417Sdim // expression. 8561296417Sdim if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_num_tasks, 8562296417Sdim /*StrictlyPositive=*/true)) 8563296417Sdim return nullptr; 8564296417Sdim 8565296417Sdim return new (Context) OMPNumTasksClause(ValExpr, StartLoc, LParenLoc, EndLoc); 8566296417Sdim} 8567296417Sdim 8568296417SdimOMPClause *Sema::ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc, 8569296417Sdim SourceLocation LParenLoc, 8570296417Sdim SourceLocation EndLoc) { 8571296417Sdim // OpenMP [2.13.2, critical construct, Description] 8572296417Sdim // ... where hint-expression is an integer constant expression that evaluates 8573296417Sdim // to a valid lock hint. 8574296417Sdim ExprResult HintExpr = VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint); 8575296417Sdim if (HintExpr.isInvalid()) 8576296417Sdim return nullptr; 8577296417Sdim return new (Context) 8578296417Sdim OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc); 8579296417Sdim} 8580296417Sdim 8581