xref: /freebsd/contrib/llvm-project/clang/lib/Sema/SemaOpenMP.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ---------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 /// This file implements semantic analysis for OpenMP directives and
10 /// clauses.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/Sema/SemaOpenMP.h"
15 
16 #include "TreeTransform.h"
17 #include "clang/AST/ASTContext.h"
18 #include "clang/AST/ASTMutationListener.h"
19 #include "clang/AST/CXXInheritance.h"
20 #include "clang/AST/Decl.h"
21 #include "clang/AST/DeclCXX.h"
22 #include "clang/AST/DeclOpenMP.h"
23 #include "clang/AST/DynamicRecursiveASTVisitor.h"
24 #include "clang/AST/OpenMPClause.h"
25 #include "clang/AST/StmtCXX.h"
26 #include "clang/AST/StmtOpenMP.h"
27 #include "clang/AST/StmtVisitor.h"
28 #include "clang/Basic/DiagnosticSema.h"
29 #include "clang/Basic/OpenMPKinds.h"
30 #include "clang/Basic/PartialDiagnostic.h"
31 #include "clang/Basic/TargetInfo.h"
32 #include "clang/Sema/EnterExpressionEvaluationContext.h"
33 #include "clang/Sema/Initialization.h"
34 #include "clang/Sema/Lookup.h"
35 #include "clang/Sema/ParsedAttr.h"
36 #include "clang/Sema/Scope.h"
37 #include "clang/Sema/ScopeInfo.h"
38 #include "clang/Sema/Sema.h"
39 #include "llvm/ADT/IndexedMap.h"
40 #include "llvm/ADT/PointerEmbeddedInt.h"
41 #include "llvm/ADT/STLExtras.h"
42 #include "llvm/ADT/Sequence.h"
43 #include "llvm/ADT/SetVector.h"
44 #include "llvm/ADT/SmallSet.h"
45 #include "llvm/ADT/StringExtras.h"
46 #include "llvm/Frontend/OpenMP/OMPAssume.h"
47 #include "llvm/Frontend/OpenMP/OMPConstants.h"
48 #include "llvm/IR/Assumptions.h"
49 #include <optional>
50 
51 using namespace clang;
52 using namespace llvm::omp;
53 
54 //===----------------------------------------------------------------------===//
55 // Stack of data-sharing attributes for variables
56 //===----------------------------------------------------------------------===//
57 
58 static const Expr *checkMapClauseExpressionBase(
59     Sema &SemaRef, Expr *E,
60     OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
61     OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
62 
63 static std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C);
64 
65 namespace {
66 /// Default data sharing attributes, which can be applied to directive.
67 enum DefaultDataSharingAttributes {
68   DSA_unspecified = 0,       /// Data sharing attribute not specified.
69   DSA_none = 1 << 0,         /// Default data sharing attribute 'none'.
70   DSA_shared = 1 << 1,       /// Default data sharing attribute 'shared'.
71   DSA_private = 1 << 2,      /// Default data sharing attribute 'private'.
72   DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
73 };
74 
75 /// Stack for tracking declarations used in OpenMP directives and
76 /// clauses and their data-sharing attributes.
77 class DSAStackTy {
78 public:
79   struct DSAVarData {
80     OpenMPDirectiveKind DKind = OMPD_unknown;
81     OpenMPClauseKind CKind = OMPC_unknown;
82     unsigned Modifier = 0;
83     const Expr *RefExpr = nullptr;
84     DeclRefExpr *PrivateCopy = nullptr;
85     SourceLocation ImplicitDSALoc;
86     bool AppliedToPointee = false;
87     DSAVarData() = default;
DSAVarData__anon1dd12e440111::DSAStackTy::DSAVarData88     DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
89                const Expr *RefExpr, DeclRefExpr *PrivateCopy,
90                SourceLocation ImplicitDSALoc, unsigned Modifier,
91                bool AppliedToPointee)
92         : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
93           PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
94           AppliedToPointee(AppliedToPointee) {}
95   };
96   using OperatorOffsetTy =
97       llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
98   using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
99   /// Kind of the declaration used in the uses_allocators clauses.
100   enum class UsesAllocatorsDeclKind {
101     /// Predefined allocator
102     PredefinedAllocator,
103     /// User-defined allocator
104     UserDefinedAllocator,
105     /// The declaration that represent allocator trait
106     AllocatorTrait,
107   };
108 
109 private:
110   struct DSAInfo {
111     OpenMPClauseKind Attributes = OMPC_unknown;
112     unsigned Modifier = 0;
113     /// Pointer to a reference expression and a flag which shows that the
114     /// variable is marked as lastprivate(true) or not (false).
115     llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
116     DeclRefExpr *PrivateCopy = nullptr;
117     /// true if the attribute is applied to the pointee, not the variable
118     /// itself.
119     bool AppliedToPointee = false;
120   };
121   using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
122   using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
123   using LCDeclInfo = std::pair<unsigned, VarDecl *>;
124   using LoopControlVariablesMapTy =
125       llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
126   /// Struct that associates a component with the clause kind where they are
127   /// found.
128   struct MappedExprComponentTy {
129     OMPClauseMappableExprCommon::MappableExprComponentLists Components;
130     OpenMPClauseKind Kind = OMPC_unknown;
131   };
132   using MappedExprComponentsTy =
133       llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
134   using CriticalsWithHintsTy =
135       llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
136   struct ReductionData {
137     using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
138     SourceRange ReductionRange;
139     llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
140     ReductionData() = default;
set__anon1dd12e440111::DSAStackTy::ReductionData141     void set(BinaryOperatorKind BO, SourceRange RR) {
142       ReductionRange = RR;
143       ReductionOp = BO;
144     }
set__anon1dd12e440111::DSAStackTy::ReductionData145     void set(const Expr *RefExpr, SourceRange RR) {
146       ReductionRange = RR;
147       ReductionOp = RefExpr;
148     }
149   };
150   using DeclReductionMapTy =
151       llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
152   struct DefaultmapInfo {
153     OpenMPDefaultmapClauseModifier ImplicitBehavior =
154         OMPC_DEFAULTMAP_MODIFIER_unknown;
155     SourceLocation SLoc;
156     DefaultmapInfo() = default;
DefaultmapInfo__anon1dd12e440111::DSAStackTy::DefaultmapInfo157     DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc)
158         : ImplicitBehavior(M), SLoc(Loc) {}
159   };
160 
161   struct SharingMapTy {
162     DeclSAMapTy SharingMap;
163     DeclReductionMapTy ReductionMap;
164     UsedRefMapTy AlignedMap;
165     UsedRefMapTy NontemporalMap;
166     MappedExprComponentsTy MappedExprComponents;
167     LoopControlVariablesMapTy LCVMap;
168     DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
169     SourceLocation DefaultAttrLoc;
170     DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1];
171     OpenMPDirectiveKind Directive = OMPD_unknown;
172     DeclarationNameInfo DirectiveName;
173     Scope *CurScope = nullptr;
174     DeclContext *Context = nullptr;
175     SourceLocation ConstructLoc;
176     /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
177     /// get the data (loop counters etc.) about enclosing loop-based construct.
178     /// This data is required during codegen.
179     DoacrossClauseMapTy DoacrossDepends;
180     /// First argument (Expr *) contains optional argument of the
181     /// 'ordered' clause, the second one is true if the regions has 'ordered'
182     /// clause, false otherwise.
183     std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
184     bool RegionHasOrderConcurrent = false;
185     unsigned AssociatedLoops = 1;
186     bool HasMutipleLoops = false;
187     const Decl *PossiblyLoopCounter = nullptr;
188     bool NowaitRegion = false;
189     bool UntiedRegion = false;
190     bool CancelRegion = false;
191     bool LoopStart = false;
192     bool BodyComplete = false;
193     SourceLocation PrevScanLocation;
194     SourceLocation PrevOrderedLocation;
195     SourceLocation InnerTeamsRegionLoc;
196     /// Reference to the taskgroup task_reduction reference expression.
197     Expr *TaskgroupReductionRef = nullptr;
198     llvm::DenseSet<QualType> MappedClassesQualTypes;
199     SmallVector<Expr *, 4> InnerUsedAllocators;
200     llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
201     /// List of globals marked as declare target link in this target region
202     /// (isOpenMPTargetExecutionDirective(Directive) == true).
203     llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
204     /// List of decls used in inclusive/exclusive clauses of the scan directive.
205     llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
206     llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
207         UsesAllocatorsDecls;
208     /// Data is required on creating capture fields for implicit
209     /// default first|private clause.
210     struct ImplicitDefaultFDInfoTy {
211       /// Field decl.
212       const FieldDecl *FD = nullptr;
213       /// Nesting stack level
214       size_t StackLevel = 0;
215       /// Capture variable decl.
216       VarDecl *VD = nullptr;
ImplicitDefaultFDInfoTy__anon1dd12e440111::DSAStackTy::SharingMapTy::ImplicitDefaultFDInfoTy217       ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
218                               VarDecl *VD)
219           : FD(FD), StackLevel(StackLevel), VD(VD) {}
220     };
221     /// List of captured fields
222     llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
223         ImplicitDefaultFirstprivateFDs;
224     Expr *DeclareMapperVar = nullptr;
225     SmallVector<VarDecl *, 16> IteratorVarDecls;
SharingMapTy__anon1dd12e440111::DSAStackTy::SharingMapTy226     SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
227                  Scope *CurScope, SourceLocation Loc)
228         : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
229           ConstructLoc(Loc) {}
230     SharingMapTy() = default;
231   };
232 
233   using StackTy = SmallVector<SharingMapTy, 4>;
234 
235   /// Stack of used declaration and their data-sharing attributes.
236   DeclSAMapTy Threadprivates;
237   const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
238   SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
239   /// true, if check for DSA must be from parent directive, false, if
240   /// from current directive.
241   OpenMPClauseKind ClauseKindMode = OMPC_unknown;
242   Sema &SemaRef;
243   bool ForceCapturing = false;
244   /// true if all the variables in the target executable directives must be
245   /// captured by reference.
246   bool ForceCaptureByReferenceInTargetExecutable = false;
247   CriticalsWithHintsTy Criticals;
248   unsigned IgnoredStackElements = 0;
249 
250   /// Iterators over the stack iterate in order from innermost to outermost
251   /// directive.
252   using const_iterator = StackTy::const_reverse_iterator;
begin() const253   const_iterator begin() const {
254     return Stack.empty() ? const_iterator()
255                          : Stack.back().first.rbegin() + IgnoredStackElements;
256   }
end() const257   const_iterator end() const {
258     return Stack.empty() ? const_iterator() : Stack.back().first.rend();
259   }
260   using iterator = StackTy::reverse_iterator;
begin()261   iterator begin() {
262     return Stack.empty() ? iterator()
263                          : Stack.back().first.rbegin() + IgnoredStackElements;
264   }
end()265   iterator end() {
266     return Stack.empty() ? iterator() : Stack.back().first.rend();
267   }
268 
269   // Convenience operations to get at the elements of the stack.
270 
isStackEmpty() const271   bool isStackEmpty() const {
272     return Stack.empty() ||
273            Stack.back().second != CurrentNonCapturingFunctionScope ||
274            Stack.back().first.size() <= IgnoredStackElements;
275   }
getStackSize() const276   size_t getStackSize() const {
277     return isStackEmpty() ? 0
278                           : Stack.back().first.size() - IgnoredStackElements;
279   }
280 
getTopOfStackOrNull()281   SharingMapTy *getTopOfStackOrNull() {
282     size_t Size = getStackSize();
283     if (Size == 0)
284       return nullptr;
285     return &Stack.back().first[Size - 1];
286   }
getTopOfStackOrNull() const287   const SharingMapTy *getTopOfStackOrNull() const {
288     return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
289   }
getTopOfStack()290   SharingMapTy &getTopOfStack() {
291     assert(!isStackEmpty() && "no current directive");
292     return *getTopOfStackOrNull();
293   }
getTopOfStack() const294   const SharingMapTy &getTopOfStack() const {
295     return const_cast<DSAStackTy &>(*this).getTopOfStack();
296   }
297 
getSecondOnStackOrNull()298   SharingMapTy *getSecondOnStackOrNull() {
299     size_t Size = getStackSize();
300     if (Size <= 1)
301       return nullptr;
302     return &Stack.back().first[Size - 2];
303   }
getSecondOnStackOrNull() const304   const SharingMapTy *getSecondOnStackOrNull() const {
305     return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
306   }
307 
308   /// Get the stack element at a certain level (previously returned by
309   /// \c getNestingLevel).
310   ///
311   /// Note that nesting levels count from outermost to innermost, and this is
312   /// the reverse of our iteration order where new inner levels are pushed at
313   /// the front of the stack.
getStackElemAtLevel(unsigned Level)314   SharingMapTy &getStackElemAtLevel(unsigned Level) {
315     assert(Level < getStackSize() && "no such stack element");
316     return Stack.back().first[Level];
317   }
getStackElemAtLevel(unsigned Level) const318   const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
319     return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
320   }
321 
322   DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
323 
324   /// Checks if the variable is a local for OpenMP region.
325   bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
326 
327   /// Vector of previously declared requires directives
328   SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
329   /// omp_allocator_handle_t type.
330   QualType OMPAllocatorHandleT;
331   /// omp_depend_t type.
332   QualType OMPDependT;
333   /// omp_event_handle_t type.
334   QualType OMPEventHandleT;
335   /// omp_alloctrait_t type.
336   QualType OMPAlloctraitT;
337   /// Expression for the predefined allocators.
338   Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
339       nullptr};
340   /// Vector of previously encountered target directives
341   SmallVector<SourceLocation, 2> TargetLocations;
342   SourceLocation AtomicLocation;
343   /// Vector of declare variant construct traits.
344   SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
345 
346 public:
DSAStackTy(Sema & S)347   explicit DSAStackTy(Sema &S) : SemaRef(S) {}
348 
349   /// Sets omp_allocator_handle_t type.
setOMPAllocatorHandleT(QualType Ty)350   void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
351   /// Gets omp_allocator_handle_t type.
getOMPAllocatorHandleT() const352   QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
353   /// Sets omp_alloctrait_t type.
setOMPAlloctraitT(QualType Ty)354   void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
355   /// Gets omp_alloctrait_t type.
getOMPAlloctraitT() const356   QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
357   /// Sets the given default allocator.
setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,Expr * Allocator)358   void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
359                     Expr *Allocator) {
360     OMPPredefinedAllocators[AllocatorKind] = Allocator;
361   }
362   /// Returns the specified default allocator.
getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const363   Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
364     return OMPPredefinedAllocators[AllocatorKind];
365   }
366   /// Sets omp_depend_t type.
setOMPDependT(QualType Ty)367   void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
368   /// Gets omp_depend_t type.
getOMPDependT() const369   QualType getOMPDependT() const { return OMPDependT; }
370 
371   /// Sets omp_event_handle_t type.
setOMPEventHandleT(QualType Ty)372   void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
373   /// Gets omp_event_handle_t type.
getOMPEventHandleT() const374   QualType getOMPEventHandleT() const { return OMPEventHandleT; }
375 
isClauseParsingMode() const376   bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
getClauseParsingMode() const377   OpenMPClauseKind getClauseParsingMode() const {
378     assert(isClauseParsingMode() && "Must be in clause parsing mode.");
379     return ClauseKindMode;
380   }
setClauseParsingMode(OpenMPClauseKind K)381   void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
382 
isBodyComplete() const383   bool isBodyComplete() const {
384     const SharingMapTy *Top = getTopOfStackOrNull();
385     return Top && Top->BodyComplete;
386   }
setBodyComplete()387   void setBodyComplete() { getTopOfStack().BodyComplete = true; }
388 
isForceVarCapturing() const389   bool isForceVarCapturing() const { return ForceCapturing; }
setForceVarCapturing(bool V)390   void setForceVarCapturing(bool V) { ForceCapturing = V; }
391 
setForceCaptureByReferenceInTargetExecutable(bool V)392   void setForceCaptureByReferenceInTargetExecutable(bool V) {
393     ForceCaptureByReferenceInTargetExecutable = V;
394   }
isForceCaptureByReferenceInTargetExecutable() const395   bool isForceCaptureByReferenceInTargetExecutable() const {
396     return ForceCaptureByReferenceInTargetExecutable;
397   }
398 
push(OpenMPDirectiveKind DKind,const DeclarationNameInfo & DirName,Scope * CurScope,SourceLocation Loc)399   void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
400             Scope *CurScope, SourceLocation Loc) {
401     assert(!IgnoredStackElements &&
402            "cannot change stack while ignoring elements");
403     if (Stack.empty() ||
404         Stack.back().second != CurrentNonCapturingFunctionScope)
405       Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
406     Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
407     Stack.back().first.back().DefaultAttrLoc = Loc;
408   }
409 
pop()410   void pop() {
411     assert(!IgnoredStackElements &&
412            "cannot change stack while ignoring elements");
413     assert(!Stack.back().first.empty() &&
414            "Data-sharing attributes stack is empty!");
415     Stack.back().first.pop_back();
416   }
417 
418   /// RAII object to temporarily leave the scope of a directive when we want to
419   /// logically operate in its parent.
420   class ParentDirectiveScope {
421     DSAStackTy &Self;
422     bool Active;
423 
424   public:
ParentDirectiveScope(DSAStackTy & Self,bool Activate)425     ParentDirectiveScope(DSAStackTy &Self, bool Activate)
426         : Self(Self), Active(false) {
427       if (Activate)
428         enable();
429     }
~ParentDirectiveScope()430     ~ParentDirectiveScope() { disable(); }
disable()431     void disable() {
432       if (Active) {
433         --Self.IgnoredStackElements;
434         Active = false;
435       }
436     }
enable()437     void enable() {
438       if (!Active) {
439         ++Self.IgnoredStackElements;
440         Active = true;
441       }
442     }
443   };
444 
445   /// Marks that we're started loop parsing.
loopInit()446   void loopInit() {
447     assert(isOpenMPLoopDirective(getCurrentDirective()) &&
448            "Expected loop-based directive.");
449     getTopOfStack().LoopStart = true;
450   }
451   /// Start capturing of the variables in the loop context.
loopStart()452   void loopStart() {
453     assert(isOpenMPLoopDirective(getCurrentDirective()) &&
454            "Expected loop-based directive.");
455     getTopOfStack().LoopStart = false;
456   }
457   /// true, if variables are captured, false otherwise.
isLoopStarted() const458   bool isLoopStarted() const {
459     assert(isOpenMPLoopDirective(getCurrentDirective()) &&
460            "Expected loop-based directive.");
461     return !getTopOfStack().LoopStart;
462   }
463   /// Marks (or clears) declaration as possibly loop counter.
resetPossibleLoopCounter(const Decl * D=nullptr)464   void resetPossibleLoopCounter(const Decl *D = nullptr) {
465     getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
466   }
467   /// Gets the possible loop counter decl.
getPossiblyLoopCounter() const468   const Decl *getPossiblyLoopCounter() const {
469     return getTopOfStack().PossiblyLoopCounter;
470   }
471   /// Start new OpenMP region stack in new non-capturing function.
pushFunction()472   void pushFunction() {
473     assert(!IgnoredStackElements &&
474            "cannot change stack while ignoring elements");
475     const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
476     assert(!isa<CapturingScopeInfo>(CurFnScope));
477     CurrentNonCapturingFunctionScope = CurFnScope;
478   }
479   /// Pop region stack for non-capturing function.
popFunction(const FunctionScopeInfo * OldFSI)480   void popFunction(const FunctionScopeInfo *OldFSI) {
481     assert(!IgnoredStackElements &&
482            "cannot change stack while ignoring elements");
483     if (!Stack.empty() && Stack.back().second == OldFSI) {
484       assert(Stack.back().first.empty());
485       Stack.pop_back();
486     }
487     CurrentNonCapturingFunctionScope = nullptr;
488     for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
489       if (!isa<CapturingScopeInfo>(FSI)) {
490         CurrentNonCapturingFunctionScope = FSI;
491         break;
492       }
493     }
494   }
495 
addCriticalWithHint(const OMPCriticalDirective * D,llvm::APSInt Hint)496   void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
497     Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
498   }
499   std::pair<const OMPCriticalDirective *, llvm::APSInt>
getCriticalWithHint(const DeclarationNameInfo & Name) const500   getCriticalWithHint(const DeclarationNameInfo &Name) const {
501     auto I = Criticals.find(Name.getAsString());
502     if (I != Criticals.end())
503       return I->second;
504     return std::make_pair(nullptr, llvm::APSInt());
505   }
506   /// If 'aligned' declaration for given variable \a D was not seen yet,
507   /// add it and return NULL; otherwise return previous occurrence's expression
508   /// for diagnostics.
509   const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
510   /// If 'nontemporal' declaration for given variable \a D was not seen yet,
511   /// add it and return NULL; otherwise return previous occurrence's expression
512   /// for diagnostics.
513   const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
514 
515   /// Register specified variable as loop control variable.
516   void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
517   /// Check if the specified variable is a loop control variable for
518   /// current region.
519   /// \return The index of the loop control variable in the list of associated
520   /// for-loops (from outer to inner).
521   const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
522   /// Check if the specified variable is a loop control variable for
523   /// parent region.
524   /// \return The index of the loop control variable in the list of associated
525   /// for-loops (from outer to inner).
526   const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
527   /// Check if the specified variable is a loop control variable for
528   /// current region.
529   /// \return The index of the loop control variable in the list of associated
530   /// for-loops (from outer to inner).
531   const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
532                                          unsigned Level) const;
533   /// Get the loop control variable for the I-th loop (or nullptr) in
534   /// parent directive.
535   const ValueDecl *getParentLoopControlVariable(unsigned I) const;
536 
537   /// Marks the specified decl \p D as used in scan directive.
markDeclAsUsedInScanDirective(ValueDecl * D)538   void markDeclAsUsedInScanDirective(ValueDecl *D) {
539     if (SharingMapTy *Stack = getSecondOnStackOrNull())
540       Stack->UsedInScanDirective.insert(D);
541   }
542 
543   /// Checks if the specified declaration was used in the inner scan directive.
isUsedInScanDirective(ValueDecl * D) const544   bool isUsedInScanDirective(ValueDecl *D) const {
545     if (const SharingMapTy *Stack = getTopOfStackOrNull())
546       return Stack->UsedInScanDirective.contains(D);
547     return false;
548   }
549 
550   /// Adds explicit data sharing attribute to the specified declaration.
551   void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
552               DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
553               bool AppliedToPointee = false);
554 
555   /// Adds additional information for the reduction items with the reduction id
556   /// represented as an operator.
557   void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
558                                  BinaryOperatorKind BOK);
559   /// Adds additional information for the reduction items with the reduction id
560   /// represented as reduction identifier.
561   void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
562                                  const Expr *ReductionRef);
563   /// Returns the location and reduction operation from the innermost parent
564   /// region for the given \p D.
565   const DSAVarData
566   getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
567                                    BinaryOperatorKind &BOK,
568                                    Expr *&TaskgroupDescriptor) const;
569   /// Returns the location and reduction operation from the innermost parent
570   /// region for the given \p D.
571   const DSAVarData
572   getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
573                                    const Expr *&ReductionRef,
574                                    Expr *&TaskgroupDescriptor) const;
575   /// Return reduction reference expression for the current taskgroup or
576   /// parallel/worksharing directives with task reductions.
getTaskgroupReductionRef() const577   Expr *getTaskgroupReductionRef() const {
578     assert((getTopOfStack().Directive == OMPD_taskgroup ||
579             ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
580               isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
581              !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
582            "taskgroup reference expression requested for non taskgroup or "
583            "parallel/worksharing directive.");
584     return getTopOfStack().TaskgroupReductionRef;
585   }
586   /// Checks if the given \p VD declaration is actually a taskgroup reduction
587   /// descriptor variable at the \p Level of OpenMP regions.
isTaskgroupReductionRef(const ValueDecl * VD,unsigned Level) const588   bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
589     return getStackElemAtLevel(Level).TaskgroupReductionRef &&
590            cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
591                    ->getDecl() == VD;
592   }
593 
594   /// Returns data sharing attributes from top of the stack for the
595   /// specified declaration.
596   const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
597   /// Returns data-sharing attributes for the specified declaration.
598   const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
599   /// Returns data-sharing attributes for the specified declaration.
600   const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
601   /// Checks if the specified variables has data-sharing attributes which
602   /// match specified \a CPred predicate in any directive which matches \a DPred
603   /// predicate.
604   const DSAVarData
605   hasDSA(ValueDecl *D,
606          const llvm::function_ref<bool(OpenMPClauseKind, bool,
607                                        DefaultDataSharingAttributes)>
608              CPred,
609          const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
610          bool FromParent) const;
611   /// Checks if the specified variables has data-sharing attributes which
612   /// match specified \a CPred predicate in any innermost directive which
613   /// matches \a DPred predicate.
614   const DSAVarData
615   hasInnermostDSA(ValueDecl *D,
616                   const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
617                   const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
618                   bool FromParent) const;
619   /// Checks if the specified variables has explicit data-sharing
620   /// attributes which match specified \a CPred predicate at the specified
621   /// OpenMP region.
622   bool
623   hasExplicitDSA(const ValueDecl *D,
624                  const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
625                  unsigned Level, bool NotLastprivate = false) const;
626 
627   /// Returns true if the directive at level \Level matches in the
628   /// specified \a DPred predicate.
629   bool hasExplicitDirective(
630       const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
631       unsigned Level) const;
632 
633   /// Finds a directive which matches specified \a DPred predicate.
634   bool hasDirective(
635       const llvm::function_ref<bool(
636           OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)>
637           DPred,
638       bool FromParent) const;
639 
640   /// Returns currently analyzed directive.
getCurrentDirective() const641   OpenMPDirectiveKind getCurrentDirective() const {
642     const SharingMapTy *Top = getTopOfStackOrNull();
643     return Top ? Top->Directive : OMPD_unknown;
644   }
645   /// Returns directive kind at specified level.
getDirective(unsigned Level) const646   OpenMPDirectiveKind getDirective(unsigned Level) const {
647     assert(!isStackEmpty() && "No directive at specified level.");
648     return getStackElemAtLevel(Level).Directive;
649   }
650   /// Returns the capture region at the specified level.
getCaptureRegion(unsigned Level,unsigned OpenMPCaptureLevel) const651   OpenMPDirectiveKind getCaptureRegion(unsigned Level,
652                                        unsigned OpenMPCaptureLevel) const {
653     SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
654     getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
655     return CaptureRegions[OpenMPCaptureLevel];
656   }
657   /// Returns parent directive.
getParentDirective() const658   OpenMPDirectiveKind getParentDirective() const {
659     const SharingMapTy *Parent = getSecondOnStackOrNull();
660     return Parent ? Parent->Directive : OMPD_unknown;
661   }
662 
663   /// Add requires decl to internal vector
addRequiresDecl(OMPRequiresDecl * RD)664   void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
665 
666   /// Checks if the defined 'requires' directive has specified type of clause.
hasRequiresDeclWithClause() const667   template <typename ClauseType> bool hasRequiresDeclWithClause() const {
668     return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
669       return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
670         return isa<ClauseType>(C);
671       });
672     });
673   }
674 
675   /// Checks for a duplicate clause amongst previously declared requires
676   /// directives
hasDuplicateRequiresClause(ArrayRef<OMPClause * > ClauseList) const677   bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
678     bool IsDuplicate = false;
679     for (OMPClause *CNew : ClauseList) {
680       for (const OMPRequiresDecl *D : RequiresDecls) {
681         for (const OMPClause *CPrev : D->clauselists()) {
682           if (CNew->getClauseKind() == CPrev->getClauseKind()) {
683             SemaRef.Diag(CNew->getBeginLoc(),
684                          diag::err_omp_requires_clause_redeclaration)
685                 << getOpenMPClauseNameForDiag(CNew->getClauseKind());
686             SemaRef.Diag(CPrev->getBeginLoc(),
687                          diag::note_omp_requires_previous_clause)
688                 << getOpenMPClauseNameForDiag(CPrev->getClauseKind());
689             IsDuplicate = true;
690           }
691         }
692       }
693     }
694     return IsDuplicate;
695   }
696 
697   /// Add location of previously encountered target to internal vector
addTargetDirLocation(SourceLocation LocStart)698   void addTargetDirLocation(SourceLocation LocStart) {
699     TargetLocations.push_back(LocStart);
700   }
701 
702   /// Add location for the first encountered atomic directive.
addAtomicDirectiveLoc(SourceLocation Loc)703   void addAtomicDirectiveLoc(SourceLocation Loc) {
704     if (AtomicLocation.isInvalid())
705       AtomicLocation = Loc;
706   }
707 
708   /// Returns the location of the first encountered atomic directive in the
709   /// module.
getAtomicDirectiveLoc() const710   SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
711 
712   // Return previously encountered target region locations.
getEncounteredTargetLocs() const713   ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
714     return TargetLocations;
715   }
716 
717   /// Set default data sharing attribute to none.
setDefaultDSANone(SourceLocation Loc)718   void setDefaultDSANone(SourceLocation Loc) {
719     getTopOfStack().DefaultAttr = DSA_none;
720     getTopOfStack().DefaultAttrLoc = Loc;
721   }
722   /// Set default data sharing attribute to shared.
setDefaultDSAShared(SourceLocation Loc)723   void setDefaultDSAShared(SourceLocation Loc) {
724     getTopOfStack().DefaultAttr = DSA_shared;
725     getTopOfStack().DefaultAttrLoc = Loc;
726   }
727   /// Set default data sharing attribute to private.
setDefaultDSAPrivate(SourceLocation Loc)728   void setDefaultDSAPrivate(SourceLocation Loc) {
729     getTopOfStack().DefaultAttr = DSA_private;
730     getTopOfStack().DefaultAttrLoc = Loc;
731   }
732   /// Set default data sharing attribute to firstprivate.
setDefaultDSAFirstPrivate(SourceLocation Loc)733   void setDefaultDSAFirstPrivate(SourceLocation Loc) {
734     getTopOfStack().DefaultAttr = DSA_firstprivate;
735     getTopOfStack().DefaultAttrLoc = Loc;
736   }
737   /// Set default data mapping attribute to Modifier:Kind
setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,OpenMPDefaultmapClauseKind Kind,SourceLocation Loc)738   void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
739                          OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) {
740     DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
741     DMI.ImplicitBehavior = M;
742     DMI.SLoc = Loc;
743   }
744   /// Check whether the implicit-behavior has been set in defaultmap
checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory)745   bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
746     if (VariableCategory == OMPC_DEFAULTMAP_unknown)
747       return getTopOfStack()
748                      .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
749                      .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
750              getTopOfStack()
751                      .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
752                      .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
753              getTopOfStack()
754                      .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
755                      .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
756     return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
757            OMPC_DEFAULTMAP_MODIFIER_unknown;
758   }
759 
getConstructTraits()760   ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
761     return ConstructTraits;
762   }
handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,bool ScopeEntry)763   void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
764                             bool ScopeEntry) {
765     if (ScopeEntry)
766       ConstructTraits.append(Traits.begin(), Traits.end());
767     else
768       for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
769         llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
770         assert(Top == Trait && "Something left a trait on the stack!");
771         (void)Trait;
772         (void)Top;
773       }
774   }
775 
getDefaultDSA(unsigned Level) const776   DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
777     return getStackSize() <= Level ? DSA_unspecified
778                                    : getStackElemAtLevel(Level).DefaultAttr;
779   }
getDefaultDSA() const780   DefaultDataSharingAttributes getDefaultDSA() const {
781     return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
782   }
getDefaultDSALocation() const783   SourceLocation getDefaultDSALocation() const {
784     return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
785   }
786   OpenMPDefaultmapClauseModifier
getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const787   getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
788     return isStackEmpty()
789                ? OMPC_DEFAULTMAP_MODIFIER_unknown
790                : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
791   }
792   OpenMPDefaultmapClauseModifier
getDefaultmapModifierAtLevel(unsigned Level,OpenMPDefaultmapClauseKind Kind) const793   getDefaultmapModifierAtLevel(unsigned Level,
794                                OpenMPDefaultmapClauseKind Kind) const {
795     return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
796   }
isDefaultmapCapturedByRef(unsigned Level,OpenMPDefaultmapClauseKind Kind) const797   bool isDefaultmapCapturedByRef(unsigned Level,
798                                  OpenMPDefaultmapClauseKind Kind) const {
799     OpenMPDefaultmapClauseModifier M =
800         getDefaultmapModifierAtLevel(Level, Kind);
801     if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
802       return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
803              (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
804              (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
805              (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
806              (M == OMPC_DEFAULTMAP_MODIFIER_present);
807     }
808     return true;
809   }
mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,OpenMPDefaultmapClauseKind Kind)810   static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
811                                      OpenMPDefaultmapClauseKind Kind) {
812     switch (Kind) {
813     case OMPC_DEFAULTMAP_scalar:
814     case OMPC_DEFAULTMAP_pointer:
815       return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
816              (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
817              (M == OMPC_DEFAULTMAP_MODIFIER_default);
818     case OMPC_DEFAULTMAP_aggregate:
819       return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
820     default:
821       break;
822     }
823     llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
824   }
mustBeFirstprivateAtLevel(unsigned Level,OpenMPDefaultmapClauseKind Kind) const825   bool mustBeFirstprivateAtLevel(unsigned Level,
826                                  OpenMPDefaultmapClauseKind Kind) const {
827     OpenMPDefaultmapClauseModifier M =
828         getDefaultmapModifierAtLevel(Level, Kind);
829     return mustBeFirstprivateBase(M, Kind);
830   }
mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const831   bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
832     OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
833     return mustBeFirstprivateBase(M, Kind);
834   }
835 
836   /// Checks if the specified variable is a threadprivate.
isThreadPrivate(VarDecl * D)837   bool isThreadPrivate(VarDecl *D) {
838     const DSAVarData DVar = getTopDSA(D, false);
839     return isOpenMPThreadPrivate(DVar.CKind);
840   }
841 
842   /// Marks current region as ordered (it has an 'ordered' clause).
setOrderedRegion(bool IsOrdered,const Expr * Param,OMPOrderedClause * Clause)843   void setOrderedRegion(bool IsOrdered, const Expr *Param,
844                         OMPOrderedClause *Clause) {
845     if (IsOrdered)
846       getTopOfStack().OrderedRegion.emplace(Param, Clause);
847     else
848       getTopOfStack().OrderedRegion.reset();
849   }
850   /// Returns true, if region is ordered (has associated 'ordered' clause),
851   /// false - otherwise.
isOrderedRegion() const852   bool isOrderedRegion() const {
853     if (const SharingMapTy *Top = getTopOfStackOrNull())
854       return Top->OrderedRegion.has_value();
855     return false;
856   }
857   /// Returns optional parameter for the ordered region.
getOrderedRegionParam() const858   std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
859     if (const SharingMapTy *Top = getTopOfStackOrNull())
860       if (Top->OrderedRegion)
861         return *Top->OrderedRegion;
862     return std::make_pair(nullptr, nullptr);
863   }
864   /// Returns true, if parent region is ordered (has associated
865   /// 'ordered' clause), false - otherwise.
isParentOrderedRegion() const866   bool isParentOrderedRegion() const {
867     if (const SharingMapTy *Parent = getSecondOnStackOrNull())
868       return Parent->OrderedRegion.has_value();
869     return false;
870   }
871   /// Returns optional parameter for the ordered region.
872   std::pair<const Expr *, OMPOrderedClause *>
getParentOrderedRegionParam() const873   getParentOrderedRegionParam() const {
874     if (const SharingMapTy *Parent = getSecondOnStackOrNull())
875       if (Parent->OrderedRegion)
876         return *Parent->OrderedRegion;
877     return std::make_pair(nullptr, nullptr);
878   }
879   /// Marks current region as having an 'order' clause.
setRegionHasOrderConcurrent(bool HasOrderConcurrent)880   void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
881     getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
882   }
883   /// Returns true, if parent region is order (has associated
884   /// 'order' clause), false - otherwise.
isParentOrderConcurrent() const885   bool isParentOrderConcurrent() const {
886     if (const SharingMapTy *Parent = getSecondOnStackOrNull())
887       return Parent->RegionHasOrderConcurrent;
888     return false;
889   }
890   /// Marks current region as nowait (it has a 'nowait' clause).
setNowaitRegion(bool IsNowait=true)891   void setNowaitRegion(bool IsNowait = true) {
892     getTopOfStack().NowaitRegion = IsNowait;
893   }
894   /// Returns true, if parent region is nowait (has associated
895   /// 'nowait' clause), false - otherwise.
isParentNowaitRegion() const896   bool isParentNowaitRegion() const {
897     if (const SharingMapTy *Parent = getSecondOnStackOrNull())
898       return Parent->NowaitRegion;
899     return false;
900   }
901   /// Marks current region as untied (it has a 'untied' clause).
setUntiedRegion(bool IsUntied=true)902   void setUntiedRegion(bool IsUntied = true) {
903     getTopOfStack().UntiedRegion = IsUntied;
904   }
905   /// Return true if current region is untied.
isUntiedRegion() const906   bool isUntiedRegion() const {
907     const SharingMapTy *Top = getTopOfStackOrNull();
908     return Top ? Top->UntiedRegion : false;
909   }
910   /// Marks parent region as cancel region.
setParentCancelRegion(bool Cancel=true)911   void setParentCancelRegion(bool Cancel = true) {
912     if (SharingMapTy *Parent = getSecondOnStackOrNull())
913       Parent->CancelRegion |= Cancel;
914   }
915   /// Return true if current region has inner cancel construct.
isCancelRegion() const916   bool isCancelRegion() const {
917     const SharingMapTy *Top = getTopOfStackOrNull();
918     return Top ? Top->CancelRegion : false;
919   }
920 
921   /// Mark that parent region already has scan directive.
setParentHasScanDirective(SourceLocation Loc)922   void setParentHasScanDirective(SourceLocation Loc) {
923     if (SharingMapTy *Parent = getSecondOnStackOrNull())
924       Parent->PrevScanLocation = Loc;
925   }
926   /// Return true if current region has inner cancel construct.
doesParentHasScanDirective() const927   bool doesParentHasScanDirective() const {
928     const SharingMapTy *Top = getSecondOnStackOrNull();
929     return Top ? Top->PrevScanLocation.isValid() : false;
930   }
931   /// Return true if current region has inner cancel construct.
getParentScanDirectiveLoc() const932   SourceLocation getParentScanDirectiveLoc() const {
933     const SharingMapTy *Top = getSecondOnStackOrNull();
934     return Top ? Top->PrevScanLocation : SourceLocation();
935   }
936   /// Mark that parent region already has ordered directive.
setParentHasOrderedDirective(SourceLocation Loc)937   void setParentHasOrderedDirective(SourceLocation Loc) {
938     if (SharingMapTy *Parent = getSecondOnStackOrNull())
939       Parent->PrevOrderedLocation = Loc;
940   }
941   /// Return true if current region has inner ordered construct.
doesParentHasOrderedDirective() const942   bool doesParentHasOrderedDirective() const {
943     const SharingMapTy *Top = getSecondOnStackOrNull();
944     return Top ? Top->PrevOrderedLocation.isValid() : false;
945   }
946   /// Returns the location of the previously specified ordered directive.
getParentOrderedDirectiveLoc() const947   SourceLocation getParentOrderedDirectiveLoc() const {
948     const SharingMapTy *Top = getSecondOnStackOrNull();
949     return Top ? Top->PrevOrderedLocation : SourceLocation();
950   }
951 
952   /// Set collapse value for the region.
setAssociatedLoops(unsigned Val)953   void setAssociatedLoops(unsigned Val) {
954     getTopOfStack().AssociatedLoops = Val;
955     if (Val > 1)
956       getTopOfStack().HasMutipleLoops = true;
957   }
958   /// Return collapse value for region.
getAssociatedLoops() const959   unsigned getAssociatedLoops() const {
960     const SharingMapTy *Top = getTopOfStackOrNull();
961     return Top ? Top->AssociatedLoops : 0;
962   }
963   /// Returns true if the construct is associated with multiple loops.
hasMutipleLoops() const964   bool hasMutipleLoops() const {
965     const SharingMapTy *Top = getTopOfStackOrNull();
966     return Top ? Top->HasMutipleLoops : false;
967   }
968 
969   /// Marks current target region as one with closely nested teams
970   /// region.
setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc)971   void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
972     if (SharingMapTy *Parent = getSecondOnStackOrNull())
973       Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
974   }
975   /// Returns true, if current region has closely nested teams region.
hasInnerTeamsRegion() const976   bool hasInnerTeamsRegion() const {
977     return getInnerTeamsRegionLoc().isValid();
978   }
979   /// Returns location of the nested teams region (if any).
getInnerTeamsRegionLoc() const980   SourceLocation getInnerTeamsRegionLoc() const {
981     const SharingMapTy *Top = getTopOfStackOrNull();
982     return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
983   }
984 
getCurScope() const985   Scope *getCurScope() const {
986     const SharingMapTy *Top = getTopOfStackOrNull();
987     return Top ? Top->CurScope : nullptr;
988   }
setContext(DeclContext * DC)989   void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
getConstructLoc() const990   SourceLocation getConstructLoc() const {
991     const SharingMapTy *Top = getTopOfStackOrNull();
992     return Top ? Top->ConstructLoc : SourceLocation();
993   }
994 
995   /// Do the check specified in \a Check to all component lists and return true
996   /// if any issue is found.
checkMappableExprComponentListsForDecl(const ValueDecl * VD,bool CurrentRegionOnly,const llvm::function_ref<bool (OMPClauseMappableExprCommon::MappableExprComponentListRef,OpenMPClauseKind)> Check) const997   bool checkMappableExprComponentListsForDecl(
998       const ValueDecl *VD, bool CurrentRegionOnly,
999       const llvm::function_ref<
1000           bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1001                OpenMPClauseKind)>
1002           Check) const {
1003     if (isStackEmpty())
1004       return false;
1005     auto SI = begin();
1006     auto SE = end();
1007 
1008     if (SI == SE)
1009       return false;
1010 
1011     if (CurrentRegionOnly)
1012       SE = std::next(SI);
1013     else
1014       std::advance(SI, 1);
1015 
1016     for (; SI != SE; ++SI) {
1017       auto MI = SI->MappedExprComponents.find(VD);
1018       if (MI != SI->MappedExprComponents.end())
1019         for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1020              MI->second.Components)
1021           if (Check(L, MI->second.Kind))
1022             return true;
1023     }
1024     return false;
1025   }
1026 
1027   /// Do the check specified in \a Check to all component lists at a given level
1028   /// and return true if any issue is found.
checkMappableExprComponentListsForDeclAtLevel(const ValueDecl * VD,unsigned Level,const llvm::function_ref<bool (OMPClauseMappableExprCommon::MappableExprComponentListRef,OpenMPClauseKind)> Check) const1029   bool checkMappableExprComponentListsForDeclAtLevel(
1030       const ValueDecl *VD, unsigned Level,
1031       const llvm::function_ref<
1032           bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1033                OpenMPClauseKind)>
1034           Check) const {
1035     if (getStackSize() <= Level)
1036       return false;
1037 
1038     const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1039     auto MI = StackElem.MappedExprComponents.find(VD);
1040     if (MI != StackElem.MappedExprComponents.end())
1041       for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1042            MI->second.Components)
1043         if (Check(L, MI->second.Kind))
1044           return true;
1045     return false;
1046   }
1047 
1048   /// Create a new mappable expression component list associated with a given
1049   /// declaration and initialize it with the provided list of components.
addMappableExpressionComponents(const ValueDecl * VD,OMPClauseMappableExprCommon::MappableExprComponentListRef Components,OpenMPClauseKind WhereFoundClauseKind)1050   void addMappableExpressionComponents(
1051       const ValueDecl *VD,
1052       OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
1053       OpenMPClauseKind WhereFoundClauseKind) {
1054     MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1055     // Create new entry and append the new components there.
1056     MEC.Components.resize(MEC.Components.size() + 1);
1057     MEC.Components.back().append(Components.begin(), Components.end());
1058     MEC.Kind = WhereFoundClauseKind;
1059   }
1060 
getNestingLevel() const1061   unsigned getNestingLevel() const {
1062     assert(!isStackEmpty());
1063     return getStackSize() - 1;
1064   }
addDoacrossDependClause(OMPClause * C,const OperatorOffsetTy & OpsOffs)1065   void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1066     SharingMapTy *Parent = getSecondOnStackOrNull();
1067     assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1068     Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1069   }
1070   llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
getDoacrossDependClauses() const1071   getDoacrossDependClauses() const {
1072     const SharingMapTy &StackElem = getTopOfStack();
1073     if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1074       const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1075       return llvm::make_range(Ref.begin(), Ref.end());
1076     }
1077     return llvm::make_range(StackElem.DoacrossDepends.end(),
1078                             StackElem.DoacrossDepends.end());
1079   }
1080 
1081   // Store types of classes which have been explicitly mapped
addMappedClassesQualTypes(QualType QT)1082   void addMappedClassesQualTypes(QualType QT) {
1083     SharingMapTy &StackElem = getTopOfStack();
1084     StackElem.MappedClassesQualTypes.insert(QT);
1085   }
1086 
1087   // Return set of mapped classes types
isClassPreviouslyMapped(QualType QT) const1088   bool isClassPreviouslyMapped(QualType QT) const {
1089     const SharingMapTy &StackElem = getTopOfStack();
1090     return StackElem.MappedClassesQualTypes.contains(QT);
1091   }
1092 
1093   /// Adds global declare target to the parent target region.
addToParentTargetRegionLinkGlobals(DeclRefExpr * E)1094   void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1095     assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1096                E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1097            "Expected declare target link global.");
1098     for (auto &Elem : *this) {
1099       if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1100         Elem.DeclareTargetLinkVarDecls.push_back(E);
1101         return;
1102       }
1103     }
1104   }
1105 
1106   /// Returns the list of globals with declare target link if current directive
1107   /// is target.
getLinkGlobals() const1108   ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1109     assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1110            "Expected target executable directive.");
1111     return getTopOfStack().DeclareTargetLinkVarDecls;
1112   }
1113 
1114   /// Adds list of allocators expressions.
addInnerAllocatorExpr(Expr * E)1115   void addInnerAllocatorExpr(Expr *E) {
1116     getTopOfStack().InnerUsedAllocators.push_back(E);
1117   }
1118   /// Return list of used allocators.
getInnerAllocators() const1119   ArrayRef<Expr *> getInnerAllocators() const {
1120     return getTopOfStack().InnerUsedAllocators;
1121   }
1122   /// Marks the declaration as implicitly firstprivate nin the task-based
1123   /// regions.
addImplicitTaskFirstprivate(unsigned Level,Decl * D)1124   void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1125     getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1126   }
1127   /// Checks if the decl is implicitly firstprivate in the task-based region.
isImplicitTaskFirstprivate(Decl * D) const1128   bool isImplicitTaskFirstprivate(Decl *D) const {
1129     return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1130   }
1131 
1132   /// Marks decl as used in uses_allocators clause as the allocator.
addUsesAllocatorsDecl(const Decl * D,UsesAllocatorsDeclKind Kind)1133   void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1134     getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1135   }
1136   /// Checks if specified decl is used in uses allocator clause as the
1137   /// allocator.
1138   std::optional<UsesAllocatorsDeclKind>
isUsesAllocatorsDecl(unsigned Level,const Decl * D) const1139   isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1140     const SharingMapTy &StackElem = getTopOfStack();
1141     auto I = StackElem.UsesAllocatorsDecls.find(D);
1142     if (I == StackElem.UsesAllocatorsDecls.end())
1143       return std::nullopt;
1144     return I->getSecond();
1145   }
1146   std::optional<UsesAllocatorsDeclKind>
isUsesAllocatorsDecl(const Decl * D) const1147   isUsesAllocatorsDecl(const Decl *D) const {
1148     const SharingMapTy &StackElem = getTopOfStack();
1149     auto I = StackElem.UsesAllocatorsDecls.find(D);
1150     if (I == StackElem.UsesAllocatorsDecls.end())
1151       return std::nullopt;
1152     return I->getSecond();
1153   }
1154 
addDeclareMapperVarRef(Expr * Ref)1155   void addDeclareMapperVarRef(Expr *Ref) {
1156     SharingMapTy &StackElem = getTopOfStack();
1157     StackElem.DeclareMapperVar = Ref;
1158   }
getDeclareMapperVarRef() const1159   const Expr *getDeclareMapperVarRef() const {
1160     const SharingMapTy *Top = getTopOfStackOrNull();
1161     return Top ? Top->DeclareMapperVar : nullptr;
1162   }
1163 
1164   /// Add a new iterator variable.
addIteratorVarDecl(VarDecl * VD)1165   void addIteratorVarDecl(VarDecl *VD) {
1166     SharingMapTy &StackElem = getTopOfStack();
1167     StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl());
1168   }
1169   /// Check if variable declaration is an iterator VarDecl.
isIteratorVarDecl(const VarDecl * VD) const1170   bool isIteratorVarDecl(const VarDecl *VD) const {
1171     const SharingMapTy *Top = getTopOfStackOrNull();
1172     if (!Top)
1173       return false;
1174 
1175     return llvm::is_contained(Top->IteratorVarDecls, VD->getCanonicalDecl());
1176   }
1177   /// get captured field from ImplicitDefaultFirstprivateFDs
getImplicitFDCapExprDecl(const FieldDecl * FD) const1178   VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1179     const_iterator I = begin();
1180     const_iterator EndI = end();
1181     size_t StackLevel = getStackSize();
1182     for (; I != EndI; ++I) {
1183       if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1184         break;
1185       StackLevel--;
1186     }
1187     assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1188     if (I == EndI)
1189       return nullptr;
1190     for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1191       if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1192         return IFD.VD;
1193     return nullptr;
1194   }
1195   /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
isImplicitDefaultFirstprivateFD(VarDecl * VD) const1196   bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1197     const_iterator I = begin();
1198     const_iterator EndI = end();
1199     for (; I != EndI; ++I)
1200       if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1201         break;
1202     if (I == EndI)
1203       return false;
1204     for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1205       if (IFD.VD == VD)
1206         return true;
1207     return false;
1208   }
1209   /// Store capture FD info in ImplicitDefaultFirstprivateFDs
addImplicitDefaultFirstprivateFD(const FieldDecl * FD,VarDecl * VD)1210   void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1211     iterator I = begin();
1212     const_iterator EndI = end();
1213     size_t StackLevel = getStackSize();
1214     for (; I != EndI; ++I) {
1215       if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1216         I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1217         break;
1218       }
1219       StackLevel--;
1220     }
1221     assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1222   }
1223 };
1224 
isImplicitTaskingRegion(OpenMPDirectiveKind DKind)1225 bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1226   return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1227 }
1228 
isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind)1229 bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1230   return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1231          DKind == OMPD_unknown;
1232 }
1233 
1234 } // namespace
1235 
getExprAsWritten(const Expr * E)1236 static const Expr *getExprAsWritten(const Expr *E) {
1237   if (const auto *FE = dyn_cast<FullExpr>(E))
1238     E = FE->getSubExpr();
1239 
1240   if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1241     E = MTE->getSubExpr();
1242 
1243   while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1244     E = Binder->getSubExpr();
1245 
1246   if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1247     E = ICE->getSubExprAsWritten();
1248   return E->IgnoreParens();
1249 }
1250 
getExprAsWritten(Expr * E)1251 static Expr *getExprAsWritten(Expr *E) {
1252   return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1253 }
1254 
getCanonicalDecl(const ValueDecl * D)1255 static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1256   if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1257     if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1258       D = ME->getMemberDecl();
1259 
1260   D = cast<ValueDecl>(D->getCanonicalDecl());
1261   return D;
1262 }
1263 
getCanonicalDecl(ValueDecl * D)1264 static ValueDecl *getCanonicalDecl(ValueDecl *D) {
1265   return const_cast<ValueDecl *>(
1266       getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1267 }
1268 
getOpenMPClauseNameForDiag(OpenMPClauseKind C)1269 static std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C) {
1270   if (C == OMPC_threadprivate)
1271     return getOpenMPClauseName(C).str() + " or thread local";
1272   return getOpenMPClauseName(C).str();
1273 }
1274 
getDSA(const_iterator & Iter,ValueDecl * D) const1275 DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1276                                           ValueDecl *D) const {
1277   D = getCanonicalDecl(D);
1278   auto *VD = dyn_cast<VarDecl>(D);
1279   const auto *FD = dyn_cast<FieldDecl>(D);
1280   DSAVarData DVar;
1281   if (Iter == end()) {
1282     // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1283     // in a region but not in construct]
1284     //  File-scope or namespace-scope variables referenced in called routines
1285     //  in the region are shared unless they appear in a threadprivate
1286     //  directive.
1287     if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1288       DVar.CKind = OMPC_shared;
1289 
1290     // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1291     // in a region but not in construct]
1292     //  Variables with static storage duration that are declared in called
1293     //  routines in the region are shared.
1294     if (VD && VD->hasGlobalStorage())
1295       DVar.CKind = OMPC_shared;
1296 
1297     // Non-static data members are shared by default.
1298     if (FD)
1299       DVar.CKind = OMPC_shared;
1300 
1301     return DVar;
1302   }
1303 
1304   // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1305   // in a Construct, C/C++, predetermined, p.1]
1306   // Variables with automatic storage duration that are declared in a scope
1307   // inside the construct are private.
1308   if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1309       (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1310     DVar.CKind = OMPC_private;
1311     return DVar;
1312   }
1313 
1314   DVar.DKind = Iter->Directive;
1315   // Explicitly specified attributes and local variables with predetermined
1316   // attributes.
1317   if (Iter->SharingMap.count(D)) {
1318     const DSAInfo &Data = Iter->SharingMap.lookup(D);
1319     DVar.RefExpr = Data.RefExpr.getPointer();
1320     DVar.PrivateCopy = Data.PrivateCopy;
1321     DVar.CKind = Data.Attributes;
1322     DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1323     DVar.Modifier = Data.Modifier;
1324     DVar.AppliedToPointee = Data.AppliedToPointee;
1325     return DVar;
1326   }
1327 
1328   // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1329   // in a Construct, C/C++, implicitly determined, p.1]
1330   //  In a parallel or task construct, the data-sharing attributes of these
1331   //  variables are determined by the default clause, if present.
1332   switch (Iter->DefaultAttr) {
1333   case DSA_shared:
1334     DVar.CKind = OMPC_shared;
1335     DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1336     return DVar;
1337   case DSA_none:
1338     return DVar;
1339   case DSA_firstprivate:
1340     if (VD && VD->getStorageDuration() == SD_Static &&
1341         VD->getDeclContext()->isFileContext()) {
1342       DVar.CKind = OMPC_unknown;
1343     } else {
1344       DVar.CKind = OMPC_firstprivate;
1345     }
1346     DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1347     return DVar;
1348   case DSA_private:
1349     // each variable with static storage duration that is declared
1350     // in a namespace or global scope and referenced in the construct,
1351     // and that does not have a predetermined data-sharing attribute
1352     if (VD && VD->getStorageDuration() == SD_Static &&
1353         VD->getDeclContext()->isFileContext()) {
1354       DVar.CKind = OMPC_unknown;
1355     } else {
1356       DVar.CKind = OMPC_private;
1357     }
1358     DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1359     return DVar;
1360   case DSA_unspecified:
1361     // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1362     // in a Construct, implicitly determined, p.2]
1363     //  In a parallel construct, if no default clause is present, these
1364     //  variables are shared.
1365     DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1366     if ((isOpenMPParallelDirective(DVar.DKind) &&
1367          !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1368         isOpenMPTeamsDirective(DVar.DKind)) {
1369       DVar.CKind = OMPC_shared;
1370       return DVar;
1371     }
1372 
1373     // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1374     // in a Construct, implicitly determined, p.4]
1375     //  In a task construct, if no default clause is present, a variable that in
1376     //  the enclosing context is determined to be shared by all implicit tasks
1377     //  bound to the current team is shared.
1378     if (isOpenMPTaskingDirective(DVar.DKind)) {
1379       DSAVarData DVarTemp;
1380       const_iterator I = Iter, E = end();
1381       do {
1382         ++I;
1383         // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1384         // Referenced in a Construct, implicitly determined, p.6]
1385         //  In a task construct, if no default clause is present, a variable
1386         //  whose data-sharing attribute is not determined by the rules above is
1387         //  firstprivate.
1388         DVarTemp = getDSA(I, D);
1389         if (DVarTemp.CKind != OMPC_shared) {
1390           DVar.RefExpr = nullptr;
1391           DVar.CKind = OMPC_firstprivate;
1392           return DVar;
1393         }
1394       } while (I != E && !isImplicitTaskingRegion(I->Directive));
1395       DVar.CKind =
1396           (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1397       return DVar;
1398     }
1399   }
1400   // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1401   // in a Construct, implicitly determined, p.3]
1402   //  For constructs other than task, if no default clause is present, these
1403   //  variables inherit their data-sharing attributes from the enclosing
1404   //  context.
1405   return getDSA(++Iter, D);
1406 }
1407 
addUniqueAligned(const ValueDecl * D,const Expr * NewDE)1408 const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1409                                          const Expr *NewDE) {
1410   assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1411   D = getCanonicalDecl(D);
1412   SharingMapTy &StackElem = getTopOfStack();
1413   auto [It, Inserted] = StackElem.AlignedMap.try_emplace(D, NewDE);
1414   if (Inserted) {
1415     assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1416     return nullptr;
1417   }
1418   assert(It->second && "Unexpected nullptr expr in the aligned map");
1419   return It->second;
1420 }
1421 
addUniqueNontemporal(const ValueDecl * D,const Expr * NewDE)1422 const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1423                                              const Expr *NewDE) {
1424   assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1425   D = getCanonicalDecl(D);
1426   SharingMapTy &StackElem = getTopOfStack();
1427   auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(D, NewDE);
1428   if (Inserted) {
1429     assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1430     return nullptr;
1431   }
1432   assert(It->second && "Unexpected nullptr expr in the aligned map");
1433   return It->second;
1434 }
1435 
addLoopControlVariable(const ValueDecl * D,VarDecl * Capture)1436 void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1437   assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1438   D = getCanonicalDecl(D);
1439   SharingMapTy &StackElem = getTopOfStack();
1440   StackElem.LCVMap.try_emplace(
1441       D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1442 }
1443 
1444 const DSAStackTy::LCDeclInfo
isLoopControlVariable(const ValueDecl * D) const1445 DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1446   assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1447   D = getCanonicalDecl(D);
1448   const SharingMapTy &StackElem = getTopOfStack();
1449   auto It = StackElem.LCVMap.find(D);
1450   if (It != StackElem.LCVMap.end())
1451     return It->second;
1452   return {0, nullptr};
1453 }
1454 
1455 const DSAStackTy::LCDeclInfo
isLoopControlVariable(const ValueDecl * D,unsigned Level) const1456 DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1457   assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1458   D = getCanonicalDecl(D);
1459   for (unsigned I = Level + 1; I > 0; --I) {
1460     const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1461     auto It = StackElem.LCVMap.find(D);
1462     if (It != StackElem.LCVMap.end())
1463       return It->second;
1464   }
1465   return {0, nullptr};
1466 }
1467 
1468 const DSAStackTy::LCDeclInfo
isParentLoopControlVariable(const ValueDecl * D) const1469 DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1470   const SharingMapTy *Parent = getSecondOnStackOrNull();
1471   assert(Parent && "Data-sharing attributes stack is empty");
1472   D = getCanonicalDecl(D);
1473   auto It = Parent->LCVMap.find(D);
1474   if (It != Parent->LCVMap.end())
1475     return It->second;
1476   return {0, nullptr};
1477 }
1478 
getParentLoopControlVariable(unsigned I) const1479 const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1480   const SharingMapTy *Parent = getSecondOnStackOrNull();
1481   assert(Parent && "Data-sharing attributes stack is empty");
1482   if (Parent->LCVMap.size() < I)
1483     return nullptr;
1484   for (const auto &Pair : Parent->LCVMap)
1485     if (Pair.second.first == I)
1486       return Pair.first;
1487   return nullptr;
1488 }
1489 
addDSA(const ValueDecl * D,const Expr * E,OpenMPClauseKind A,DeclRefExpr * PrivateCopy,unsigned Modifier,bool AppliedToPointee)1490 void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1491                         DeclRefExpr *PrivateCopy, unsigned Modifier,
1492                         bool AppliedToPointee) {
1493   D = getCanonicalDecl(D);
1494   if (A == OMPC_threadprivate) {
1495     DSAInfo &Data = Threadprivates[D];
1496     Data.Attributes = A;
1497     Data.RefExpr.setPointer(E);
1498     Data.PrivateCopy = nullptr;
1499     Data.Modifier = Modifier;
1500   } else {
1501     DSAInfo &Data = getTopOfStack().SharingMap[D];
1502     assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1503            (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1504            (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1505            (isLoopControlVariable(D).first && A == OMPC_private));
1506     Data.Modifier = Modifier;
1507     if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1508       Data.RefExpr.setInt(/*IntVal=*/true);
1509       return;
1510     }
1511     const bool IsLastprivate =
1512         A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1513     Data.Attributes = A;
1514     Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1515     Data.PrivateCopy = PrivateCopy;
1516     Data.AppliedToPointee = AppliedToPointee;
1517     if (PrivateCopy) {
1518       DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1519       Data.Modifier = Modifier;
1520       Data.Attributes = A;
1521       Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1522       Data.PrivateCopy = nullptr;
1523       Data.AppliedToPointee = AppliedToPointee;
1524     }
1525   }
1526 }
1527 
1528 /// Build a variable declaration for OpenMP loop iteration variable.
buildVarDecl(Sema & SemaRef,SourceLocation Loc,QualType Type,StringRef Name,const AttrVec * Attrs=nullptr,DeclRefExpr * OrigRef=nullptr)1529 static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
1530                              StringRef Name, const AttrVec *Attrs = nullptr,
1531                              DeclRefExpr *OrigRef = nullptr) {
1532   DeclContext *DC = SemaRef.CurContext;
1533   IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1534   TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
1535   auto *Decl =
1536       VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
1537   if (Attrs) {
1538     for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1539          I != E; ++I)
1540       Decl->addAttr(*I);
1541   }
1542   Decl->setImplicit();
1543   if (OrigRef) {
1544     Decl->addAttr(
1545         OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1546   }
1547   return Decl;
1548 }
1549 
buildDeclRefExpr(Sema & S,VarDecl * D,QualType Ty,SourceLocation Loc,bool RefersToCapture=false)1550 static DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty,
1551                                      SourceLocation Loc,
1552                                      bool RefersToCapture = false) {
1553   D->setReferenced();
1554   D->markUsed(S.Context);
1555   return DeclRefExpr::Create(S.getASTContext(), NestedNameSpecifierLoc(),
1556                              SourceLocation(), D, RefersToCapture, Loc, Ty,
1557                              VK_LValue);
1558 }
1559 
addTaskgroupReductionData(const ValueDecl * D,SourceRange SR,BinaryOperatorKind BOK)1560 void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1561                                            BinaryOperatorKind BOK) {
1562   D = getCanonicalDecl(D);
1563   assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1564   assert(
1565       getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1566       "Additional reduction info may be specified only for reduction items.");
1567   ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1568   assert(ReductionData.ReductionRange.isInvalid() &&
1569          (getTopOfStack().Directive == OMPD_taskgroup ||
1570           ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1571             isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1572            !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1573          "Additional reduction info may be specified only once for reduction "
1574          "items.");
1575   ReductionData.set(BOK, SR);
1576   Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1577   if (!TaskgroupReductionRef) {
1578     VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1579                                SemaRef.Context.VoidPtrTy, ".task_red.");
1580     TaskgroupReductionRef =
1581         buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1582   }
1583 }
1584 
addTaskgroupReductionData(const ValueDecl * D,SourceRange SR,const Expr * ReductionRef)1585 void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1586                                            const Expr *ReductionRef) {
1587   D = getCanonicalDecl(D);
1588   assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1589   assert(
1590       getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1591       "Additional reduction info may be specified only for reduction items.");
1592   ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1593   assert(ReductionData.ReductionRange.isInvalid() &&
1594          (getTopOfStack().Directive == OMPD_taskgroup ||
1595           ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1596             isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1597            !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1598          "Additional reduction info may be specified only once for reduction "
1599          "items.");
1600   ReductionData.set(ReductionRef, SR);
1601   Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1602   if (!TaskgroupReductionRef) {
1603     VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1604                                SemaRef.Context.VoidPtrTy, ".task_red.");
1605     TaskgroupReductionRef =
1606         buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1607   }
1608 }
1609 
getTopMostTaskgroupReductionData(const ValueDecl * D,SourceRange & SR,BinaryOperatorKind & BOK,Expr * & TaskgroupDescriptor) const1610 const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1611     const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1612     Expr *&TaskgroupDescriptor) const {
1613   D = getCanonicalDecl(D);
1614   assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1615   for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1616     const DSAInfo &Data = I->SharingMap.lookup(D);
1617     if (Data.Attributes != OMPC_reduction ||
1618         Data.Modifier != OMPC_REDUCTION_task)
1619       continue;
1620     const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1621     if (!ReductionData.ReductionOp ||
1622         isa<const Expr *>(ReductionData.ReductionOp))
1623       return DSAVarData();
1624     SR = ReductionData.ReductionRange;
1625     BOK = cast<ReductionData::BOKPtrType>(ReductionData.ReductionOp);
1626     assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1627                                        "expression for the descriptor is not "
1628                                        "set.");
1629     TaskgroupDescriptor = I->TaskgroupReductionRef;
1630     return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1631                       Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1632                       /*AppliedToPointee=*/false);
1633   }
1634   return DSAVarData();
1635 }
1636 
getTopMostTaskgroupReductionData(const ValueDecl * D,SourceRange & SR,const Expr * & ReductionRef,Expr * & TaskgroupDescriptor) const1637 const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1638     const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1639     Expr *&TaskgroupDescriptor) const {
1640   D = getCanonicalDecl(D);
1641   assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1642   for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1643     const DSAInfo &Data = I->SharingMap.lookup(D);
1644     if (Data.Attributes != OMPC_reduction ||
1645         Data.Modifier != OMPC_REDUCTION_task)
1646       continue;
1647     const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1648     if (!ReductionData.ReductionOp ||
1649         !isa<const Expr *>(ReductionData.ReductionOp))
1650       return DSAVarData();
1651     SR = ReductionData.ReductionRange;
1652     ReductionRef = cast<const Expr *>(ReductionData.ReductionOp);
1653     assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1654                                        "expression for the descriptor is not "
1655                                        "set.");
1656     TaskgroupDescriptor = I->TaskgroupReductionRef;
1657     return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1658                       Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1659                       /*AppliedToPointee=*/false);
1660   }
1661   return DSAVarData();
1662 }
1663 
isOpenMPLocal(VarDecl * D,const_iterator I) const1664 bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1665   D = D->getCanonicalDecl();
1666   for (const_iterator E = end(); I != E; ++I) {
1667     if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1668         isOpenMPTargetExecutionDirective(I->Directive)) {
1669       if (I->CurScope) {
1670         Scope *TopScope = I->CurScope->getParent();
1671         Scope *CurScope = getCurScope();
1672         while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1673           CurScope = CurScope->getParent();
1674         return CurScope != TopScope;
1675       }
1676       for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1677         if (I->Context == DC)
1678           return true;
1679       return false;
1680     }
1681   }
1682   return false;
1683 }
1684 
isConstNotMutableType(Sema & SemaRef,QualType Type,bool AcceptIfMutable=true,bool * IsClassType=nullptr)1685 static bool isConstNotMutableType(Sema &SemaRef, QualType Type,
1686                                   bool AcceptIfMutable = true,
1687                                   bool *IsClassType = nullptr) {
1688   ASTContext &Context = SemaRef.getASTContext();
1689   Type = Type.getNonReferenceType().getCanonicalType();
1690   bool IsConstant = Type.isConstant(Context);
1691   Type = Context.getBaseElementType(Type);
1692   const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1693                                 ? Type->getAsCXXRecordDecl()
1694                                 : nullptr;
1695   if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1696     if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1697       RD = CTD->getTemplatedDecl();
1698   if (IsClassType)
1699     *IsClassType = RD;
1700   return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1701                          RD->hasDefinition() && RD->hasMutableFields());
1702 }
1703 
rejectConstNotMutableType(Sema & SemaRef,const ValueDecl * D,QualType Type,OpenMPClauseKind CKind,SourceLocation ELoc,bool AcceptIfMutable=true,bool ListItemNotVar=false)1704 static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1705                                       QualType Type, OpenMPClauseKind CKind,
1706                                       SourceLocation ELoc,
1707                                       bool AcceptIfMutable = true,
1708                                       bool ListItemNotVar = false) {
1709   ASTContext &Context = SemaRef.getASTContext();
1710   bool IsClassType;
1711   if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
1712     unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1713                     : IsClassType  ? diag::err_omp_const_not_mutable_variable
1714                                    : diag::err_omp_const_variable;
1715     SemaRef.Diag(ELoc, Diag) << getOpenMPClauseNameForDiag(CKind);
1716     if (!ListItemNotVar && D) {
1717       const VarDecl *VD = dyn_cast<VarDecl>(D);
1718       bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1719                                VarDecl::DeclarationOnly;
1720       SemaRef.Diag(D->getLocation(),
1721                    IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1722           << D;
1723     }
1724     return true;
1725   }
1726   return false;
1727 }
1728 
getTopDSA(ValueDecl * D,bool FromParent)1729 const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1730                                                    bool FromParent) {
1731   D = getCanonicalDecl(D);
1732   DSAVarData DVar;
1733 
1734   auto *VD = dyn_cast<VarDecl>(D);
1735   auto TI = Threadprivates.find(D);
1736   if (TI != Threadprivates.end()) {
1737     DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1738     DVar.CKind = OMPC_threadprivate;
1739     DVar.Modifier = TI->getSecond().Modifier;
1740     return DVar;
1741   }
1742   if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1743     DVar.RefExpr = buildDeclRefExpr(
1744         SemaRef, VD, D->getType().getNonReferenceType(),
1745         VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1746     DVar.CKind = OMPC_threadprivate;
1747     addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1748     return DVar;
1749   }
1750   // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1751   // in a Construct, C/C++, predetermined, p.1]
1752   //  Variables appearing in threadprivate directives are threadprivate.
1753   if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1754        !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1755          SemaRef.getLangOpts().OpenMPUseTLS &&
1756          SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1757       (VD && VD->getStorageClass() == SC_Register &&
1758        VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1759     DVar.RefExpr = buildDeclRefExpr(
1760         SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1761     DVar.CKind = OMPC_threadprivate;
1762     addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1763     return DVar;
1764   }
1765   if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1766       VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1767       !isLoopControlVariable(D).first) {
1768     const_iterator IterTarget =
1769         std::find_if(begin(), end(), [](const SharingMapTy &Data) {
1770           return isOpenMPTargetExecutionDirective(Data.Directive);
1771         });
1772     if (IterTarget != end()) {
1773       const_iterator ParentIterTarget = IterTarget + 1;
1774       for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1775         if (isOpenMPLocal(VD, Iter)) {
1776           DVar.RefExpr =
1777               buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1778                                D->getLocation());
1779           DVar.CKind = OMPC_threadprivate;
1780           return DVar;
1781         }
1782       }
1783       if (!isClauseParsingMode() || IterTarget != begin()) {
1784         auto DSAIter = IterTarget->SharingMap.find(D);
1785         if (DSAIter != IterTarget->SharingMap.end() &&
1786             isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1787           DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1788           DVar.CKind = OMPC_threadprivate;
1789           return DVar;
1790         }
1791         const_iterator End = end();
1792         if (!SemaRef.OpenMP().isOpenMPCapturedByRef(
1793                 D, std::distance(ParentIterTarget, End),
1794                 /*OpenMPCaptureLevel=*/0)) {
1795           DVar.RefExpr =
1796               buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1797                                IterTarget->ConstructLoc);
1798           DVar.CKind = OMPC_threadprivate;
1799           return DVar;
1800         }
1801       }
1802     }
1803   }
1804 
1805   if (isStackEmpty())
1806     // Not in OpenMP execution region and top scope was already checked.
1807     return DVar;
1808 
1809   // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1810   // in a Construct, C/C++, predetermined, p.4]
1811   //  Static data members are shared.
1812   // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1813   // in a Construct, C/C++, predetermined, p.7]
1814   //  Variables with static storage duration that are declared in a scope
1815   //  inside the construct are shared.
1816   if (VD && VD->isStaticDataMember()) {
1817     // Check for explicitly specified attributes.
1818     const_iterator I = begin();
1819     const_iterator EndI = end();
1820     if (FromParent && I != EndI)
1821       ++I;
1822     if (I != EndI) {
1823       auto It = I->SharingMap.find(D);
1824       if (It != I->SharingMap.end()) {
1825         const DSAInfo &Data = It->getSecond();
1826         DVar.RefExpr = Data.RefExpr.getPointer();
1827         DVar.PrivateCopy = Data.PrivateCopy;
1828         DVar.CKind = Data.Attributes;
1829         DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1830         DVar.DKind = I->Directive;
1831         DVar.Modifier = Data.Modifier;
1832         DVar.AppliedToPointee = Data.AppliedToPointee;
1833         return DVar;
1834       }
1835     }
1836 
1837     DVar.CKind = OMPC_shared;
1838     return DVar;
1839   }
1840 
1841   auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1842   // The predetermined shared attribute for const-qualified types having no
1843   // mutable members was removed after OpenMP 3.1.
1844   if (SemaRef.LangOpts.OpenMP <= 31) {
1845     // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1846     // in a Construct, C/C++, predetermined, p.6]
1847     //  Variables with const qualified type having no mutable member are
1848     //  shared.
1849     if (isConstNotMutableType(SemaRef, D->getType())) {
1850       // Variables with const-qualified type having no mutable member may be
1851       // listed in a firstprivate clause, even if they are static data members.
1852       DSAVarData DVarTemp = hasInnermostDSA(
1853           D,
1854           [](OpenMPClauseKind C, bool) {
1855             return C == OMPC_firstprivate || C == OMPC_shared;
1856           },
1857           MatchesAlways, FromParent);
1858       if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1859         return DVarTemp;
1860 
1861       DVar.CKind = OMPC_shared;
1862       return DVar;
1863     }
1864   }
1865 
1866   // Explicitly specified attributes and local variables with predetermined
1867   // attributes.
1868   const_iterator I = begin();
1869   const_iterator EndI = end();
1870   if (FromParent && I != EndI)
1871     ++I;
1872   if (I == EndI)
1873     return DVar;
1874   auto It = I->SharingMap.find(D);
1875   if (It != I->SharingMap.end()) {
1876     const DSAInfo &Data = It->getSecond();
1877     DVar.RefExpr = Data.RefExpr.getPointer();
1878     DVar.PrivateCopy = Data.PrivateCopy;
1879     DVar.CKind = Data.Attributes;
1880     DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1881     DVar.DKind = I->Directive;
1882     DVar.Modifier = Data.Modifier;
1883     DVar.AppliedToPointee = Data.AppliedToPointee;
1884   }
1885 
1886   return DVar;
1887 }
1888 
getImplicitDSA(ValueDecl * D,bool FromParent) const1889 const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1890                                                         bool FromParent) const {
1891   if (isStackEmpty()) {
1892     const_iterator I;
1893     return getDSA(I, D);
1894   }
1895   D = getCanonicalDecl(D);
1896   const_iterator StartI = begin();
1897   const_iterator EndI = end();
1898   if (FromParent && StartI != EndI)
1899     ++StartI;
1900   return getDSA(StartI, D);
1901 }
1902 
getImplicitDSA(ValueDecl * D,unsigned Level) const1903 const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1904                                                         unsigned Level) const {
1905   if (getStackSize() <= Level)
1906     return DSAVarData();
1907   D = getCanonicalDecl(D);
1908   const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1909   return getDSA(StartI, D);
1910 }
1911 
1912 const DSAStackTy::DSAVarData
hasDSA(ValueDecl * D,const llvm::function_ref<bool (OpenMPClauseKind,bool,DefaultDataSharingAttributes)> CPred,const llvm::function_ref<bool (OpenMPDirectiveKind)> DPred,bool FromParent) const1913 DSAStackTy::hasDSA(ValueDecl *D,
1914                    const llvm::function_ref<bool(OpenMPClauseKind, bool,
1915                                                  DefaultDataSharingAttributes)>
1916                        CPred,
1917                    const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1918                    bool FromParent) const {
1919   if (isStackEmpty())
1920     return {};
1921   D = getCanonicalDecl(D);
1922   const_iterator I = begin();
1923   const_iterator EndI = end();
1924   if (FromParent && I != EndI)
1925     ++I;
1926   for (; I != EndI; ++I) {
1927     if (!DPred(I->Directive) &&
1928         !isImplicitOrExplicitTaskingRegion(I->Directive))
1929       continue;
1930     const_iterator NewI = I;
1931     DSAVarData DVar = getDSA(NewI, D);
1932     if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1933       return DVar;
1934   }
1935   return {};
1936 }
1937 
hasInnermostDSA(ValueDecl * D,const llvm::function_ref<bool (OpenMPClauseKind,bool)> CPred,const llvm::function_ref<bool (OpenMPDirectiveKind)> DPred,bool FromParent) const1938 const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1939     ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1940     const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1941     bool FromParent) const {
1942   if (isStackEmpty())
1943     return {};
1944   D = getCanonicalDecl(D);
1945   const_iterator StartI = begin();
1946   const_iterator EndI = end();
1947   if (FromParent && StartI != EndI)
1948     ++StartI;
1949   if (StartI == EndI || !DPred(StartI->Directive))
1950     return {};
1951   const_iterator NewI = StartI;
1952   DSAVarData DVar = getDSA(NewI, D);
1953   return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1954              ? DVar
1955              : DSAVarData();
1956 }
1957 
hasExplicitDSA(const ValueDecl * D,const llvm::function_ref<bool (OpenMPClauseKind,bool)> CPred,unsigned Level,bool NotLastprivate) const1958 bool DSAStackTy::hasExplicitDSA(
1959     const ValueDecl *D,
1960     const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1961     unsigned Level, bool NotLastprivate) const {
1962   if (getStackSize() <= Level)
1963     return false;
1964   D = getCanonicalDecl(D);
1965   const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1966   auto I = StackElem.SharingMap.find(D);
1967   if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1968       CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1969       (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1970     return true;
1971   // Check predetermined rules for the loop control variables.
1972   auto LI = StackElem.LCVMap.find(D);
1973   if (LI != StackElem.LCVMap.end())
1974     return CPred(OMPC_private, /*AppliedToPointee=*/false);
1975   return false;
1976 }
1977 
hasExplicitDirective(const llvm::function_ref<bool (OpenMPDirectiveKind)> DPred,unsigned Level) const1978 bool DSAStackTy::hasExplicitDirective(
1979     const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1980     unsigned Level) const {
1981   if (getStackSize() <= Level)
1982     return false;
1983   const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1984   return DPred(StackElem.Directive);
1985 }
1986 
hasDirective(const llvm::function_ref<bool (OpenMPDirectiveKind,const DeclarationNameInfo &,SourceLocation)> DPred,bool FromParent) const1987 bool DSAStackTy::hasDirective(
1988     const llvm::function_ref<bool(OpenMPDirectiveKind,
1989                                   const DeclarationNameInfo &, SourceLocation)>
1990         DPred,
1991     bool FromParent) const {
1992   // We look only in the enclosing region.
1993   size_t Skip = FromParent ? 2 : 1;
1994   for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
1995        I != E; ++I) {
1996     if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
1997       return true;
1998   }
1999   return false;
2000 }
2001 
InitDataSharingAttributesStack()2002 void SemaOpenMP::InitDataSharingAttributesStack() {
2003   VarDataSharingAttributesStack = new DSAStackTy(SemaRef);
2004 }
2005 
2006 #define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2007 
pushOpenMPFunctionRegion()2008 void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2009 
popOpenMPFunctionRegion(const FunctionScopeInfo * OldFSI)2010 void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2011   DSAStack->popFunction(OldFSI);
2012 }
2013 
isOpenMPDeviceDelayedContext(Sema & S)2014 static bool isOpenMPDeviceDelayedContext(Sema &S) {
2015   assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2016          "Expected OpenMP device compilation.");
2017   return !S.OpenMP().isInOpenMPTargetExecutionDirective();
2018 }
2019 
2020 namespace {
2021 /// Status of the function emission on the host/device.
2022 enum class FunctionEmissionStatus {
2023   Emitted,
2024   Discarded,
2025   Unknown,
2026 };
2027 } // anonymous namespace
2028 
2029 SemaBase::SemaDiagnosticBuilder
diagIfOpenMPDeviceCode(SourceLocation Loc,unsigned DiagID,const FunctionDecl * FD)2030 SemaOpenMP::diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID,
2031                                    const FunctionDecl *FD) {
2032   assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&
2033          "Expected OpenMP device compilation.");
2034 
2035   SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2036   if (FD) {
2037     Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(FD);
2038     switch (FES) {
2039     case Sema::FunctionEmissionStatus::Emitted:
2040       Kind = SemaDiagnosticBuilder::K_Immediate;
2041       break;
2042     case Sema::FunctionEmissionStatus::Unknown:
2043       // TODO: We should always delay diagnostics here in case a target
2044       //       region is in a function we do not emit. However, as the
2045       //       current diagnostics are associated with the function containing
2046       //       the target region and we do not emit that one, we would miss out
2047       //       on diagnostics for the target region itself. We need to anchor
2048       //       the diagnostics with the new generated function *or* ensure we
2049       //       emit diagnostics associated with the surrounding function.
2050       Kind = isOpenMPDeviceDelayedContext(SemaRef)
2051                  ? SemaDiagnosticBuilder::K_Deferred
2052                  : SemaDiagnosticBuilder::K_Immediate;
2053       break;
2054     case Sema::FunctionEmissionStatus::TemplateDiscarded:
2055     case Sema::FunctionEmissionStatus::OMPDiscarded:
2056       Kind = SemaDiagnosticBuilder::K_Nop;
2057       break;
2058     case Sema::FunctionEmissionStatus::CUDADiscarded:
2059       llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2060       break;
2061     }
2062   }
2063 
2064   return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2065 }
2066 
2067 SemaBase::SemaDiagnosticBuilder
diagIfOpenMPHostCode(SourceLocation Loc,unsigned DiagID,const FunctionDecl * FD)2068 SemaOpenMP::diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID,
2069                                  const FunctionDecl *FD) {
2070   assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice &&
2071          "Expected OpenMP host compilation.");
2072 
2073   SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2074   if (FD) {
2075     Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(FD);
2076     switch (FES) {
2077     case Sema::FunctionEmissionStatus::Emitted:
2078       Kind = SemaDiagnosticBuilder::K_Immediate;
2079       break;
2080     case Sema::FunctionEmissionStatus::Unknown:
2081       Kind = SemaDiagnosticBuilder::K_Deferred;
2082       break;
2083     case Sema::FunctionEmissionStatus::TemplateDiscarded:
2084     case Sema::FunctionEmissionStatus::OMPDiscarded:
2085     case Sema::FunctionEmissionStatus::CUDADiscarded:
2086       Kind = SemaDiagnosticBuilder::K_Nop;
2087       break;
2088     }
2089   }
2090 
2091   return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2092 }
2093 
2094 static OpenMPDefaultmapClauseKind
getVariableCategoryFromDecl(const LangOptions & LO,const ValueDecl * VD)2095 getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD) {
2096   if (LO.OpenMP <= 45) {
2097     if (VD->getType().getNonReferenceType()->isScalarType())
2098       return OMPC_DEFAULTMAP_scalar;
2099     return OMPC_DEFAULTMAP_aggregate;
2100   }
2101   if (VD->getType().getNonReferenceType()->isAnyPointerType())
2102     return OMPC_DEFAULTMAP_pointer;
2103   if (VD->getType().getNonReferenceType()->isScalarType())
2104     return OMPC_DEFAULTMAP_scalar;
2105   return OMPC_DEFAULTMAP_aggregate;
2106 }
2107 
isOpenMPCapturedByRef(const ValueDecl * D,unsigned Level,unsigned OpenMPCaptureLevel) const2108 bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2109                                        unsigned OpenMPCaptureLevel) const {
2110   assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2111 
2112   ASTContext &Ctx = getASTContext();
2113   bool IsByRef = true;
2114 
2115   // Find the directive that is associated with the provided scope.
2116   D = cast<ValueDecl>(D->getCanonicalDecl());
2117   QualType Ty = D->getType();
2118 
2119   bool IsVariableUsedInMapClause = false;
2120   if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2121     // This table summarizes how a given variable should be passed to the device
2122     // given its type and the clauses where it appears. This table is based on
2123     // the description in OpenMP 4.5 [2.10.4, target Construct] and
2124     // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2125     //
2126     // =========================================================================
2127     // | type |  defaultmap   | pvt | first | is_device_ptr |    map   | res.  |
2128     // |      |(tofrom:scalar)|     |  pvt  |               |has_dv_adr|       |
2129     // =========================================================================
2130     // | scl  |               |     |       |       -       |          | bycopy|
2131     // | scl  |               |  -  |   x   |       -       |     -    | bycopy|
2132     // | scl  |               |  x  |   -   |       -       |     -    | null  |
2133     // | scl  |       x       |     |       |       -       |          | byref |
2134     // | scl  |       x       |  -  |   x   |       -       |     -    | bycopy|
2135     // | scl  |       x       |  x  |   -   |       -       |     -    | null  |
2136     // | scl  |               |  -  |   -   |       -       |     x    | byref |
2137     // | scl  |       x       |  -  |   -   |       -       |     x    | byref |
2138     //
2139     // | agg  |      n.a.     |     |       |       -       |          | byref |
2140     // | agg  |      n.a.     |  -  |   x   |       -       |     -    | byref |
2141     // | agg  |      n.a.     |  x  |   -   |       -       |     -    | null  |
2142     // | agg  |      n.a.     |  -  |   -   |       -       |     x    | byref |
2143     // | agg  |      n.a.     |  -  |   -   |       -       |    x[]   | byref |
2144     //
2145     // | ptr  |      n.a.     |     |       |       -       |          | bycopy|
2146     // | ptr  |      n.a.     |  -  |   x   |       -       |     -    | bycopy|
2147     // | ptr  |      n.a.     |  x  |   -   |       -       |     -    | null  |
2148     // | ptr  |      n.a.     |  -  |   -   |       -       |     x    | byref |
2149     // | ptr  |      n.a.     |  -  |   -   |       -       |    x[]   | bycopy|
2150     // | ptr  |      n.a.     |  -  |   -   |       x       |          | bycopy|
2151     // | ptr  |      n.a.     |  -  |   -   |       x       |     x    | bycopy|
2152     // | ptr  |      n.a.     |  -  |   -   |       x       |    x[]   | bycopy|
2153     // =========================================================================
2154     // Legend:
2155     //  scl - scalar
2156     //  ptr - pointer
2157     //  agg - aggregate
2158     //  x - applies
2159     //  - - invalid in this combination
2160     //  [] - mapped with an array section
2161     //  byref - should be mapped by reference
2162     //  byval - should be mapped by value
2163     //  null - initialize a local variable to null on the device
2164     //
2165     // Observations:
2166     //  - All scalar declarations that show up in a map clause have to be passed
2167     //    by reference, because they may have been mapped in the enclosing data
2168     //    environment.
2169     //  - If the scalar value does not fit the size of uintptr, it has to be
2170     //    passed by reference, regardless the result in the table above.
2171     //  - For pointers mapped by value that have either an implicit map or an
2172     //    array section, the runtime library may pass the NULL value to the
2173     //    device instead of the value passed to it by the compiler.
2174 
2175     if (Ty->isReferenceType())
2176       Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2177 
2178     // Locate map clauses and see if the variable being captured is referred to
2179     // in any of those clauses. Here we only care about variables, not fields,
2180     // because fields are part of aggregates.
2181     bool IsVariableAssociatedWithSection = false;
2182 
2183     DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2184         D, Level,
2185         [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2186          D](OMPClauseMappableExprCommon::MappableExprComponentListRef
2187                 MapExprComponents,
2188             OpenMPClauseKind WhereFoundClauseKind) {
2189           // Both map and has_device_addr clauses information influences how a
2190           // variable is captured. E.g. is_device_ptr does not require changing
2191           // the default behavior.
2192           if (WhereFoundClauseKind != OMPC_map &&
2193               WhereFoundClauseKind != OMPC_has_device_addr)
2194             return false;
2195 
2196           auto EI = MapExprComponents.rbegin();
2197           auto EE = MapExprComponents.rend();
2198 
2199           assert(EI != EE && "Invalid map expression!");
2200 
2201           if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2202             IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2203 
2204           ++EI;
2205           if (EI == EE)
2206             return false;
2207           auto Last = std::prev(EE);
2208           const auto *UO =
2209               dyn_cast<UnaryOperator>(Last->getAssociatedExpression());
2210           if ((UO && UO->getOpcode() == UO_Deref) ||
2211               isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) ||
2212               isa<ArraySectionExpr>(Last->getAssociatedExpression()) ||
2213               isa<MemberExpr>(EI->getAssociatedExpression()) ||
2214               isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) {
2215             IsVariableAssociatedWithSection = true;
2216             // There is nothing more we need to know about this variable.
2217             return true;
2218           }
2219 
2220           // Keep looking for more map info.
2221           return false;
2222         });
2223 
2224     if (IsVariableUsedInMapClause) {
2225       // If variable is identified in a map clause it is always captured by
2226       // reference except if it is a pointer that is dereferenced somehow.
2227       IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2228     } else {
2229       // By default, all the data that has a scalar type is mapped by copy
2230       // (except for reduction variables).
2231       // Defaultmap scalar is mutual exclusive to defaultmap pointer
2232       IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2233                  !Ty->isAnyPointerType()) ||
2234                 !Ty->isScalarType() ||
2235                 DSAStack->isDefaultmapCapturedByRef(
2236                     Level, getVariableCategoryFromDecl(getLangOpts(), D)) ||
2237                 DSAStack->hasExplicitDSA(
2238                     D,
2239                     [](OpenMPClauseKind K, bool AppliedToPointee) {
2240                       return K == OMPC_reduction && !AppliedToPointee;
2241                     },
2242                     Level);
2243     }
2244   }
2245 
2246   if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2247     IsByRef =
2248         ((IsVariableUsedInMapClause &&
2249           DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2250               OMPD_target) ||
2251          !(DSAStack->hasExplicitDSA(
2252                D,
2253                [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2254                  return K == OMPC_firstprivate ||
2255                         (K == OMPC_reduction && AppliedToPointee);
2256                },
2257                Level, /*NotLastprivate=*/true) ||
2258            DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2259         // If the variable is artificial and must be captured by value - try to
2260         // capture by value.
2261         !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2262           !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2263         // If the variable is implicitly firstprivate and scalar - capture by
2264         // copy
2265         !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2266            DSAStack->getDefaultDSA() == DSA_private) &&
2267           !DSAStack->hasExplicitDSA(
2268               D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2269               Level) &&
2270           !DSAStack->isLoopControlVariable(D, Level).first);
2271   }
2272 
2273   // When passing data by copy, we need to make sure it fits the uintptr size
2274   // and alignment, because the runtime library only deals with uintptr types.
2275   // If it does not fit the uintptr size, we need to pass the data by reference
2276   // instead.
2277   if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) >
2278                        Ctx.getTypeSizeInChars(Ctx.getUIntPtrType()) ||
2279                    Ctx.getAlignOfGlobalVarInChars(Ty, dyn_cast<VarDecl>(D)) >
2280                        Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2281     IsByRef = true;
2282   }
2283 
2284   return IsByRef;
2285 }
2286 
getOpenMPNestingLevel() const2287 unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2288   assert(getLangOpts().OpenMP);
2289   return DSAStack->getNestingLevel();
2290 }
2291 
isInOpenMPTaskUntiedContext() const2292 bool SemaOpenMP::isInOpenMPTaskUntiedContext() const {
2293   return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2294          DSAStack->isUntiedRegion();
2295 }
2296 
isInOpenMPTargetExecutionDirective() const2297 bool SemaOpenMP::isInOpenMPTargetExecutionDirective() const {
2298   return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2299           !DSAStack->isClauseParsingMode()) ||
2300          DSAStack->hasDirective(
2301              [](OpenMPDirectiveKind K, const DeclarationNameInfo &,
2302                 SourceLocation) -> bool {
2303                return isOpenMPTargetExecutionDirective(K);
2304              },
2305              false);
2306 }
2307 
isOpenMPRebuildMemberExpr(ValueDecl * D)2308 bool SemaOpenMP::isOpenMPRebuildMemberExpr(ValueDecl *D) {
2309   // Only rebuild for Field.
2310   if (!isa<FieldDecl>(D))
2311     return false;
2312   DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2313       D,
2314       [](OpenMPClauseKind C, bool AppliedToPointee,
2315          DefaultDataSharingAttributes DefaultAttr) {
2316         return isOpenMPPrivate(C) && !AppliedToPointee &&
2317                (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2318       },
2319       [](OpenMPDirectiveKind) { return true; },
2320       DSAStack->isClauseParsingMode());
2321   if (DVarPrivate.CKind != OMPC_unknown)
2322     return true;
2323   return false;
2324 }
2325 
2326 static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
2327                                              Expr *CaptureExpr, bool WithInit,
2328                                              DeclContext *CurContext,
2329                                              bool AsExpression);
2330 
isOpenMPCapturedDecl(ValueDecl * D,bool CheckScopeInfo,unsigned StopAt)2331 VarDecl *SemaOpenMP::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
2332                                           unsigned StopAt) {
2333   assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2334   D = getCanonicalDecl(D);
2335 
2336   auto *VD = dyn_cast<VarDecl>(D);
2337   // Do not capture constexpr variables.
2338   if (VD && VD->isConstexpr())
2339     return nullptr;
2340 
2341   // If we want to determine whether the variable should be captured from the
2342   // perspective of the current capturing scope, and we've already left all the
2343   // capturing scopes of the top directive on the stack, check from the
2344   // perspective of its parent directive (if any) instead.
2345   DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2346       *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2347 
2348   // If we are attempting to capture a global variable in a directive with
2349   // 'target' we return true so that this global is also mapped to the device.
2350   //
2351   if (VD && !VD->hasLocalStorage() &&
2352       (SemaRef.getCurCapturedRegion() || SemaRef.getCurBlock() ||
2353        SemaRef.getCurLambda())) {
2354     if (isInOpenMPTargetExecutionDirective()) {
2355       DSAStackTy::DSAVarData DVarTop =
2356           DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2357       if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2358         return VD;
2359       // If the declaration is enclosed in a 'declare target' directive,
2360       // then it should not be captured.
2361       //
2362       if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2363         return nullptr;
2364       CapturedRegionScopeInfo *CSI = nullptr;
2365       for (FunctionScopeInfo *FSI : llvm::drop_begin(
2366                llvm::reverse(SemaRef.FunctionScopes),
2367                CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2368                               : 0)) {
2369         if (!isa<CapturingScopeInfo>(FSI))
2370           return nullptr;
2371         if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2372           if (RSI->CapRegionKind == CR_OpenMP) {
2373             CSI = RSI;
2374             break;
2375           }
2376       }
2377       assert(CSI && "Failed to find CapturedRegionScopeInfo");
2378       SmallVector<OpenMPDirectiveKind, 4> Regions;
2379       getOpenMPCaptureRegions(Regions,
2380                               DSAStack->getDirective(CSI->OpenMPLevel));
2381       if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2382         return VD;
2383     }
2384     if (isInOpenMPDeclareTargetContext()) {
2385       // Try to mark variable as declare target if it is used in capturing
2386       // regions.
2387       if (getLangOpts().OpenMP <= 45 &&
2388           !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2389         checkDeclIsAllowedInOpenMPTarget(nullptr, VD);
2390       return nullptr;
2391     }
2392   }
2393 
2394   if (CheckScopeInfo) {
2395     bool OpenMPFound = false;
2396     for (unsigned I = StopAt + 1; I > 0; --I) {
2397       FunctionScopeInfo *FSI = SemaRef.FunctionScopes[I - 1];
2398       if (!isa<CapturingScopeInfo>(FSI))
2399         return nullptr;
2400       if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2401         if (RSI->CapRegionKind == CR_OpenMP) {
2402           OpenMPFound = true;
2403           break;
2404         }
2405     }
2406     if (!OpenMPFound)
2407       return nullptr;
2408   }
2409 
2410   if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2411       (!DSAStack->isClauseParsingMode() ||
2412        DSAStack->getParentDirective() != OMPD_unknown)) {
2413     auto &&Info = DSAStack->isLoopControlVariable(D);
2414     if (Info.first ||
2415         (VD && VD->hasLocalStorage() &&
2416          isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2417         (VD && DSAStack->isForceVarCapturing()))
2418       return VD ? VD : Info.second;
2419     DSAStackTy::DSAVarData DVarTop =
2420         DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2421     if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2422         (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee))
2423       return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2424     // Threadprivate variables must not be captured.
2425     if (isOpenMPThreadPrivate(DVarTop.CKind))
2426       return nullptr;
2427     // The variable is not private or it is the variable in the directive with
2428     // default(none) clause and not used in any clause.
2429     DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2430         D,
2431         [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2432           return isOpenMPPrivate(C) && !AppliedToPointee;
2433         },
2434         [](OpenMPDirectiveKind) { return true; },
2435         DSAStack->isClauseParsingMode());
2436     // Global shared must not be captured.
2437     if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2438         ((DSAStack->getDefaultDSA() != DSA_none &&
2439           DSAStack->getDefaultDSA() != DSA_private &&
2440           DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2441          DVarTop.CKind == OMPC_shared))
2442       return nullptr;
2443     auto *FD = dyn_cast<FieldDecl>(D);
2444     if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2445         !DVarPrivate.PrivateCopy) {
2446       DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2447           D,
2448           [](OpenMPClauseKind C, bool AppliedToPointee,
2449              DefaultDataSharingAttributes DefaultAttr) {
2450             return isOpenMPPrivate(C) && !AppliedToPointee &&
2451                    (DefaultAttr == DSA_firstprivate ||
2452                     DefaultAttr == DSA_private);
2453           },
2454           [](OpenMPDirectiveKind) { return true; },
2455           DSAStack->isClauseParsingMode());
2456       if (DVarPrivate.CKind == OMPC_unknown)
2457         return nullptr;
2458 
2459       VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2460       if (VD)
2461         return VD;
2462       if (SemaRef.getCurrentThisType().isNull())
2463         return nullptr;
2464       Expr *ThisExpr = SemaRef.BuildCXXThisExpr(SourceLocation(),
2465                                                 SemaRef.getCurrentThisType(),
2466                                                 /*IsImplicit=*/true);
2467       const CXXScopeSpec CS = CXXScopeSpec();
2468       Expr *ME = SemaRef.BuildMemberExpr(
2469           ThisExpr, /*IsArrow=*/true, SourceLocation(),
2470           NestedNameSpecifierLoc(), SourceLocation(), FD,
2471           DeclAccessPair::make(FD, FD->getAccess()),
2472           /*HadMultipleCandidates=*/false, DeclarationNameInfo(), FD->getType(),
2473           VK_LValue, OK_Ordinary);
2474       OMPCapturedExprDecl *CD = buildCaptureDecl(
2475           SemaRef, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2476           SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2477       DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2478           SemaRef, CD, CD->getType().getNonReferenceType(), SourceLocation());
2479       VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2480       DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2481       return VD;
2482     }
2483     if (DVarPrivate.CKind != OMPC_unknown ||
2484         (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2485                 DSAStack->getDefaultDSA() == DSA_private ||
2486                 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2487       return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2488   }
2489   return nullptr;
2490 }
2491 
adjustOpenMPTargetScopeIndex(unsigned & FunctionScopesIndex,unsigned Level) const2492 void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2493                                               unsigned Level) const {
2494   FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2495 }
2496 
startOpenMPLoop()2497 void SemaOpenMP::startOpenMPLoop() {
2498   assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2499   if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2500     DSAStack->loopInit();
2501 }
2502 
startOpenMPCXXRangeFor()2503 void SemaOpenMP::startOpenMPCXXRangeFor() {
2504   assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2505   if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2506     DSAStack->resetPossibleLoopCounter();
2507     DSAStack->loopStart();
2508   }
2509 }
2510 
isOpenMPPrivateDecl(ValueDecl * D,unsigned Level,unsigned CapLevel) const2511 OpenMPClauseKind SemaOpenMP::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
2512                                                  unsigned CapLevel) const {
2513   assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2514   if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2515       (!DSAStack->isClauseParsingMode() ||
2516        DSAStack->getParentDirective() != OMPD_unknown)) {
2517     DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2518         D,
2519         [](OpenMPClauseKind C, bool AppliedToPointee,
2520            DefaultDataSharingAttributes DefaultAttr) {
2521           return isOpenMPPrivate(C) && !AppliedToPointee &&
2522                  DefaultAttr == DSA_private;
2523         },
2524         [](OpenMPDirectiveKind) { return true; },
2525         DSAStack->isClauseParsingMode());
2526     if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2527         DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2528         !DSAStack->isLoopControlVariable(D).first)
2529       return OMPC_private;
2530   }
2531   if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2532     bool IsTriviallyCopyable =
2533         D->getType().getNonReferenceType().isTriviallyCopyableType(
2534             getASTContext()) &&
2535         !D->getType()
2536              .getNonReferenceType()
2537              .getCanonicalType()
2538              ->getAsCXXRecordDecl();
2539     OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2540     SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
2541     getOpenMPCaptureRegions(CaptureRegions, DKind);
2542     if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2543         (IsTriviallyCopyable ||
2544          !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2545       if (DSAStack->hasExplicitDSA(
2546               D,
2547               [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2548               Level, /*NotLastprivate=*/true))
2549         return OMPC_firstprivate;
2550       DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2551       if (DVar.CKind != OMPC_shared &&
2552           !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2553         DSAStack->addImplicitTaskFirstprivate(Level, D);
2554         return OMPC_firstprivate;
2555       }
2556     }
2557   }
2558   if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2559       !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2560     if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2561       DSAStack->resetPossibleLoopCounter(D);
2562       DSAStack->loopStart();
2563       return OMPC_private;
2564     }
2565     if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2566          DSAStack->isLoopControlVariable(D).first) &&
2567         !DSAStack->hasExplicitDSA(
2568             D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2569             Level) &&
2570         !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2571       return OMPC_private;
2572   }
2573   if (const auto *VD = dyn_cast<VarDecl>(D)) {
2574     if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2575         DSAStack->isForceVarCapturing() &&
2576         !DSAStack->hasExplicitDSA(
2577             D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2578             Level))
2579       return OMPC_private;
2580   }
2581   // User-defined allocators are private since they must be defined in the
2582   // context of target region.
2583   if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2584       DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2585           DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2586           DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2587     return OMPC_private;
2588   return (DSAStack->hasExplicitDSA(
2589               D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2590               Level) ||
2591           (DSAStack->isClauseParsingMode() &&
2592            DSAStack->getClauseParsingMode() == OMPC_private) ||
2593           // Consider taskgroup reduction descriptor variable a private
2594           // to avoid possible capture in the region.
2595           (DSAStack->hasExplicitDirective(
2596                [](OpenMPDirectiveKind K) {
2597                  return K == OMPD_taskgroup ||
2598                         ((isOpenMPParallelDirective(K) ||
2599                           isOpenMPWorksharingDirective(K)) &&
2600                          !isOpenMPSimdDirective(K));
2601                },
2602                Level) &&
2603            DSAStack->isTaskgroupReductionRef(D, Level)))
2604              ? OMPC_private
2605              : OMPC_unknown;
2606 }
2607 
setOpenMPCaptureKind(FieldDecl * FD,const ValueDecl * D,unsigned Level)2608 void SemaOpenMP::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D,
2609                                       unsigned Level) {
2610   assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2611   D = getCanonicalDecl(D);
2612   OpenMPClauseKind OMPC = OMPC_unknown;
2613   for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2614     const unsigned NewLevel = I - 1;
2615     if (DSAStack->hasExplicitDSA(
2616             D,
2617             [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2618               if (isOpenMPPrivate(K) && !AppliedToPointee) {
2619                 OMPC = K;
2620                 return true;
2621               }
2622               return false;
2623             },
2624             NewLevel))
2625       break;
2626     if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2627             D, NewLevel,
2628             [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
2629                OpenMPClauseKind) { return true; })) {
2630       OMPC = OMPC_map;
2631       break;
2632     }
2633     if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2634                                        NewLevel)) {
2635       OMPC = OMPC_map;
2636       if (DSAStack->mustBeFirstprivateAtLevel(
2637               NewLevel, getVariableCategoryFromDecl(getLangOpts(), D)))
2638         OMPC = OMPC_firstprivate;
2639       break;
2640     }
2641   }
2642   if (OMPC != OMPC_unknown)
2643     FD->addAttr(
2644         OMPCaptureKindAttr::CreateImplicit(getASTContext(), unsigned(OMPC)));
2645 }
2646 
isOpenMPTargetCapturedDecl(const ValueDecl * D,unsigned Level,unsigned CaptureLevel) const2647 bool SemaOpenMP::isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level,
2648                                             unsigned CaptureLevel) const {
2649   assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2650   // Return true if the current level is no longer enclosed in a target region.
2651 
2652   SmallVector<OpenMPDirectiveKind, 4> Regions;
2653   getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2654   const auto *VD = dyn_cast<VarDecl>(D);
2655   return VD && !VD->hasLocalStorage() &&
2656          DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2657                                         Level) &&
2658          Regions[CaptureLevel] != OMPD_task;
2659 }
2660 
isOpenMPGlobalCapturedDecl(ValueDecl * D,unsigned Level,unsigned CaptureLevel) const2661 bool SemaOpenMP::isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level,
2662                                             unsigned CaptureLevel) const {
2663   assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2664   // Return true if the current level is no longer enclosed in a target region.
2665 
2666   if (const auto *VD = dyn_cast<VarDecl>(D)) {
2667     if (!VD->hasLocalStorage()) {
2668       if (isInOpenMPTargetExecutionDirective())
2669         return true;
2670       DSAStackTy::DSAVarData TopDVar =
2671           DSAStack->getTopDSA(D, /*FromParent=*/false);
2672       unsigned NumLevels =
2673           getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2674       if (Level == 0)
2675         // non-file scope static variable with default(firstprivate)
2676         // should be global captured.
2677         return (NumLevels == CaptureLevel + 1 &&
2678                 (TopDVar.CKind != OMPC_shared ||
2679                  DSAStack->getDefaultDSA() == DSA_firstprivate));
2680       do {
2681         --Level;
2682         DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2683         if (DVar.CKind != OMPC_shared)
2684           return true;
2685       } while (Level > 0);
2686     }
2687   }
2688   return true;
2689 }
2690 
DestroyDataSharingAttributesStack()2691 void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2692 
ActOnOpenMPBeginDeclareVariant(SourceLocation Loc,OMPTraitInfo & TI)2693 void SemaOpenMP::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc,
2694                                                 OMPTraitInfo &TI) {
2695   OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2696 }
2697 
ActOnOpenMPEndDeclareVariant()2698 void SemaOpenMP::ActOnOpenMPEndDeclareVariant() {
2699   assert(isInOpenMPDeclareVariantScope() &&
2700          "Not in OpenMP declare variant scope!");
2701 
2702   OMPDeclareVariantScopes.pop_back();
2703 }
2704 
finalizeOpenMPDelayedAnalysis(const FunctionDecl * Caller,const FunctionDecl * Callee,SourceLocation Loc)2705 void SemaOpenMP::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,
2706                                                const FunctionDecl *Callee,
2707                                                SourceLocation Loc) {
2708   assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2709   std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2710       OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2711   // Ignore host functions during device analysis.
2712   if (getLangOpts().OpenMPIsTargetDevice &&
2713       (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2714     return;
2715   // Ignore nohost functions during host analysis.
2716   if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2717       *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2718     return;
2719   const FunctionDecl *FD = Callee->getMostRecentDecl();
2720   DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2721   if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2722       *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2723     // Diagnose host function called during device codegen.
2724     StringRef HostDevTy =
2725         getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2726     Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2727     Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2728          diag::note_omp_marked_device_type_here)
2729         << HostDevTy;
2730     return;
2731   }
2732   if (!getLangOpts().OpenMPIsTargetDevice &&
2733       !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2734       *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2735     // In OpenMP 5.2 or later, if the function has a host variant then allow
2736     // that to be called instead
2737     auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2738       for (OMPDeclareVariantAttr *A :
2739            Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2740         auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2741         auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2742         std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2743             OMPDeclareTargetDeclAttr::getDeviceType(
2744                 VariantFD->getMostRecentDecl());
2745         if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2746           return true;
2747       }
2748       return false;
2749     };
2750     if (getLangOpts().OpenMP >= 52 &&
2751         Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2752       return;
2753     // Diagnose nohost function called during host codegen.
2754     StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2755         OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2756     Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2757     Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2758          diag::note_omp_marked_device_type_here)
2759         << NoHostDevTy;
2760   }
2761 }
2762 
StartOpenMPDSABlock(OpenMPDirectiveKind DKind,const DeclarationNameInfo & DirName,Scope * CurScope,SourceLocation Loc)2763 void SemaOpenMP::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
2764                                      const DeclarationNameInfo &DirName,
2765                                      Scope *CurScope, SourceLocation Loc) {
2766   DSAStack->push(DKind, DirName, CurScope, Loc);
2767   SemaRef.PushExpressionEvaluationContext(
2768       Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
2769 }
2770 
StartOpenMPClause(OpenMPClauseKind K)2771 void SemaOpenMP::StartOpenMPClause(OpenMPClauseKind K) {
2772   DSAStack->setClauseParsingMode(K);
2773 }
2774 
EndOpenMPClause()2775 void SemaOpenMP::EndOpenMPClause() {
2776   DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2777   SemaRef.CleanupVarDeclMarking();
2778 }
2779 
2780 static std::pair<ValueDecl *, bool>
2781 getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2782                SourceRange &ERange, bool AllowArraySection = false,
2783                StringRef DiagType = "");
2784 
2785 /// Check consistency of the reduction clauses.
checkReductionClauses(Sema & S,DSAStackTy * Stack,ArrayRef<OMPClause * > Clauses)2786 static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2787                                   ArrayRef<OMPClause *> Clauses) {
2788   bool InscanFound = false;
2789   SourceLocation InscanLoc;
2790   // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2791   // A reduction clause without the inscan reduction-modifier may not appear on
2792   // a construct on which a reduction clause with the inscan reduction-modifier
2793   // appears.
2794   for (OMPClause *C : Clauses) {
2795     if (C->getClauseKind() != OMPC_reduction)
2796       continue;
2797     auto *RC = cast<OMPReductionClause>(C);
2798     if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2799       InscanFound = true;
2800       InscanLoc = RC->getModifierLoc();
2801       continue;
2802     }
2803     if (RC->getModifier() == OMPC_REDUCTION_task) {
2804       // OpenMP 5.0, 2.19.5.4 reduction Clause.
2805       // A reduction clause with the task reduction-modifier may only appear on
2806       // a parallel construct, a worksharing construct or a combined or
2807       // composite construct for which any of the aforementioned constructs is a
2808       // constituent construct and simd or loop are not constituent constructs.
2809       OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2810       if (!(isOpenMPParallelDirective(CurDir) ||
2811             isOpenMPWorksharingDirective(CurDir)) ||
2812           isOpenMPSimdDirective(CurDir))
2813         S.Diag(RC->getModifierLoc(),
2814                diag::err_omp_reduction_task_not_parallel_or_worksharing);
2815       continue;
2816     }
2817   }
2818   if (InscanFound) {
2819     for (OMPClause *C : Clauses) {
2820       if (C->getClauseKind() != OMPC_reduction)
2821         continue;
2822       auto *RC = cast<OMPReductionClause>(C);
2823       if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2824         S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2825                    ? RC->getBeginLoc()
2826                    : RC->getModifierLoc(),
2827                diag::err_omp_inscan_reduction_expected);
2828         S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2829         continue;
2830       }
2831       for (Expr *Ref : RC->varlist()) {
2832         assert(Ref && "NULL expr in OpenMP nontemporal clause.");
2833         SourceLocation ELoc;
2834         SourceRange ERange;
2835         Expr *SimpleRefExpr = Ref;
2836         auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2837                                   /*AllowArraySection=*/true);
2838         ValueDecl *D = Res.first;
2839         if (!D)
2840           continue;
2841         if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2842           S.Diag(Ref->getExprLoc(),
2843                  diag::err_omp_reduction_not_inclusive_exclusive)
2844               << Ref->getSourceRange();
2845         }
2846       }
2847     }
2848   }
2849 }
2850 
2851 static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2852                                  ArrayRef<OMPClause *> Clauses);
2853 static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2854                                  bool WithInit);
2855 
2856 static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2857                               const ValueDecl *D,
2858                               const DSAStackTy::DSAVarData &DVar,
2859                               bool IsLoopIterVar = false);
2860 
EndOpenMPDSABlock(Stmt * CurDirective)2861 void SemaOpenMP::EndOpenMPDSABlock(Stmt *CurDirective) {
2862   // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2863   //  A variable of class type (or array thereof) that appears in a lastprivate
2864   //  clause requires an accessible, unambiguous default constructor for the
2865   //  class type, unless the list item is also specified in a firstprivate
2866   //  clause.
2867 
2868   auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) {
2869     SmallVector<Expr *, 8> PrivateCopies;
2870     for (Expr *DE : Clause->varlist()) {
2871       if (DE->isValueDependent() || DE->isTypeDependent()) {
2872         PrivateCopies.push_back(nullptr);
2873         continue;
2874       }
2875       auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2876       auto *VD = cast<VarDecl>(DRE->getDecl());
2877       QualType Type = VD->getType().getNonReferenceType();
2878       const DSAStackTy::DSAVarData DVar =
2879           DSAStack->getTopDSA(VD, /*FromParent=*/false);
2880       if (DVar.CKind != OMPC_lastprivate) {
2881         // The variable is also a firstprivate, so initialization sequence
2882         // for private copy is generated already.
2883         PrivateCopies.push_back(nullptr);
2884         continue;
2885       }
2886       // Generate helper private variable and initialize it with the
2887       // default value. The address of the original variable is replaced
2888       // by the address of the new private variable in CodeGen. This new
2889       // variable is not added to IdResolver, so the code in the OpenMP
2890       // region uses original variable for proper diagnostics.
2891       VarDecl *VDPrivate = buildVarDecl(
2892           SemaRef, DE->getExprLoc(), Type.getUnqualifiedType(), VD->getName(),
2893           VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2894       SemaRef.ActOnUninitializedDecl(VDPrivate);
2895       if (VDPrivate->isInvalidDecl()) {
2896         PrivateCopies.push_back(nullptr);
2897         continue;
2898       }
2899       PrivateCopies.push_back(buildDeclRefExpr(
2900           SemaRef, VDPrivate, DE->getType(), DE->getExprLoc()));
2901     }
2902     Clause->setPrivateCopies(PrivateCopies);
2903   };
2904 
2905   auto FinalizeNontemporal = [&](OMPNontemporalClause *Clause) {
2906     // Finalize nontemporal clause by handling private copies, if any.
2907     SmallVector<Expr *, 8> PrivateRefs;
2908     for (Expr *RefExpr : Clause->varlist()) {
2909       assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2910       SourceLocation ELoc;
2911       SourceRange ERange;
2912       Expr *SimpleRefExpr = RefExpr;
2913       auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
2914       if (Res.second)
2915         // It will be analyzed later.
2916         PrivateRefs.push_back(RefExpr);
2917       ValueDecl *D = Res.first;
2918       if (!D)
2919         continue;
2920 
2921       const DSAStackTy::DSAVarData DVar =
2922           DSAStack->getTopDSA(D, /*FromParent=*/false);
2923       PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2924                                              : SimpleRefExpr);
2925     }
2926     Clause->setPrivateRefs(PrivateRefs);
2927   };
2928 
2929   auto FinalizeAllocators = [&](OMPUsesAllocatorsClause *Clause) {
2930     for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2931       OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2932       auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
2933       if (!DRE)
2934         continue;
2935       ValueDecl *VD = DRE->getDecl();
2936       if (!VD || !isa<VarDecl>(VD))
2937         continue;
2938       DSAStackTy::DSAVarData DVar =
2939           DSAStack->getTopDSA(VD, /*FromParent=*/false);
2940       // OpenMP [2.12.5, target Construct]
2941       // Memory allocators that appear in a uses_allocators clause cannot
2942       // appear in other data-sharing attribute clauses or data-mapping
2943       // attribute clauses in the same construct.
2944       Expr *MapExpr = nullptr;
2945       if (DVar.RefExpr ||
2946           DSAStack->checkMappableExprComponentListsForDecl(
2947               VD, /*CurrentRegionOnly=*/true,
2948               [VD, &MapExpr](
2949                   OMPClauseMappableExprCommon::MappableExprComponentListRef
2950                       MapExprComponents,
2951                   OpenMPClauseKind C) {
2952                 auto MI = MapExprComponents.rbegin();
2953                 auto ME = MapExprComponents.rend();
2954                 if (MI != ME &&
2955                     MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2956                         VD->getCanonicalDecl()) {
2957                   MapExpr = MI->getAssociatedExpression();
2958                   return true;
2959                 }
2960                 return false;
2961               })) {
2962         Diag(D.Allocator->getExprLoc(), diag::err_omp_allocator_used_in_clauses)
2963             << D.Allocator->getSourceRange();
2964         if (DVar.RefExpr)
2965           reportOriginalDsa(SemaRef, DSAStack, VD, DVar);
2966         else
2967           Diag(MapExpr->getExprLoc(), diag::note_used_here)
2968               << MapExpr->getSourceRange();
2969       }
2970     }
2971   };
2972 
2973   if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2974     for (OMPClause *C : D->clauses()) {
2975       if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
2976         FinalizeLastprivate(Clause);
2977       } else if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
2978         FinalizeNontemporal(Clause);
2979       } else if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
2980         FinalizeAllocators(Clause);
2981       }
2982     }
2983     // Check allocate clauses.
2984     if (!SemaRef.CurContext->isDependentContext())
2985       checkAllocateClauses(SemaRef, DSAStack, D->clauses());
2986     checkReductionClauses(SemaRef, DSAStack, D->clauses());
2987   }
2988 
2989   DSAStack->pop();
2990   SemaRef.DiscardCleanupsInEvaluationContext();
2991   SemaRef.PopExpressionEvaluationContext();
2992 }
2993 
2994 static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
2995                                      Expr *NumIterations, Sema &SemaRef,
2996                                      Scope *S, DSAStackTy *Stack);
2997 
finishLinearClauses(Sema & SemaRef,ArrayRef<OMPClause * > Clauses,OMPLoopBasedDirective::HelperExprs & B,DSAStackTy * Stack)2998 static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
2999                                 OMPLoopBasedDirective::HelperExprs &B,
3000                                 DSAStackTy *Stack) {
3001   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
3002          "loop exprs were not built");
3003 
3004   if (SemaRef.CurContext->isDependentContext())
3005     return false;
3006 
3007   // Finalize the clauses that need pre-built expressions for CodeGen.
3008   for (OMPClause *C : Clauses) {
3009     auto *LC = dyn_cast<OMPLinearClause>(C);
3010     if (!LC)
3011       continue;
3012     if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
3013                                  B.NumIterations, SemaRef,
3014                                  SemaRef.getCurScope(), Stack))
3015       return true;
3016   }
3017 
3018   return false;
3019 }
3020 
3021 namespace {
3022 
3023 class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3024 private:
3025   Sema &SemaRef;
3026 
3027 public:
VarDeclFilterCCC(Sema & S)3028   explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
ValidateCandidate(const TypoCorrection & Candidate)3029   bool ValidateCandidate(const TypoCorrection &Candidate) override {
3030     NamedDecl *ND = Candidate.getCorrectionDecl();
3031     if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3032       return VD->hasGlobalStorage() &&
3033              SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3034                                    SemaRef.getCurScope());
3035     }
3036     return false;
3037   }
3038 
clone()3039   std::unique_ptr<CorrectionCandidateCallback> clone() override {
3040     return std::make_unique<VarDeclFilterCCC>(*this);
3041   }
3042 };
3043 
3044 class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3045 private:
3046   Sema &SemaRef;
3047 
3048 public:
VarOrFuncDeclFilterCCC(Sema & S)3049   explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
ValidateCandidate(const TypoCorrection & Candidate)3050   bool ValidateCandidate(const TypoCorrection &Candidate) override {
3051     NamedDecl *ND = Candidate.getCorrectionDecl();
3052     if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3053                isa<FunctionDecl>(ND))) {
3054       return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3055                                    SemaRef.getCurScope());
3056     }
3057     return false;
3058   }
3059 
clone()3060   std::unique_ptr<CorrectionCandidateCallback> clone() override {
3061     return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3062   }
3063 };
3064 
3065 } // namespace
3066 
ActOnOpenMPIdExpression(Scope * CurScope,CXXScopeSpec & ScopeSpec,const DeclarationNameInfo & Id,OpenMPDirectiveKind Kind)3067 ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope *CurScope,
3068                                                CXXScopeSpec &ScopeSpec,
3069                                                const DeclarationNameInfo &Id,
3070                                                OpenMPDirectiveKind Kind) {
3071   ASTContext &Context = getASTContext();
3072   unsigned OMPVersion = getLangOpts().OpenMP;
3073   LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName);
3074   SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
3075                            /*ObjectType=*/QualType(),
3076                            /*AllowBuiltinCreation=*/true);
3077 
3078   if (Lookup.isAmbiguous())
3079     return ExprError();
3080 
3081   VarDecl *VD;
3082   if (!Lookup.isSingleResult()) {
3083     VarDeclFilterCCC CCC(SemaRef);
3084     if (TypoCorrection Corrected =
3085             SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
3086                                 CCC, CorrectTypoKind::ErrorRecovery)) {
3087       SemaRef.diagnoseTypo(
3088           Corrected,
3089           SemaRef.PDiag(Lookup.empty() ? diag::err_undeclared_var_use_suggest
3090                                        : diag::err_omp_expected_var_arg_suggest)
3091               << Id.getName());
3092       VD = Corrected.getCorrectionDeclAs<VarDecl>();
3093     } else {
3094       Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3095                                        : diag::err_omp_expected_var_arg)
3096           << Id.getName();
3097       return ExprError();
3098     }
3099   } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3100     Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3101     Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3102     return ExprError();
3103   }
3104   Lookup.suppressDiagnostics();
3105 
3106   // OpenMP [2.9.2, Syntax, C/C++]
3107   //   Variables must be file-scope, namespace-scope, or static block-scope.
3108   if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
3109     Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3110         << getOpenMPDirectiveName(Kind, OMPVersion) << !VD->isStaticLocal();
3111     bool IsDecl =
3112         VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3113     Diag(VD->getLocation(),
3114          IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3115         << VD;
3116     return ExprError();
3117   }
3118 
3119   VarDecl *CanonicalVD = VD->getCanonicalDecl();
3120   NamedDecl *ND = CanonicalVD;
3121   // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3122   //   A threadprivate directive for file-scope variables must appear outside
3123   //   any definition or declaration.
3124   if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3125       !SemaRef.getCurLexicalContext()->isTranslationUnit()) {
3126     Diag(Id.getLoc(), diag::err_omp_var_scope)
3127         << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3128     bool IsDecl =
3129         VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3130     Diag(VD->getLocation(),
3131          IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3132         << VD;
3133     return ExprError();
3134   }
3135   // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3136   //   A threadprivate directive for static class member variables must appear
3137   //   in the class definition, in the same scope in which the member
3138   //   variables are declared.
3139   if (CanonicalVD->isStaticDataMember() &&
3140       !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) {
3141     Diag(Id.getLoc(), diag::err_omp_var_scope)
3142         << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3143     bool IsDecl =
3144         VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3145     Diag(VD->getLocation(),
3146          IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3147         << VD;
3148     return ExprError();
3149   }
3150   // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3151   //   A threadprivate directive for namespace-scope variables must appear
3152   //   outside any definition or declaration other than the namespace
3153   //   definition itself.
3154   if (CanonicalVD->getDeclContext()->isNamespace() &&
3155       (!SemaRef.getCurLexicalContext()->isFileContext() ||
3156        !SemaRef.getCurLexicalContext()->Encloses(
3157            CanonicalVD->getDeclContext()))) {
3158     Diag(Id.getLoc(), diag::err_omp_var_scope)
3159         << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3160     bool IsDecl =
3161         VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3162     Diag(VD->getLocation(),
3163          IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3164         << VD;
3165     return ExprError();
3166   }
3167   // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3168   //   A threadprivate directive for static block-scope variables must appear
3169   //   in the scope of the variable and not in a nested scope.
3170   if (CanonicalVD->isLocalVarDecl() && CurScope &&
3171       !SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(), CurScope)) {
3172     Diag(Id.getLoc(), diag::err_omp_var_scope)
3173         << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3174     bool IsDecl =
3175         VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3176     Diag(VD->getLocation(),
3177          IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3178         << VD;
3179     return ExprError();
3180   }
3181 
3182   // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3183   //   A threadprivate directive must lexically precede all references to any
3184   //   of the variables in its list.
3185   if (Kind == OMPD_threadprivate && VD->isUsed() &&
3186       !DSAStack->isThreadPrivate(VD)) {
3187     Diag(Id.getLoc(), diag::err_omp_var_used)
3188         << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3189     return ExprError();
3190   }
3191 
3192   QualType ExprType = VD->getType().getNonReferenceType();
3193   return DeclRefExpr::Create(Context, NestedNameSpecifierLoc(),
3194                              SourceLocation(), VD,
3195                              /*RefersToEnclosingVariableOrCapture=*/false,
3196                              Id.getLoc(), ExprType, VK_LValue);
3197 }
3198 
3199 SemaOpenMP::DeclGroupPtrTy
ActOnOpenMPThreadprivateDirective(SourceLocation Loc,ArrayRef<Expr * > VarList)3200 SemaOpenMP::ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
3201                                               ArrayRef<Expr *> VarList) {
3202   if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3203     SemaRef.CurContext->addDecl(D);
3204     return DeclGroupPtrTy::make(DeclGroupRef(D));
3205   }
3206   return nullptr;
3207 }
3208 
3209 namespace {
3210 class LocalVarRefChecker final
3211     : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3212   Sema &SemaRef;
3213 
3214 public:
VisitDeclRefExpr(const DeclRefExpr * E)3215   bool VisitDeclRefExpr(const DeclRefExpr *E) {
3216     if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3217       if (VD->hasLocalStorage()) {
3218         SemaRef.Diag(E->getBeginLoc(),
3219                      diag::err_omp_local_var_in_threadprivate_init)
3220             << E->getSourceRange();
3221         SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3222             << VD << VD->getSourceRange();
3223         return true;
3224       }
3225     }
3226     return false;
3227   }
VisitStmt(const Stmt * S)3228   bool VisitStmt(const Stmt *S) {
3229     for (const Stmt *Child : S->children()) {
3230       if (Child && Visit(Child))
3231         return true;
3232     }
3233     return false;
3234   }
LocalVarRefChecker(Sema & SemaRef)3235   explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3236 };
3237 } // namespace
3238 
3239 OMPThreadPrivateDecl *
CheckOMPThreadPrivateDecl(SourceLocation Loc,ArrayRef<Expr * > VarList)3240 SemaOpenMP::CheckOMPThreadPrivateDecl(SourceLocation Loc,
3241                                       ArrayRef<Expr *> VarList) {
3242   ASTContext &Context = getASTContext();
3243   SmallVector<Expr *, 8> Vars;
3244   for (Expr *RefExpr : VarList) {
3245     auto *DE = cast<DeclRefExpr>(RefExpr);
3246     auto *VD = cast<VarDecl>(DE->getDecl());
3247     SourceLocation ILoc = DE->getExprLoc();
3248 
3249     // Mark variable as used.
3250     VD->setReferenced();
3251     VD->markUsed(Context);
3252 
3253     QualType QType = VD->getType();
3254     if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3255       // It will be analyzed later.
3256       Vars.push_back(DE);
3257       continue;
3258     }
3259 
3260     // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3261     //   A threadprivate variable must not have an incomplete type.
3262     if (SemaRef.RequireCompleteType(
3263             ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) {
3264       continue;
3265     }
3266 
3267     // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3268     //   A threadprivate variable must not have a reference type.
3269     if (VD->getType()->isReferenceType()) {
3270       unsigned OMPVersion = getLangOpts().OpenMP;
3271       Diag(ILoc, diag::err_omp_ref_type_arg)
3272           << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion)
3273           << VD->getType();
3274       bool IsDecl =
3275           VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3276       Diag(VD->getLocation(),
3277            IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3278           << VD;
3279       continue;
3280     }
3281 
3282     // Check if this is a TLS variable. If TLS is not being supported, produce
3283     // the corresponding diagnostic.
3284     if ((VD->getTLSKind() != VarDecl::TLS_None &&
3285          !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3286            getLangOpts().OpenMPUseTLS &&
3287            getASTContext().getTargetInfo().isTLSSupported())) ||
3288         (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3289          !VD->isLocalVarDecl())) {
3290       Diag(ILoc, diag::err_omp_var_thread_local)
3291           << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3292       bool IsDecl =
3293           VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3294       Diag(VD->getLocation(),
3295            IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3296           << VD;
3297       continue;
3298     }
3299 
3300     // Check if initial value of threadprivate variable reference variable with
3301     // local storage (it is not supported by runtime).
3302     if (const Expr *Init = VD->getAnyInitializer()) {
3303       LocalVarRefChecker Checker(SemaRef);
3304       if (Checker.Visit(Init))
3305         continue;
3306     }
3307 
3308     Vars.push_back(RefExpr);
3309     DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3310     VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3311         Context, SourceRange(Loc, Loc)));
3312     if (ASTMutationListener *ML = Context.getASTMutationListener())
3313       ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3314   }
3315   OMPThreadPrivateDecl *D = nullptr;
3316   if (!Vars.empty()) {
3317     D = OMPThreadPrivateDecl::Create(Context, SemaRef.getCurLexicalContext(),
3318                                      Loc, Vars);
3319     D->setAccess(AS_public);
3320   }
3321   return D;
3322 }
3323 
3324 static OMPAllocateDeclAttr::AllocatorTypeTy
getAllocatorKind(Sema & S,DSAStackTy * Stack,Expr * Allocator)3325 getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3326   if (!Allocator)
3327     return OMPAllocateDeclAttr::OMPNullMemAlloc;
3328   if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3329       Allocator->isInstantiationDependent() ||
3330       Allocator->containsUnexpandedParameterPack())
3331     return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3332   auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3333   llvm::FoldingSetNodeID AEId;
3334   const Expr *AE = Allocator->IgnoreParenImpCasts();
3335   AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3336   for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3337     auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3338     const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3339     llvm::FoldingSetNodeID DAEId;
3340     DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3341                                             /*Canonical=*/true);
3342     if (AEId == DAEId) {
3343       AllocatorKindRes = AllocatorKind;
3344       break;
3345     }
3346   }
3347   return AllocatorKindRes;
3348 }
3349 
checkPreviousOMPAllocateAttribute(Sema & S,DSAStackTy * Stack,Expr * RefExpr,VarDecl * VD,OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,Expr * Allocator)3350 static bool checkPreviousOMPAllocateAttribute(
3351     Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3352     OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3353   if (!VD->hasAttr<OMPAllocateDeclAttr>())
3354     return false;
3355   const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3356   Expr *PrevAllocator = A->getAllocator();
3357   OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3358       getAllocatorKind(S, Stack, PrevAllocator);
3359   bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3360   if (AllocatorsMatch &&
3361       AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3362       Allocator && PrevAllocator) {
3363     const Expr *AE = Allocator->IgnoreParenImpCasts();
3364     const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3365     llvm::FoldingSetNodeID AEId, PAEId;
3366     AE->Profile(AEId, S.Context, /*Canonical=*/true);
3367     PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3368     AllocatorsMatch = AEId == PAEId;
3369   }
3370   if (!AllocatorsMatch) {
3371     SmallString<256> AllocatorBuffer;
3372     llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3373     if (Allocator)
3374       Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3375     SmallString<256> PrevAllocatorBuffer;
3376     llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3377     if (PrevAllocator)
3378       PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3379                                  S.getPrintingPolicy());
3380 
3381     SourceLocation AllocatorLoc =
3382         Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3383     SourceRange AllocatorRange =
3384         Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3385     SourceLocation PrevAllocatorLoc =
3386         PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3387     SourceRange PrevAllocatorRange =
3388         PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3389     S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3390         << (Allocator ? 1 : 0) << AllocatorStream.str()
3391         << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3392         << AllocatorRange;
3393     S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3394         << PrevAllocatorRange;
3395     return true;
3396   }
3397   return false;
3398 }
3399 
3400 static void
applyOMPAllocateAttribute(Sema & S,VarDecl * VD,OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,Expr * Allocator,Expr * Alignment,SourceRange SR)3401 applyOMPAllocateAttribute(Sema &S, VarDecl *VD,
3402                           OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3403                           Expr *Allocator, Expr *Alignment, SourceRange SR) {
3404   if (VD->hasAttr<OMPAllocateDeclAttr>())
3405     return;
3406   if (Alignment &&
3407       (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3408        Alignment->isInstantiationDependent() ||
3409        Alignment->containsUnexpandedParameterPack()))
3410     // Apply later when we have a usable value.
3411     return;
3412   if (Allocator &&
3413       (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3414        Allocator->isInstantiationDependent() ||
3415        Allocator->containsUnexpandedParameterPack()))
3416     return;
3417   auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3418                                                 Allocator, Alignment, SR);
3419   VD->addAttr(A);
3420   if (ASTMutationListener *ML = S.Context.getASTMutationListener())
3421     ML->DeclarationMarkedOpenMPAllocate(VD, A);
3422 }
3423 
ActOnOpenMPAllocateDirective(SourceLocation Loc,ArrayRef<Expr * > VarList,ArrayRef<OMPClause * > Clauses,DeclContext * Owner)3424 SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPAllocateDirective(
3425     SourceLocation Loc, ArrayRef<Expr *> VarList, ArrayRef<OMPClause *> Clauses,
3426     DeclContext *Owner) {
3427   assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3428   Expr *Alignment = nullptr;
3429   Expr *Allocator = nullptr;
3430   if (Clauses.empty()) {
3431     // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3432     // allocate directives that appear in a target region must specify an
3433     // allocator clause unless a requires directive with the dynamic_allocators
3434     // clause is present in the same compilation unit.
3435     if (getLangOpts().OpenMPIsTargetDevice &&
3436         !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3437       SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3438   } else {
3439     for (const OMPClause *C : Clauses)
3440       if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3441         Allocator = AC->getAllocator();
3442       else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3443         Alignment = AC->getAlignment();
3444       else
3445         llvm_unreachable("Unexpected clause on allocate directive");
3446   }
3447   OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3448       getAllocatorKind(SemaRef, DSAStack, Allocator);
3449   SmallVector<Expr *, 8> Vars;
3450   for (Expr *RefExpr : VarList) {
3451     auto *DE = cast<DeclRefExpr>(RefExpr);
3452     auto *VD = cast<VarDecl>(DE->getDecl());
3453 
3454     // Check if this is a TLS variable or global register.
3455     if (VD->getTLSKind() != VarDecl::TLS_None ||
3456         VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3457         (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3458          !VD->isLocalVarDecl()))
3459       continue;
3460 
3461     // If the used several times in the allocate directive, the same allocator
3462     // must be used.
3463     if (checkPreviousOMPAllocateAttribute(SemaRef, DSAStack, RefExpr, VD,
3464                                           AllocatorKind, Allocator))
3465       continue;
3466 
3467     // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3468     // If a list item has a static storage type, the allocator expression in the
3469     // allocator clause must be a constant expression that evaluates to one of
3470     // the predefined memory allocator values.
3471     if (Allocator && VD->hasGlobalStorage()) {
3472       if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3473         Diag(Allocator->getExprLoc(),
3474              diag::err_omp_expected_predefined_allocator)
3475             << Allocator->getSourceRange();
3476         bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3477                       VarDecl::DeclarationOnly;
3478         Diag(VD->getLocation(),
3479              IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3480             << VD;
3481         continue;
3482       }
3483     }
3484 
3485     Vars.push_back(RefExpr);
3486     applyOMPAllocateAttribute(SemaRef, VD, AllocatorKind, Allocator, Alignment,
3487                               DE->getSourceRange());
3488   }
3489   if (Vars.empty())
3490     return nullptr;
3491   if (!Owner)
3492     Owner = SemaRef.getCurLexicalContext();
3493   auto *D = OMPAllocateDecl::Create(getASTContext(), Owner, Loc, Vars, Clauses);
3494   D->setAccess(AS_public);
3495   Owner->addDecl(D);
3496   return DeclGroupPtrTy::make(DeclGroupRef(D));
3497 }
3498 
3499 SemaOpenMP::DeclGroupPtrTy
ActOnOpenMPRequiresDirective(SourceLocation Loc,ArrayRef<OMPClause * > ClauseList)3500 SemaOpenMP::ActOnOpenMPRequiresDirective(SourceLocation Loc,
3501                                          ArrayRef<OMPClause *> ClauseList) {
3502   OMPRequiresDecl *D = nullptr;
3503   if (!SemaRef.CurContext->isFileContext()) {
3504     Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3505   } else {
3506     D = CheckOMPRequiresDecl(Loc, ClauseList);
3507     if (D) {
3508       SemaRef.CurContext->addDecl(D);
3509       DSAStack->addRequiresDecl(D);
3510     }
3511   }
3512   return DeclGroupPtrTy::make(DeclGroupRef(D));
3513 }
3514 
ActOnOpenMPAssumesDirective(SourceLocation Loc,OpenMPDirectiveKind DKind,ArrayRef<std::string> Assumptions,bool SkippedClauses)3515 void SemaOpenMP::ActOnOpenMPAssumesDirective(SourceLocation Loc,
3516                                              OpenMPDirectiveKind DKind,
3517                                              ArrayRef<std::string> Assumptions,
3518                                              bool SkippedClauses) {
3519   if (!SkippedClauses && Assumptions.empty()) {
3520     unsigned OMPVersion = getLangOpts().OpenMP;
3521     Diag(Loc, diag::err_omp_no_clause_for_directive)
3522         << llvm::omp::getAllAssumeClauseOptions()
3523         << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion);
3524   }
3525 
3526   auto *AA =
3527       OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc);
3528   if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3529     OMPAssumeScoped.push_back(AA);
3530     return;
3531   }
3532 
3533   // Global assumes without assumption clauses are ignored.
3534   if (Assumptions.empty())
3535     return;
3536 
3537   assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3538          "Unexpected omp assumption directive!");
3539   OMPAssumeGlobal.push_back(AA);
3540 
3541   // The OMPAssumeGlobal scope above will take care of new declarations but
3542   // we also want to apply the assumption to existing ones, e.g., to
3543   // declarations in included headers. To this end, we traverse all existing
3544   // declaration contexts and annotate function declarations here.
3545   SmallVector<DeclContext *, 8> DeclContexts;
3546   auto *Ctx = SemaRef.CurContext;
3547   while (Ctx->getLexicalParent())
3548     Ctx = Ctx->getLexicalParent();
3549   DeclContexts.push_back(Ctx);
3550   while (!DeclContexts.empty()) {
3551     DeclContext *DC = DeclContexts.pop_back_val();
3552     for (auto *SubDC : DC->decls()) {
3553       if (SubDC->isInvalidDecl())
3554         continue;
3555       if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3556         DeclContexts.push_back(CTD->getTemplatedDecl());
3557         llvm::append_range(DeclContexts, CTD->specializations());
3558         continue;
3559       }
3560       if (auto *DC = dyn_cast<DeclContext>(SubDC))
3561         DeclContexts.push_back(DC);
3562       if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3563         F->addAttr(AA);
3564         continue;
3565       }
3566     }
3567   }
3568 }
3569 
ActOnOpenMPEndAssumesDirective()3570 void SemaOpenMP::ActOnOpenMPEndAssumesDirective() {
3571   assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3572   OMPAssumeScoped.pop_back();
3573 }
3574 
ActOnOpenMPAssumeDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)3575 StmtResult SemaOpenMP::ActOnOpenMPAssumeDirective(ArrayRef<OMPClause *> Clauses,
3576                                                   Stmt *AStmt,
3577                                                   SourceLocation StartLoc,
3578                                                   SourceLocation EndLoc) {
3579   if (!AStmt)
3580     return StmtError();
3581 
3582   return OMPAssumeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
3583                                     AStmt);
3584 }
3585 
3586 OMPRequiresDecl *
CheckOMPRequiresDecl(SourceLocation Loc,ArrayRef<OMPClause * > ClauseList)3587 SemaOpenMP::CheckOMPRequiresDecl(SourceLocation Loc,
3588                                  ArrayRef<OMPClause *> ClauseList) {
3589   /// For target specific clauses, the requires directive cannot be
3590   /// specified after the handling of any of the target regions in the
3591   /// current compilation unit.
3592   ArrayRef<SourceLocation> TargetLocations =
3593       DSAStack->getEncounteredTargetLocs();
3594   SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3595   if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3596     for (const OMPClause *CNew : ClauseList) {
3597       // Check if any of the requires clauses affect target regions.
3598       if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3599           isa<OMPUnifiedAddressClause>(CNew) ||
3600           isa<OMPReverseOffloadClause>(CNew) ||
3601           isa<OMPDynamicAllocatorsClause>(CNew)) {
3602         Diag(Loc, diag::err_omp_directive_before_requires)
3603             << "target" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3604         for (SourceLocation TargetLoc : TargetLocations) {
3605           Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3606               << "target";
3607         }
3608       } else if (!AtomicLoc.isInvalid() &&
3609                  isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3610         Diag(Loc, diag::err_omp_directive_before_requires)
3611             << "atomic" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3612         Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3613             << "atomic";
3614       }
3615     }
3616   }
3617 
3618   if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3619     return OMPRequiresDecl::Create(
3620         getASTContext(), SemaRef.getCurLexicalContext(), Loc, ClauseList);
3621   return nullptr;
3622 }
3623 
reportOriginalDsa(Sema & SemaRef,const DSAStackTy * Stack,const ValueDecl * D,const DSAStackTy::DSAVarData & DVar,bool IsLoopIterVar)3624 static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3625                               const ValueDecl *D,
3626                               const DSAStackTy::DSAVarData &DVar,
3627                               bool IsLoopIterVar) {
3628   if (DVar.RefExpr) {
3629     SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3630         << getOpenMPClauseNameForDiag(DVar.CKind);
3631     return;
3632   }
3633   enum {
3634     PDSA_StaticMemberShared,
3635     PDSA_StaticLocalVarShared,
3636     PDSA_LoopIterVarPrivate,
3637     PDSA_LoopIterVarLinear,
3638     PDSA_LoopIterVarLastprivate,
3639     PDSA_ConstVarShared,
3640     PDSA_GlobalVarShared,
3641     PDSA_TaskVarFirstprivate,
3642     PDSA_LocalVarPrivate,
3643     PDSA_Implicit
3644   } Reason = PDSA_Implicit;
3645   bool ReportHint = false;
3646   auto ReportLoc = D->getLocation();
3647   auto *VD = dyn_cast<VarDecl>(D);
3648   if (IsLoopIterVar) {
3649     if (DVar.CKind == OMPC_private)
3650       Reason = PDSA_LoopIterVarPrivate;
3651     else if (DVar.CKind == OMPC_lastprivate)
3652       Reason = PDSA_LoopIterVarLastprivate;
3653     else
3654       Reason = PDSA_LoopIterVarLinear;
3655   } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3656              DVar.CKind == OMPC_firstprivate) {
3657     Reason = PDSA_TaskVarFirstprivate;
3658     ReportLoc = DVar.ImplicitDSALoc;
3659   } else if (VD && VD->isStaticLocal())
3660     Reason = PDSA_StaticLocalVarShared;
3661   else if (VD && VD->isStaticDataMember())
3662     Reason = PDSA_StaticMemberShared;
3663   else if (VD && VD->isFileVarDecl())
3664     Reason = PDSA_GlobalVarShared;
3665   else if (D->getType().isConstant(SemaRef.getASTContext()))
3666     Reason = PDSA_ConstVarShared;
3667   else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3668     ReportHint = true;
3669     Reason = PDSA_LocalVarPrivate;
3670   }
3671   if (Reason != PDSA_Implicit) {
3672     unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
3673     SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3674         << Reason << ReportHint
3675         << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
3676   } else if (DVar.ImplicitDSALoc.isValid()) {
3677     SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3678         << getOpenMPClauseNameForDiag(DVar.CKind);
3679   }
3680 }
3681 
3682 static OpenMPMapClauseKind
getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M,bool IsAggregateOrDeclareTarget)3683 getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M,
3684                              bool IsAggregateOrDeclareTarget) {
3685   OpenMPMapClauseKind Kind = OMPC_MAP_unknown;
3686   switch (M) {
3687   case OMPC_DEFAULTMAP_MODIFIER_alloc:
3688     Kind = OMPC_MAP_alloc;
3689     break;
3690   case OMPC_DEFAULTMAP_MODIFIER_to:
3691     Kind = OMPC_MAP_to;
3692     break;
3693   case OMPC_DEFAULTMAP_MODIFIER_from:
3694     Kind = OMPC_MAP_from;
3695     break;
3696   case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3697     Kind = OMPC_MAP_tofrom;
3698     break;
3699   case OMPC_DEFAULTMAP_MODIFIER_present:
3700     // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3701     // If implicit-behavior is present, each variable referenced in the
3702     // construct in the category specified by variable-category is treated as if
3703     // it had been listed in a map clause with the map-type of alloc and
3704     // map-type-modifier of present.
3705     Kind = OMPC_MAP_alloc;
3706     break;
3707   case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3708   case OMPC_DEFAULTMAP_MODIFIER_last:
3709     llvm_unreachable("Unexpected defaultmap implicit behavior");
3710   case OMPC_DEFAULTMAP_MODIFIER_none:
3711   case OMPC_DEFAULTMAP_MODIFIER_default:
3712   case OMPC_DEFAULTMAP_MODIFIER_unknown:
3713     // IsAggregateOrDeclareTarget could be true if:
3714     // 1. the implicit behavior for aggregate is tofrom
3715     // 2. it's a declare target link
3716     if (IsAggregateOrDeclareTarget) {
3717       Kind = OMPC_MAP_tofrom;
3718       break;
3719     }
3720     llvm_unreachable("Unexpected defaultmap implicit behavior");
3721   }
3722   assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3723   return Kind;
3724 }
3725 
3726 namespace {
3727 struct VariableImplicitInfo {
3728   static const unsigned MapKindNum = OMPC_MAP_unknown;
3729   static const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3730 
3731   llvm::SetVector<Expr *> Privates;
3732   llvm::SetVector<Expr *> Firstprivates;
3733   llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3734   llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3735       MapModifiers[DefaultmapKindNum];
3736 };
3737 
3738 class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3739   DSAStackTy *Stack;
3740   Sema &SemaRef;
3741   OpenMPDirectiveKind DKind = OMPD_unknown;
3742   bool ErrorFound = false;
3743   bool TryCaptureCXXThisMembers = false;
3744   CapturedStmt *CS = nullptr;
3745 
3746   VariableImplicitInfo ImpInfo;
3747   SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3748   llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3749 
VisitSubCaptures(OMPExecutableDirective * S)3750   void VisitSubCaptures(OMPExecutableDirective *S) {
3751     // Check implicitly captured variables.
3752     if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3753       return;
3754     if (S->getDirectiveKind() == OMPD_atomic ||
3755         S->getDirectiveKind() == OMPD_critical ||
3756         S->getDirectiveKind() == OMPD_section ||
3757         S->getDirectiveKind() == OMPD_master ||
3758         S->getDirectiveKind() == OMPD_masked ||
3759         S->getDirectiveKind() == OMPD_scope ||
3760         S->getDirectiveKind() == OMPD_assume ||
3761         isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3762       Visit(S->getAssociatedStmt());
3763       return;
3764     }
3765     visitSubCaptures(S->getInnermostCapturedStmt());
3766     // Try to capture inner this->member references to generate correct mappings
3767     // and diagnostics.
3768     if (TryCaptureCXXThisMembers ||
3769         (isOpenMPTargetExecutionDirective(DKind) &&
3770          llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3771                       [](const CapturedStmt::Capture &C) {
3772                         return C.capturesThis();
3773                       }))) {
3774       bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3775       TryCaptureCXXThisMembers = true;
3776       Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3777       TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3778     }
3779     // In tasks firstprivates are not captured anymore, need to analyze them
3780     // explicitly.
3781     if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3782         !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3783       for (OMPClause *C : S->clauses())
3784         if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3785           for (Expr *Ref : FC->varlist())
3786             Visit(Ref);
3787         }
3788     }
3789   }
3790 
3791 public:
VisitDeclRefExpr(DeclRefExpr * E)3792   void VisitDeclRefExpr(DeclRefExpr *E) {
3793     if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3794         E->isValueDependent() || E->containsUnexpandedParameterPack() ||
3795         E->isInstantiationDependent() ||
3796         E->isNonOdrUse() == clang::NOUR_Unevaluated)
3797       return;
3798     if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3799       // Check the datasharing rules for the expressions in the clauses.
3800       if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3801                   !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3802                   !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3803         if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3804           if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3805             Visit(CED->getInit());
3806             return;
3807           }
3808       } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3809         // Do not analyze internal variables and do not enclose them into
3810         // implicit clauses.
3811         if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3812           return;
3813       VD = VD->getCanonicalDecl();
3814       // Skip internally declared variables.
3815       if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3816           !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3817           !Stack->isImplicitTaskFirstprivate(VD))
3818         return;
3819       // Skip allocators in uses_allocators clauses.
3820       if (Stack->isUsesAllocatorsDecl(VD))
3821         return;
3822 
3823       DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3824       // Check if the variable has explicit DSA set and stop analysis if it so.
3825       if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3826         return;
3827 
3828       // Skip internally declared static variables.
3829       std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3830           OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3831       if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3832           (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3833            !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3834           !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3835           !Stack->isImplicitTaskFirstprivate(VD))
3836         return;
3837 
3838       SourceLocation ELoc = E->getExprLoc();
3839       // The default(none) clause requires that each variable that is referenced
3840       // in the construct, and does not have a predetermined data-sharing
3841       // attribute, must have its data-sharing attribute explicitly determined
3842       // by being listed in a data-sharing attribute clause.
3843       if (DVar.CKind == OMPC_unknown &&
3844           (Stack->getDefaultDSA() == DSA_none ||
3845            Stack->getDefaultDSA() == DSA_private ||
3846            Stack->getDefaultDSA() == DSA_firstprivate) &&
3847           isImplicitOrExplicitTaskingRegion(DKind) &&
3848           VarsWithInheritedDSA.count(VD) == 0) {
3849         bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3850         if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3851                               Stack->getDefaultDSA() == DSA_private)) {
3852           DSAStackTy::DSAVarData DVar =
3853               Stack->getImplicitDSA(VD, /*FromParent=*/false);
3854           InheritedDSA = DVar.CKind == OMPC_unknown;
3855         }
3856         if (InheritedDSA)
3857           VarsWithInheritedDSA[VD] = E;
3858         if (Stack->getDefaultDSA() == DSA_none)
3859           return;
3860       }
3861 
3862       // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3863       // If implicit-behavior is none, each variable referenced in the
3864       // construct that does not have a predetermined data-sharing attribute
3865       // and does not appear in a to or link clause on a declare target
3866       // directive must be listed in a data-mapping attribute clause, a
3867       // data-sharing attribute clause (including a data-sharing attribute
3868       // clause on a combined construct where target. is one of the
3869       // constituent constructs), or an is_device_ptr clause.
3870       OpenMPDefaultmapClauseKind ClauseKind =
3871           getVariableCategoryFromDecl(SemaRef.getLangOpts(), VD);
3872       if (SemaRef.getLangOpts().OpenMP >= 50) {
3873         bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3874                               OMPC_DEFAULTMAP_MODIFIER_none;
3875         if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3876             VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3877           // Only check for data-mapping attribute and is_device_ptr here
3878           // since we have already make sure that the declaration does not
3879           // have a data-sharing attribute above
3880           if (!Stack->checkMappableExprComponentListsForDecl(
3881                   VD, /*CurrentRegionOnly=*/true,
3882                   [VD](OMPClauseMappableExprCommon::MappableExprComponentListRef
3883                            MapExprComponents,
3884                        OpenMPClauseKind) {
3885                     auto MI = MapExprComponents.rbegin();
3886                     auto ME = MapExprComponents.rend();
3887                     return MI != ME && MI->getAssociatedDeclaration() == VD;
3888                   })) {
3889             VarsWithInheritedDSA[VD] = E;
3890             return;
3891           }
3892         }
3893       }
3894       if (SemaRef.getLangOpts().OpenMP > 50) {
3895         bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3896                                  OMPC_DEFAULTMAP_MODIFIER_present;
3897         if (IsModifierPresent) {
3898           if (!llvm::is_contained(ImpInfo.MapModifiers[ClauseKind],
3899                                   OMPC_MAP_MODIFIER_present)) {
3900             ImpInfo.MapModifiers[ClauseKind].push_back(
3901                 OMPC_MAP_MODIFIER_present);
3902           }
3903         }
3904       }
3905 
3906       if (isOpenMPTargetExecutionDirective(DKind) &&
3907           !Stack->isLoopControlVariable(VD).first) {
3908         if (!Stack->checkMappableExprComponentListsForDecl(
3909                 VD, /*CurrentRegionOnly=*/true,
3910                 [this](OMPClauseMappableExprCommon::MappableExprComponentListRef
3911                            StackComponents,
3912                        OpenMPClauseKind) {
3913                   if (SemaRef.LangOpts.OpenMP >= 50)
3914                     return !StackComponents.empty();
3915                   // Variable is used if it has been marked as an array, array
3916                   // section, array shaping or the variable itself.
3917                   return StackComponents.size() == 1 ||
3918                          llvm::all_of(
3919                              llvm::drop_begin(llvm::reverse(StackComponents)),
3920                              [](const OMPClauseMappableExprCommon::
3921                                     MappableComponent &MC) {
3922                                return MC.getAssociatedDeclaration() ==
3923                                           nullptr &&
3924                                       (isa<ArraySectionExpr>(
3925                                            MC.getAssociatedExpression()) ||
3926                                        isa<OMPArrayShapingExpr>(
3927                                            MC.getAssociatedExpression()) ||
3928                                        isa<ArraySubscriptExpr>(
3929                                            MC.getAssociatedExpression()));
3930                              });
3931                 })) {
3932           bool IsFirstprivate = false;
3933           // By default lambdas are captured as firstprivates.
3934           if (const auto *RD =
3935                   VD->getType().getNonReferenceType()->getAsCXXRecordDecl())
3936             IsFirstprivate = RD->isLambda();
3937           IsFirstprivate =
3938               IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3939           if (IsFirstprivate) {
3940             ImpInfo.Firstprivates.insert(E);
3941           } else {
3942             OpenMPDefaultmapClauseModifier M =
3943                 Stack->getDefaultmapModifier(ClauseKind);
3944             OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
3945                 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3946             ImpInfo.Mappings[ClauseKind][Kind].insert(E);
3947           }
3948           return;
3949         }
3950       }
3951 
3952       // OpenMP [2.9.3.6, Restrictions, p.2]
3953       //  A list item that appears in a reduction clause of the innermost
3954       //  enclosing worksharing or parallel construct may not be accessed in an
3955       //  explicit task.
3956       DVar = Stack->hasInnermostDSA(
3957           VD,
3958           [](OpenMPClauseKind C, bool AppliedToPointee) {
3959             return C == OMPC_reduction && !AppliedToPointee;
3960           },
3961           [](OpenMPDirectiveKind K) {
3962             return isOpenMPParallelDirective(K) ||
3963                    isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
3964           },
3965           /*FromParent=*/true);
3966       if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3967         ErrorFound = true;
3968         SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3969         reportOriginalDsa(SemaRef, Stack, VD, DVar);
3970         return;
3971       }
3972 
3973       // Define implicit data-sharing attributes for task.
3974       DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
3975       if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
3976            (((Stack->getDefaultDSA() == DSA_firstprivate &&
3977               DVar.CKind == OMPC_firstprivate) ||
3978              (Stack->getDefaultDSA() == DSA_private &&
3979               DVar.CKind == OMPC_private)) &&
3980             !DVar.RefExpr)) &&
3981           !Stack->isLoopControlVariable(VD).first) {
3982         if (Stack->getDefaultDSA() == DSA_private)
3983           ImpInfo.Privates.insert(E);
3984         else
3985           ImpInfo.Firstprivates.insert(E);
3986         return;
3987       }
3988 
3989       // Store implicitly used globals with declare target link for parent
3990       // target.
3991       if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
3992           *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3993         Stack->addToParentTargetRegionLinkGlobals(E);
3994         return;
3995       }
3996     }
3997   }
VisitMemberExpr(MemberExpr * E)3998   void VisitMemberExpr(MemberExpr *E) {
3999     if (E->isTypeDependent() || E->isValueDependent() ||
4000         E->containsUnexpandedParameterPack() || E->isInstantiationDependent())
4001       return;
4002     auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
4003     if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
4004       if (!FD)
4005         return;
4006       DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
4007       // Check if the variable has explicit DSA set and stop analysis if it
4008       // so.
4009       if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
4010         return;
4011 
4012       if (isOpenMPTargetExecutionDirective(DKind) &&
4013           !Stack->isLoopControlVariable(FD).first &&
4014           !Stack->checkMappableExprComponentListsForDecl(
4015               FD, /*CurrentRegionOnly=*/true,
4016               [](OMPClauseMappableExprCommon::MappableExprComponentListRef
4017                      StackComponents,
4018                  OpenMPClauseKind) {
4019                 return isa<CXXThisExpr>(
4020                     cast<MemberExpr>(
4021                         StackComponents.back().getAssociatedExpression())
4022                         ->getBase()
4023                         ->IgnoreParens());
4024               })) {
4025         // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
4026         //  A bit-field cannot appear in a map clause.
4027         //
4028         if (FD->isBitField())
4029           return;
4030 
4031         // Check to see if the member expression is referencing a class that
4032         // has already been explicitly mapped
4033         if (Stack->isClassPreviouslyMapped(TE->getType()))
4034           return;
4035 
4036         OpenMPDefaultmapClauseModifier Modifier =
4037             Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4038         OpenMPDefaultmapClauseKind ClauseKind =
4039             getVariableCategoryFromDecl(SemaRef.getLangOpts(), FD);
4040         OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
4041             Modifier, /*IsAggregateOrDeclareTarget=*/true);
4042         ImpInfo.Mappings[ClauseKind][Kind].insert(E);
4043         return;
4044       }
4045 
4046       SourceLocation ELoc = E->getExprLoc();
4047       // OpenMP [2.9.3.6, Restrictions, p.2]
4048       //  A list item that appears in a reduction clause of the innermost
4049       //  enclosing worksharing or parallel construct may not be accessed in
4050       //  an  explicit task.
4051       DVar = Stack->hasInnermostDSA(
4052           FD,
4053           [](OpenMPClauseKind C, bool AppliedToPointee) {
4054             return C == OMPC_reduction && !AppliedToPointee;
4055           },
4056           [](OpenMPDirectiveKind K) {
4057             return isOpenMPParallelDirective(K) ||
4058                    isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
4059           },
4060           /*FromParent=*/true);
4061       if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4062         ErrorFound = true;
4063         SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4064         reportOriginalDsa(SemaRef, Stack, FD, DVar);
4065         return;
4066       }
4067 
4068       // Define implicit data-sharing attributes for task.
4069       DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4070       if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4071           !Stack->isLoopControlVariable(FD).first) {
4072         // Check if there is a captured expression for the current field in the
4073         // region. Do not mark it as firstprivate unless there is no captured
4074         // expression.
4075         // TODO: try to make it firstprivate.
4076         if (DVar.CKind != OMPC_unknown)
4077           ImpInfo.Firstprivates.insert(E);
4078       }
4079       return;
4080     }
4081     if (isOpenMPTargetExecutionDirective(DKind)) {
4082       OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
4083       if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4084                                         DKind, /*NoDiagnose=*/true))
4085         return;
4086       const auto *VD = cast<ValueDecl>(
4087           CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4088       if (!Stack->checkMappableExprComponentListsForDecl(
4089               VD, /*CurrentRegionOnly=*/true,
4090               [&CurComponents](
4091                   OMPClauseMappableExprCommon::MappableExprComponentListRef
4092                       StackComponents,
4093                   OpenMPClauseKind) {
4094                 auto CCI = CurComponents.rbegin();
4095                 auto CCE = CurComponents.rend();
4096                 for (const auto &SC : llvm::reverse(StackComponents)) {
4097                   // Do both expressions have the same kind?
4098                   if (CCI->getAssociatedExpression()->getStmtClass() !=
4099                       SC.getAssociatedExpression()->getStmtClass())
4100                     if (!((isa<ArraySectionExpr>(
4101                                SC.getAssociatedExpression()) ||
4102                            isa<OMPArrayShapingExpr>(
4103                                SC.getAssociatedExpression())) &&
4104                           isa<ArraySubscriptExpr>(
4105                               CCI->getAssociatedExpression())))
4106                       return false;
4107 
4108                   const Decl *CCD = CCI->getAssociatedDeclaration();
4109                   const Decl *SCD = SC.getAssociatedDeclaration();
4110                   CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4111                   SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4112                   if (SCD != CCD)
4113                     return false;
4114                   std::advance(CCI, 1);
4115                   if (CCI == CCE)
4116                     break;
4117                 }
4118                 return true;
4119               })) {
4120         Visit(E->getBase());
4121       }
4122     } else if (!TryCaptureCXXThisMembers) {
4123       Visit(E->getBase());
4124     }
4125   }
VisitOMPExecutableDirective(OMPExecutableDirective * S)4126   void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4127     for (OMPClause *C : S->clauses()) {
4128       // Skip analysis of arguments of private clauses for task|target
4129       // directives.
4130       if (isa_and_nonnull<OMPPrivateClause>(C))
4131         continue;
4132       // Skip analysis of arguments of implicitly defined firstprivate clause
4133       // for task|target directives.
4134       // Skip analysis of arguments of implicitly defined map clause for target
4135       // directives.
4136       if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
4137                  C->isImplicit() && !isOpenMPTaskingDirective(DKind))) {
4138         for (Stmt *CC : C->children()) {
4139           if (CC)
4140             Visit(CC);
4141         }
4142       }
4143     }
4144     // Check implicitly captured variables.
4145     VisitSubCaptures(S);
4146   }
4147 
VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective * S)4148   void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) {
4149     // Loop transformation directives do not introduce data sharing
4150     VisitStmt(S);
4151   }
4152 
VisitCallExpr(CallExpr * S)4153   void VisitCallExpr(CallExpr *S) {
4154     for (Stmt *C : S->arguments()) {
4155       if (C) {
4156         // Check implicitly captured variables in the task-based directives to
4157         // check if they must be firstprivatized.
4158         Visit(C);
4159       }
4160     }
4161     if (Expr *Callee = S->getCallee()) {
4162       auto *CI = Callee->IgnoreParenImpCasts();
4163       if (auto *CE = dyn_cast<MemberExpr>(CI))
4164         Visit(CE->getBase());
4165       else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4166         Visit(CE);
4167     }
4168   }
VisitStmt(Stmt * S)4169   void VisitStmt(Stmt *S) {
4170     for (Stmt *C : S->children()) {
4171       if (C) {
4172         // Check implicitly captured variables in the task-based directives to
4173         // check if they must be firstprivatized.
4174         Visit(C);
4175       }
4176     }
4177   }
4178 
visitSubCaptures(CapturedStmt * S)4179   void visitSubCaptures(CapturedStmt *S) {
4180     for (const CapturedStmt::Capture &Cap : S->captures()) {
4181       if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4182         continue;
4183       VarDecl *VD = Cap.getCapturedVar();
4184       // Do not try to map the variable if it or its sub-component was mapped
4185       // already.
4186       if (isOpenMPTargetExecutionDirective(DKind) &&
4187           Stack->checkMappableExprComponentListsForDecl(
4188               VD, /*CurrentRegionOnly=*/true,
4189               [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
4190                  OpenMPClauseKind) { return true; }))
4191         continue;
4192       DeclRefExpr *DRE = buildDeclRefExpr(
4193           SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4194           Cap.getLocation(), /*RefersToCapture=*/true);
4195       Visit(DRE);
4196     }
4197   }
isErrorFound() const4198   bool isErrorFound() const { return ErrorFound; }
getImplicitInfo() const4199   const VariableImplicitInfo &getImplicitInfo() const { return ImpInfo; }
getVarsWithInheritedDSA() const4200   const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4201     return VarsWithInheritedDSA;
4202   }
4203 
DSAAttrChecker(DSAStackTy * S,Sema & SemaRef,CapturedStmt * CS)4204   DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4205       : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4206     DKind = S->getCurrentDirective();
4207     // Process declare target link variables for the target directives.
4208     if (isOpenMPTargetExecutionDirective(DKind)) {
4209       for (DeclRefExpr *E : Stack->getLinkGlobals())
4210         Visit(E);
4211     }
4212   }
4213 };
4214 } // namespace
4215 
handleDeclareVariantConstructTrait(DSAStackTy * Stack,OpenMPDirectiveKind DKind,bool ScopeEntry)4216 static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4217                                                OpenMPDirectiveKind DKind,
4218                                                bool ScopeEntry) {
4219   SmallVector<llvm::omp::TraitProperty, 8> Traits;
4220   if (isOpenMPTargetExecutionDirective(DKind))
4221     Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4222   if (isOpenMPTeamsDirective(DKind))
4223     Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4224   if (isOpenMPParallelDirective(DKind))
4225     Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4226   if (isOpenMPWorksharingDirective(DKind))
4227     Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4228   if (isOpenMPSimdDirective(DKind))
4229     Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4230   Stack->handleConstructTrait(Traits, ScopeEntry);
4231 }
4232 
4233 static SmallVector<SemaOpenMP::CapturedParamNameType>
getParallelRegionParams(Sema & SemaRef,bool LoopBoundSharing)4234 getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4235   ASTContext &Context = SemaRef.getASTContext();
4236   QualType KmpInt32Ty =
4237       Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4238   QualType KmpInt32PtrTy =
4239       Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4240   SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4241       std::make_pair(".global_tid.", KmpInt32PtrTy),
4242       std::make_pair(".bound_tid.", KmpInt32PtrTy),
4243   };
4244   if (LoopBoundSharing) {
4245     QualType KmpSizeTy = Context.getSizeType().withConst();
4246     Params.push_back(std::make_pair(".previous.lb.", KmpSizeTy));
4247     Params.push_back(std::make_pair(".previous.ub.", KmpSizeTy));
4248   }
4249 
4250   // __context with shared vars
4251   Params.push_back(std::make_pair(StringRef(), QualType()));
4252   return Params;
4253 }
4254 
4255 static SmallVector<SemaOpenMP::CapturedParamNameType>
getTeamsRegionParams(Sema & SemaRef)4256 getTeamsRegionParams(Sema &SemaRef) {
4257   return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4258 }
4259 
4260 static SmallVector<SemaOpenMP::CapturedParamNameType>
getTaskRegionParams(Sema & SemaRef)4261 getTaskRegionParams(Sema &SemaRef) {
4262   ASTContext &Context = SemaRef.getASTContext();
4263   QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4264   QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4265   QualType KmpInt32PtrTy =
4266       Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4267   QualType Args[] = {VoidPtrTy};
4268   FunctionProtoType::ExtProtoInfo EPI;
4269   EPI.Variadic = true;
4270   QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4271   SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4272       std::make_pair(".global_tid.", KmpInt32Ty),
4273       std::make_pair(".part_id.", KmpInt32PtrTy),
4274       std::make_pair(".privates.", VoidPtrTy),
4275       std::make_pair(
4276           ".copy_fn.",
4277           Context.getPointerType(CopyFnType).withConst().withRestrict()),
4278       std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4279       std::make_pair(StringRef(), QualType()) // __context with shared vars
4280   };
4281   return Params;
4282 }
4283 
4284 static SmallVector<SemaOpenMP::CapturedParamNameType>
getTargetRegionParams(Sema & SemaRef)4285 getTargetRegionParams(Sema &SemaRef) {
4286   ASTContext &Context = SemaRef.getASTContext();
4287   SmallVector<SemaOpenMP::CapturedParamNameType> Params;
4288   if (SemaRef.getLangOpts().OpenMPIsTargetDevice) {
4289     QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4290     Params.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4291   }
4292   // __context with shared vars
4293   Params.push_back(std::make_pair(StringRef(), QualType()));
4294   return Params;
4295 }
4296 
4297 static SmallVector<SemaOpenMP::CapturedParamNameType>
getUnknownRegionParams(Sema & SemaRef)4298 getUnknownRegionParams(Sema &SemaRef) {
4299   SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4300       std::make_pair(StringRef(), QualType()) // __context with shared vars
4301   };
4302   return Params;
4303 }
4304 
4305 static SmallVector<SemaOpenMP::CapturedParamNameType>
getTaskloopRegionParams(Sema & SemaRef)4306 getTaskloopRegionParams(Sema &SemaRef) {
4307   ASTContext &Context = SemaRef.getASTContext();
4308   QualType KmpInt32Ty =
4309       Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4310   QualType KmpUInt64Ty =
4311       Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4312   QualType KmpInt64Ty =
4313       Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4314   QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4315   QualType KmpInt32PtrTy =
4316       Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4317   QualType Args[] = {VoidPtrTy};
4318   FunctionProtoType::ExtProtoInfo EPI;
4319   EPI.Variadic = true;
4320   QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4321   SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4322       std::make_pair(".global_tid.", KmpInt32Ty),
4323       std::make_pair(".part_id.", KmpInt32PtrTy),
4324       std::make_pair(".privates.", VoidPtrTy),
4325       std::make_pair(
4326           ".copy_fn.",
4327           Context.getPointerType(CopyFnType).withConst().withRestrict()),
4328       std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4329       std::make_pair(".lb.", KmpUInt64Ty),
4330       std::make_pair(".ub.", KmpUInt64Ty),
4331       std::make_pair(".st.", KmpInt64Ty),
4332       std::make_pair(".liter.", KmpInt32Ty),
4333       std::make_pair(".reductions.", VoidPtrTy),
4334       std::make_pair(StringRef(), QualType()) // __context with shared vars
4335   };
4336   return Params;
4337 }
4338 
processCapturedRegions(Sema & SemaRef,OpenMPDirectiveKind DKind,Scope * CurScope,SourceLocation Loc)4339 static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind,
4340                                    Scope *CurScope, SourceLocation Loc) {
4341   SmallVector<OpenMPDirectiveKind> Regions;
4342   getOpenMPCaptureRegions(Regions, DKind);
4343 
4344   bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(DKind);
4345 
4346   auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4347     CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4348         SemaRef.getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4349   };
4350 
4351   for (auto [Level, RKind] : llvm::enumerate(Regions)) {
4352     switch (RKind) {
4353     // All region kinds that can be returned from `getOpenMPCaptureRegions`
4354     // are listed here.
4355     case OMPD_parallel:
4356       SemaRef.ActOnCapturedRegionStart(
4357           Loc, CurScope, CR_OpenMP,
4358           getParallelRegionParams(SemaRef, LoopBoundSharing), Level);
4359       break;
4360     case OMPD_teams:
4361       SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4362                                        getTeamsRegionParams(SemaRef), Level);
4363       break;
4364     case OMPD_task:
4365       SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4366                                        getTaskRegionParams(SemaRef), Level);
4367       // Mark this captured region as inlined, because we don't use outlined
4368       // function directly.
4369       MarkAsInlined(SemaRef.getCurCapturedRegion());
4370       break;
4371     case OMPD_taskloop:
4372       SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4373                                        getTaskloopRegionParams(SemaRef), Level);
4374       // Mark this captured region as inlined, because we don't use outlined
4375       // function directly.
4376       MarkAsInlined(SemaRef.getCurCapturedRegion());
4377       break;
4378     case OMPD_target:
4379       SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4380                                        getTargetRegionParams(SemaRef), Level);
4381       break;
4382     case OMPD_unknown:
4383       SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4384                                        getUnknownRegionParams(SemaRef));
4385       break;
4386     case OMPD_metadirective:
4387     case OMPD_nothing:
4388     default:
4389       llvm_unreachable("Unexpected capture region");
4390     }
4391   }
4392 }
4393 
ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind,Scope * CurScope)4394 void SemaOpenMP::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind,
4395                                         Scope *CurScope) {
4396   switch (DKind) {
4397   case OMPD_atomic:
4398   case OMPD_critical:
4399   case OMPD_masked:
4400   case OMPD_master:
4401   case OMPD_section:
4402   case OMPD_tile:
4403   case OMPD_stripe:
4404   case OMPD_unroll:
4405   case OMPD_reverse:
4406   case OMPD_interchange:
4407   case OMPD_assume:
4408     break;
4409   default:
4410     processCapturedRegions(SemaRef, DKind, CurScope,
4411                            DSAStack->getConstructLoc());
4412     break;
4413   }
4414 
4415   DSAStack->setContext(SemaRef.CurContext);
4416   handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
4417 }
4418 
getNumberOfConstructScopes(unsigned Level) const4419 int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4420   return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4421 }
4422 
getOpenMPCaptureLevels(OpenMPDirectiveKind DKind)4423 int SemaOpenMP::getOpenMPCaptureLevels(OpenMPDirectiveKind DKind) {
4424   SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4425   getOpenMPCaptureRegions(CaptureRegions, DKind);
4426   return CaptureRegions.size();
4427 }
4428 
buildCaptureDecl(Sema & S,IdentifierInfo * Id,Expr * CaptureExpr,bool WithInit,DeclContext * CurContext,bool AsExpression)4429 static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
4430                                              Expr *CaptureExpr, bool WithInit,
4431                                              DeclContext *CurContext,
4432                                              bool AsExpression) {
4433   assert(CaptureExpr);
4434   ASTContext &C = S.getASTContext();
4435   Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4436   QualType Ty = Init->getType();
4437   if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4438     if (S.getLangOpts().CPlusPlus) {
4439       Ty = C.getLValueReferenceType(Ty);
4440     } else {
4441       Ty = C.getPointerType(Ty);
4442       ExprResult Res =
4443           S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4444       if (!Res.isUsable())
4445         return nullptr;
4446       Init = Res.get();
4447     }
4448     WithInit = true;
4449   }
4450   auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4451                                           CaptureExpr->getBeginLoc());
4452   if (!WithInit)
4453     CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4454   CurContext->addHiddenDecl(CED);
4455   Sema::TentativeAnalysisScope Trap(S);
4456   S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4457   return CED;
4458 }
4459 
buildCapture(Sema & S,ValueDecl * D,Expr * CaptureExpr,bool WithInit)4460 static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4461                                  bool WithInit) {
4462   OMPCapturedExprDecl *CD;
4463   if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4464     CD = cast<OMPCapturedExprDecl>(VD);
4465   else
4466     CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4467                           S.CurContext,
4468                           /*AsExpression=*/false);
4469   return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4470                           CaptureExpr->getExprLoc());
4471 }
4472 
buildCapture(Sema & S,Expr * CaptureExpr,DeclRefExpr * & Ref,StringRef Name)4473 static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4474                                StringRef Name) {
4475   CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4476   if (!Ref) {
4477     OMPCapturedExprDecl *CD = buildCaptureDecl(
4478         S, &S.getASTContext().Idents.get(Name), CaptureExpr,
4479         /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4480     Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4481                            CaptureExpr->getExprLoc());
4482   }
4483   ExprResult Res = Ref;
4484   if (!S.getLangOpts().CPlusPlus &&
4485       CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4486       Ref->getType()->isPointerType()) {
4487     Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4488     if (!Res.isUsable())
4489       return ExprError();
4490   }
4491   return S.DefaultLvalueConversion(Res.get());
4492 }
4493 
4494 namespace {
4495 // OpenMP directives parsed in this section are represented as a
4496 // CapturedStatement with an associated statement.  If a syntax error
4497 // is detected during the parsing of the associated statement, the
4498 // compiler must abort processing and close the CapturedStatement.
4499 //
4500 // Combined directives such as 'target parallel' have more than one
4501 // nested CapturedStatements.  This RAII ensures that we unwind out
4502 // of all the nested CapturedStatements when an error is found.
4503 class CaptureRegionUnwinderRAII {
4504 private:
4505   Sema &S;
4506   bool &ErrorFound;
4507   OpenMPDirectiveKind DKind = OMPD_unknown;
4508 
4509 public:
CaptureRegionUnwinderRAII(Sema & S,bool & ErrorFound,OpenMPDirectiveKind DKind)4510   CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4511                             OpenMPDirectiveKind DKind)
4512       : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
~CaptureRegionUnwinderRAII()4513   ~CaptureRegionUnwinderRAII() {
4514     if (ErrorFound) {
4515       int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4516       while (--ThisCaptureLevel >= 0)
4517         S.ActOnCapturedRegionError();
4518     }
4519   }
4520 };
4521 } // namespace
4522 
tryCaptureOpenMPLambdas(ValueDecl * V)4523 void SemaOpenMP::tryCaptureOpenMPLambdas(ValueDecl *V) {
4524   // Capture variables captured by reference in lambdas for target-based
4525   // directives.
4526   if (!SemaRef.CurContext->isDependentContext() &&
4527       (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4528        isOpenMPTargetDataManagementDirective(
4529            DSAStack->getCurrentDirective()))) {
4530     QualType Type = V->getType();
4531     if (const auto *RD = Type.getCanonicalType()
4532                              .getNonReferenceType()
4533                              ->getAsCXXRecordDecl()) {
4534       bool SavedForceCaptureByReferenceInTargetExecutable =
4535           DSAStack->isForceCaptureByReferenceInTargetExecutable();
4536       DSAStack->setForceCaptureByReferenceInTargetExecutable(
4537           /*V=*/true);
4538       if (RD->isLambda()) {
4539         llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4540         FieldDecl *ThisCapture;
4541         RD->getCaptureFields(Captures, ThisCapture);
4542         for (const LambdaCapture &LC : RD->captures()) {
4543           if (LC.getCaptureKind() == LCK_ByRef) {
4544             VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4545             DeclContext *VDC = VD->getDeclContext();
4546             if (!VDC->Encloses(SemaRef.CurContext))
4547               continue;
4548             SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
4549           } else if (LC.getCaptureKind() == LCK_This) {
4550             QualType ThisTy = SemaRef.getCurrentThisType();
4551             if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4552                                         ThisTy, ThisCapture->getType()))
4553               SemaRef.CheckCXXThisCapture(LC.getLocation());
4554           }
4555         }
4556       }
4557       DSAStack->setForceCaptureByReferenceInTargetExecutable(
4558           SavedForceCaptureByReferenceInTargetExecutable);
4559     }
4560   }
4561 }
4562 
checkOrderedOrderSpecified(Sema & S,const ArrayRef<OMPClause * > Clauses)4563 static bool checkOrderedOrderSpecified(Sema &S,
4564                                        const ArrayRef<OMPClause *> Clauses) {
4565   const OMPOrderedClause *Ordered = nullptr;
4566   const OMPOrderClause *Order = nullptr;
4567 
4568   for (const OMPClause *Clause : Clauses) {
4569     if (Clause->getClauseKind() == OMPC_ordered)
4570       Ordered = cast<OMPOrderedClause>(Clause);
4571     else if (Clause->getClauseKind() == OMPC_order) {
4572       Order = cast<OMPOrderClause>(Clause);
4573       if (Order->getKind() != OMPC_ORDER_concurrent)
4574         Order = nullptr;
4575     }
4576     if (Ordered && Order)
4577       break;
4578   }
4579 
4580   if (Ordered && Order) {
4581     S.Diag(Order->getKindKwLoc(),
4582            diag::err_omp_simple_clause_incompatible_with_ordered)
4583         << getOpenMPClauseNameForDiag(OMPC_order)
4584         << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4585         << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4586     S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4587         << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4588     return true;
4589   }
4590   return false;
4591 }
4592 
ActOnOpenMPRegionEnd(StmtResult S,ArrayRef<OMPClause * > Clauses)4593 StmtResult SemaOpenMP::ActOnOpenMPRegionEnd(StmtResult S,
4594                                             ArrayRef<OMPClause *> Clauses) {
4595   handleDeclareVariantConstructTrait(DSAStack, DSAStack->getCurrentDirective(),
4596                                      /*ScopeEntry=*/false);
4597   if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
4598     return S;
4599 
4600   bool ErrorFound = false;
4601   CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4602       SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4603   if (!S.isUsable()) {
4604     ErrorFound = true;
4605     return StmtError();
4606   }
4607 
4608   SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4609   getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4610   OMPOrderedClause *OC = nullptr;
4611   OMPScheduleClause *SC = nullptr;
4612   SmallVector<const OMPLinearClause *, 4> LCs;
4613   SmallVector<const OMPClauseWithPreInit *, 4> PICs;
4614   // This is required for proper codegen.
4615   for (OMPClause *Clause : Clauses) {
4616     if (!getLangOpts().OpenMPSimd &&
4617         (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4618          DSAStack->getCurrentDirective() == OMPD_target) &&
4619         Clause->getClauseKind() == OMPC_in_reduction) {
4620       // Capture taskgroup task_reduction descriptors inside the tasking regions
4621       // with the corresponding in_reduction items.
4622       auto *IRC = cast<OMPInReductionClause>(Clause);
4623       for (Expr *E : IRC->taskgroup_descriptors())
4624         if (E)
4625           SemaRef.MarkDeclarationsReferencedInExpr(E);
4626     }
4627     if (isOpenMPPrivate(Clause->getClauseKind()) ||
4628         Clause->getClauseKind() == OMPC_copyprivate ||
4629         (getLangOpts().OpenMPUseTLS &&
4630          getASTContext().getTargetInfo().isTLSSupported() &&
4631          Clause->getClauseKind() == OMPC_copyin)) {
4632       DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4633       // Mark all variables in private list clauses as used in inner region.
4634       for (Stmt *VarRef : Clause->children()) {
4635         if (auto *E = cast_or_null<Expr>(VarRef)) {
4636           SemaRef.MarkDeclarationsReferencedInExpr(E);
4637         }
4638       }
4639       DSAStack->setForceVarCapturing(/*V=*/false);
4640     } else if (CaptureRegions.size() > 1 ||
4641                CaptureRegions.back() != OMPD_unknown) {
4642       if (auto *C = OMPClauseWithPreInit::get(Clause))
4643         PICs.push_back(C);
4644       if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4645         if (Expr *E = C->getPostUpdateExpr())
4646           SemaRef.MarkDeclarationsReferencedInExpr(E);
4647       }
4648     }
4649     if (Clause->getClauseKind() == OMPC_schedule)
4650       SC = cast<OMPScheduleClause>(Clause);
4651     else if (Clause->getClauseKind() == OMPC_ordered)
4652       OC = cast<OMPOrderedClause>(Clause);
4653     else if (Clause->getClauseKind() == OMPC_linear)
4654       LCs.push_back(cast<OMPLinearClause>(Clause));
4655   }
4656   // Capture allocator expressions if used.
4657   for (Expr *E : DSAStack->getInnerAllocators())
4658     SemaRef.MarkDeclarationsReferencedInExpr(E);
4659   // OpenMP, 2.7.1 Loop Construct, Restrictions
4660   // The nonmonotonic modifier cannot be specified if an ordered clause is
4661   // specified.
4662   if (SC &&
4663       (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4664        SC->getSecondScheduleModifier() ==
4665            OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4666       OC) {
4667     Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4668              ? SC->getFirstScheduleModifierLoc()
4669              : SC->getSecondScheduleModifierLoc(),
4670          diag::err_omp_simple_clause_incompatible_with_ordered)
4671         << getOpenMPClauseNameForDiag(OMPC_schedule)
4672         << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4673                                          OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4674         << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4675     ErrorFound = true;
4676   }
4677   // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4678   // If an order(concurrent) clause is present, an ordered clause may not appear
4679   // on the same directive.
4680   if (checkOrderedOrderSpecified(SemaRef, Clauses))
4681     ErrorFound = true;
4682   if (!LCs.empty() && OC && OC->getNumForLoops()) {
4683     for (const OMPLinearClause *C : LCs) {
4684       Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4685           << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4686     }
4687     ErrorFound = true;
4688   }
4689   if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4690       isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4691       OC->getNumForLoops()) {
4692     unsigned OMPVersion = getLangOpts().OpenMP;
4693     Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4694         << getOpenMPDirectiveName(DSAStack->getCurrentDirective(), OMPVersion);
4695     ErrorFound = true;
4696   }
4697   if (ErrorFound) {
4698     return StmtError();
4699   }
4700   StmtResult SR = S;
4701   unsigned CompletedRegions = 0;
4702   for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4703     // Mark all variables in private list clauses as used in inner region.
4704     // Required for proper codegen of combined directives.
4705     // TODO: add processing for other clauses.
4706     if (ThisCaptureRegion != OMPD_unknown) {
4707       for (const clang::OMPClauseWithPreInit *C : PICs) {
4708         OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4709         // Find the particular capture region for the clause if the
4710         // directive is a combined one with multiple capture regions.
4711         // If the directive is not a combined one, the capture region
4712         // associated with the clause is OMPD_unknown and is generated
4713         // only once.
4714         if (CaptureRegion == ThisCaptureRegion ||
4715             CaptureRegion == OMPD_unknown) {
4716           if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4717             for (Decl *D : DS->decls())
4718               SemaRef.MarkVariableReferenced(D->getLocation(),
4719                                              cast<VarDecl>(D));
4720           }
4721         }
4722       }
4723     }
4724     if (ThisCaptureRegion == OMPD_target) {
4725       // Capture allocator traits in the target region. They are used implicitly
4726       // and, thus, are not captured by default.
4727       for (OMPClause *C : Clauses) {
4728         if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4729           for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4730                ++I) {
4731             OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4732             if (Expr *E = D.AllocatorTraits)
4733               SemaRef.MarkDeclarationsReferencedInExpr(E);
4734           }
4735           continue;
4736         }
4737       }
4738     }
4739     if (ThisCaptureRegion == OMPD_parallel) {
4740       // Capture temp arrays for inscan reductions and locals in aligned
4741       // clauses.
4742       for (OMPClause *C : Clauses) {
4743         if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4744           if (RC->getModifier() != OMPC_REDUCTION_inscan)
4745             continue;
4746           for (Expr *E : RC->copy_array_temps())
4747             if (E)
4748               SemaRef.MarkDeclarationsReferencedInExpr(E);
4749         }
4750         if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4751           for (Expr *E : AC->varlist())
4752             SemaRef.MarkDeclarationsReferencedInExpr(E);
4753         }
4754       }
4755     }
4756     if (++CompletedRegions == CaptureRegions.size())
4757       DSAStack->setBodyComplete();
4758     SR = SemaRef.ActOnCapturedRegionEnd(SR.get());
4759   }
4760   return SR;
4761 }
4762 
checkCancelRegion(Sema & SemaRef,OpenMPDirectiveKind CurrentRegion,OpenMPDirectiveKind CancelRegion,SourceLocation StartLoc)4763 static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4764                               OpenMPDirectiveKind CancelRegion,
4765                               SourceLocation StartLoc) {
4766   // CancelRegion is only needed for cancel and cancellation_point.
4767   if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4768     return false;
4769 
4770   if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4771       CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4772     return false;
4773 
4774   unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
4775   SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4776       << getOpenMPDirectiveName(CancelRegion, OMPVersion);
4777   return true;
4778 }
4779 
checkNestingOfRegions(Sema & SemaRef,const DSAStackTy * Stack,OpenMPDirectiveKind CurrentRegion,const DeclarationNameInfo & CurrentName,OpenMPDirectiveKind CancelRegion,OpenMPBindClauseKind BindKind,SourceLocation StartLoc)4780 static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4781                                   OpenMPDirectiveKind CurrentRegion,
4782                                   const DeclarationNameInfo &CurrentName,
4783                                   OpenMPDirectiveKind CancelRegion,
4784                                   OpenMPBindClauseKind BindKind,
4785                                   SourceLocation StartLoc) {
4786   if (!Stack->getCurScope())
4787     return false;
4788 
4789   OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4790   OpenMPDirectiveKind OffendingRegion = ParentRegion;
4791   bool NestingProhibited = false;
4792   bool CloseNesting = true;
4793   bool OrphanSeen = false;
4794   enum {
4795     NoRecommend,
4796     ShouldBeInParallelRegion,
4797     ShouldBeInOrderedRegion,
4798     ShouldBeInTargetRegion,
4799     ShouldBeInTeamsRegion,
4800     ShouldBeInLoopSimdRegion,
4801   } Recommend = NoRecommend;
4802 
4803   SmallVector<OpenMPDirectiveKind, 4> LeafOrComposite;
4804   ArrayRef<OpenMPDirectiveKind> ParentLOC =
4805       getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4806   OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
4807   unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
4808 
4809   if (OMPVersion >= 50 && Stack->isParentOrderConcurrent() &&
4810       !isOpenMPOrderConcurrentNestableDirective(CurrentRegion,
4811                                                 SemaRef.LangOpts)) {
4812     SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
4813         << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
4814     return true;
4815   }
4816   if (isOpenMPSimdDirective(ParentRegion) &&
4817       ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered) ||
4818        (OMPVersion >= 50 && CurrentRegion != OMPD_ordered &&
4819         CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4820         CurrentRegion != OMPD_scan))) {
4821     // OpenMP [2.16, Nesting of Regions]
4822     // OpenMP constructs may not be nested inside a simd region.
4823     // OpenMP [2.8.1,simd Construct, Restrictions]
4824     // An ordered construct with the simd clause is the only OpenMP
4825     // construct that can appear in the simd region.
4826     // Allowing a SIMD construct nested in another SIMD construct is an
4827     // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
4828     // message.
4829     // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
4830     // The only OpenMP constructs that can be encountered during execution of
4831     // a simd region are the atomic construct, the loop construct, the simd
4832     // construct and the ordered construct with the simd clause.
4833     SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
4834                                ? diag::err_omp_prohibited_region_simd
4835                                : diag::warn_omp_nesting_simd)
4836         << (OMPVersion >= 50 ? 1 : 0);
4837     return CurrentRegion != OMPD_simd;
4838   }
4839   if (EnclosingConstruct == OMPD_atomic) {
4840     // OpenMP [2.16, Nesting of Regions]
4841     // OpenMP constructs may not be nested inside an atomic region.
4842     SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
4843     return true;
4844   }
4845   if (CurrentRegion == OMPD_section) {
4846     // OpenMP [2.7.2, sections Construct, Restrictions]
4847     // Orphaned section directives are prohibited. That is, the section
4848     // directives must appear within the sections construct and must not be
4849     // encountered elsewhere in the sections region.
4850     if (EnclosingConstruct != OMPD_sections) {
4851       SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
4852           << (ParentRegion != OMPD_unknown)
4853           << getOpenMPDirectiveName(ParentRegion, OMPVersion);
4854       return true;
4855     }
4856     return false;
4857   }
4858   // Allow some constructs (except teams and cancellation constructs) to be
4859   // orphaned (they could be used in functions, called from OpenMP regions
4860   // with the required preconditions).
4861   if (ParentRegion == OMPD_unknown &&
4862       !isOpenMPNestingTeamsDirective(CurrentRegion) &&
4863       CurrentRegion != OMPD_cancellation_point &&
4864       CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
4865     return false;
4866   // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
4867   // for a detailed explanation
4868   if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
4869       (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
4870       (isOpenMPWorksharingDirective(ParentRegion) ||
4871        EnclosingConstruct == OMPD_loop)) {
4872     int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
4873     SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
4874         << true << getOpenMPDirectiveName(ParentRegion, OMPVersion)
4875         << ErrorMsgNumber << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
4876     return true;
4877   }
4878   if (CurrentRegion == OMPD_cancellation_point ||
4879       CurrentRegion == OMPD_cancel) {
4880     // OpenMP [2.16, Nesting of Regions]
4881     // A cancellation point construct for which construct-type-clause is
4882     // taskgroup must be nested inside a task construct. A cancellation
4883     // point construct for which construct-type-clause is not taskgroup must
4884     // be closely nested inside an OpenMP construct that matches the type
4885     // specified in construct-type-clause.
4886     // A cancel construct for which construct-type-clause is taskgroup must be
4887     // nested inside a task construct. A cancel construct for which
4888     // construct-type-clause is not taskgroup must be closely nested inside an
4889     // OpenMP construct that matches the type specified in
4890     // construct-type-clause.
4891     ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(ParentRegion);
4892     if (CancelRegion == OMPD_taskgroup) {
4893       NestingProhibited =
4894           EnclosingConstruct != OMPD_task &&
4895           (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
4896     } else if (CancelRegion == OMPD_sections) {
4897       NestingProhibited = EnclosingConstruct != OMPD_section &&
4898                           EnclosingConstruct != OMPD_sections;
4899     } else {
4900       NestingProhibited = CancelRegion != Leafs.back();
4901     }
4902     OrphanSeen = ParentRegion == OMPD_unknown;
4903   } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
4904     // OpenMP 5.1 [2.22, Nesting of Regions]
4905     // A masked region may not be closely nested inside a worksharing, loop,
4906     // atomic, task, or taskloop region.
4907     NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4908                         isOpenMPGenericLoopDirective(ParentRegion) ||
4909                         isOpenMPTaskingDirective(ParentRegion);
4910   } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
4911     // OpenMP [2.16, Nesting of Regions]
4912     // A critical region may not be nested (closely or otherwise) inside a
4913     // critical region with the same name. Note that this restriction is not
4914     // sufficient to prevent deadlock.
4915     SourceLocation PreviousCriticalLoc;
4916     bool DeadLock = Stack->hasDirective(
4917         [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
4918                                             const DeclarationNameInfo &DNI,
4919                                             SourceLocation Loc) {
4920           if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
4921             PreviousCriticalLoc = Loc;
4922             return true;
4923           }
4924           return false;
4925         },
4926         false /* skip top directive */);
4927     if (DeadLock) {
4928       SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
4929           << CurrentName.getName();
4930       if (PreviousCriticalLoc.isValid())
4931         SemaRef.Diag(PreviousCriticalLoc,
4932                      diag::note_omp_previous_critical_region);
4933       return true;
4934     }
4935   } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
4936     // OpenMP 5.1 [2.22, Nesting of Regions]
4937     // A scope region may not be closely nested inside a worksharing, loop,
4938     // task, taskloop, critical, ordered, atomic, or masked region.
4939     // OpenMP 5.1 [2.22, Nesting of Regions]
4940     // A barrier region may not be closely nested inside a worksharing, loop,
4941     // task, taskloop, critical, ordered, atomic, or masked region.
4942     NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4943                         isOpenMPGenericLoopDirective(ParentRegion) ||
4944                         isOpenMPTaskingDirective(ParentRegion) ||
4945                         llvm::is_contained({OMPD_masked, OMPD_master,
4946                                             OMPD_critical, OMPD_ordered},
4947                                            EnclosingConstruct);
4948   } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
4949              !isOpenMPParallelDirective(CurrentRegion) &&
4950              !isOpenMPTeamsDirective(CurrentRegion)) {
4951     // OpenMP 5.1 [2.22, Nesting of Regions]
4952     // A loop region that binds to a parallel region or a worksharing region
4953     // may not be closely nested inside a worksharing, loop, task, taskloop,
4954     // critical, ordered, atomic, or masked region.
4955     NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4956                         isOpenMPGenericLoopDirective(ParentRegion) ||
4957                         isOpenMPTaskingDirective(ParentRegion) ||
4958                         llvm::is_contained({OMPD_masked, OMPD_master,
4959                                             OMPD_critical, OMPD_ordered},
4960                                            EnclosingConstruct);
4961     Recommend = ShouldBeInParallelRegion;
4962   } else if (CurrentRegion == OMPD_ordered) {
4963     // OpenMP [2.16, Nesting of Regions]
4964     // An ordered region may not be closely nested inside a critical,
4965     // atomic, or explicit task region.
4966     // An ordered region must be closely nested inside a loop region (or
4967     // parallel loop region) with an ordered clause.
4968     // OpenMP [2.8.1,simd Construct, Restrictions]
4969     // An ordered construct with the simd clause is the only OpenMP construct
4970     // that can appear in the simd region.
4971     NestingProhibited = EnclosingConstruct == OMPD_critical ||
4972                         isOpenMPTaskingDirective(ParentRegion) ||
4973                         !(isOpenMPSimdDirective(ParentRegion) ||
4974                           Stack->isParentOrderedRegion());
4975     Recommend = ShouldBeInOrderedRegion;
4976   } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
4977     // OpenMP [2.16, Nesting of Regions]
4978     // If specified, a teams construct must be contained within a target
4979     // construct.
4980     NestingProhibited =
4981         (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
4982         (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
4983          EnclosingConstruct != OMPD_target);
4984     OrphanSeen = ParentRegion == OMPD_unknown;
4985     Recommend = ShouldBeInTargetRegion;
4986   } else if (CurrentRegion == OMPD_scan) {
4987     if (OMPVersion >= 50) {
4988       // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
4989       // simd, or for simd. This has to take into account combined directives.
4990       // In 5.2 this seems to be implied by the fact that the specified
4991       // separated constructs are do, for, and simd.
4992       NestingProhibited = !llvm::is_contained(
4993           {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
4994     } else {
4995       NestingProhibited = true;
4996     }
4997     OrphanSeen = ParentRegion == OMPD_unknown;
4998     Recommend = ShouldBeInLoopSimdRegion;
4999   }
5000   if (!NestingProhibited && !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5001       !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5002       EnclosingConstruct == OMPD_teams) {
5003     // OpenMP [5.1, 2.22, Nesting of Regions]
5004     // distribute, distribute simd, distribute parallel worksharing-loop,
5005     // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5006     // including any parallel regions arising from combined constructs,
5007     // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5008     // only OpenMP regions that may be strictly nested inside the teams
5009     // region.
5010     //
5011     // As an extension, we permit atomic within teams as well.
5012     NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5013                         !isOpenMPDistributeDirective(CurrentRegion) &&
5014                         CurrentRegion != OMPD_loop &&
5015                         !(SemaRef.getLangOpts().OpenMPExtensions &&
5016                           CurrentRegion == OMPD_atomic);
5017     Recommend = ShouldBeInParallelRegion;
5018   }
5019   if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5020     // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5021     // If the bind clause is present on the loop construct and binding is
5022     // teams then the corresponding loop region must be strictly nested inside
5023     // a teams region.
5024     NestingProhibited =
5025         BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5026     Recommend = ShouldBeInTeamsRegion;
5027   }
5028   if (!NestingProhibited && isOpenMPNestingDistributeDirective(CurrentRegion)) {
5029     // OpenMP 4.5 [2.17 Nesting of Regions]
5030     // The region associated with the distribute construct must be strictly
5031     // nested inside a teams region
5032     NestingProhibited = EnclosingConstruct != OMPD_teams;
5033     Recommend = ShouldBeInTeamsRegion;
5034   }
5035   if (!NestingProhibited &&
5036       (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5037        isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5038     // OpenMP 4.5 [2.17 Nesting of Regions]
5039     // If a target, target update, target data, target enter data, or
5040     // target exit data construct is encountered during execution of a
5041     // target region, the behavior is unspecified.
5042     NestingProhibited = Stack->hasDirective(
5043         [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5044                            SourceLocation) {
5045           if (isOpenMPTargetExecutionDirective(K)) {
5046             OffendingRegion = K;
5047             return true;
5048           }
5049           return false;
5050         },
5051         false /* don't skip top directive */);
5052     CloseNesting = false;
5053   }
5054   if (NestingProhibited) {
5055     if (OrphanSeen) {
5056       SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5057           << getOpenMPDirectiveName(CurrentRegion, OMPVersion) << Recommend;
5058     } else {
5059       SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5060           << CloseNesting << getOpenMPDirectiveName(OffendingRegion, OMPVersion)
5061           << Recommend << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5062     }
5063     return true;
5064   }
5065   return false;
5066 }
5067 
5068 struct Kind2Unsigned {
5069   using argument_type = OpenMPDirectiveKind;
operator ()Kind2Unsigned5070   unsigned operator()(argument_type DK) { return unsigned(DK); }
5071 };
checkIfClauses(Sema & S,OpenMPDirectiveKind Kind,ArrayRef<OMPClause * > Clauses,ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers)5072 static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
5073                            ArrayRef<OMPClause *> Clauses,
5074                            ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5075   bool ErrorFound = false;
5076   unsigned NamedModifiersNumber = 0;
5077   llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5078   FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5079   SmallVector<SourceLocation, 4> NameModifierLoc;
5080   unsigned OMPVersion = S.getLangOpts().OpenMP;
5081   for (const OMPClause *C : Clauses) {
5082     if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5083       // At most one if clause without a directive-name-modifier can appear on
5084       // the directive.
5085       OpenMPDirectiveKind CurNM = IC->getNameModifier();
5086       auto &FNM = FoundNameModifiers[CurNM];
5087       if (FNM) {
5088         S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5089             << getOpenMPDirectiveName(Kind, OMPVersion)
5090             << getOpenMPClauseNameForDiag(OMPC_if) << (CurNM != OMPD_unknown)
5091             << getOpenMPDirectiveName(CurNM, OMPVersion);
5092         ErrorFound = true;
5093       } else if (CurNM != OMPD_unknown) {
5094         NameModifierLoc.push_back(IC->getNameModifierLoc());
5095         ++NamedModifiersNumber;
5096       }
5097       FNM = IC;
5098       if (CurNM == OMPD_unknown)
5099         continue;
5100       // Check if the specified name modifier is allowed for the current
5101       // directive.
5102       // At most one if clause with the particular directive-name-modifier can
5103       // appear on the directive.
5104       if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5105         S.Diag(IC->getNameModifierLoc(),
5106                diag::err_omp_wrong_if_directive_name_modifier)
5107             << getOpenMPDirectiveName(CurNM, OMPVersion)
5108             << getOpenMPDirectiveName(Kind, OMPVersion);
5109         ErrorFound = true;
5110       }
5111     }
5112   }
5113   // If any if clause on the directive includes a directive-name-modifier then
5114   // all if clauses on the directive must include a directive-name-modifier.
5115   if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5116     if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5117       S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5118              diag::err_omp_no_more_if_clause);
5119     } else {
5120       std::string Values;
5121       std::string Sep(", ");
5122       unsigned AllowedCnt = 0;
5123       unsigned TotalAllowedNum =
5124           AllowedNameModifiers.size() - NamedModifiersNumber;
5125       for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5126            ++Cnt) {
5127         OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5128         if (!FoundNameModifiers[NM]) {
5129           Values += "'";
5130           Values += getOpenMPDirectiveName(NM, OMPVersion);
5131           Values += "'";
5132           if (AllowedCnt + 2 == TotalAllowedNum)
5133             Values += " or ";
5134           else if (AllowedCnt + 1 != TotalAllowedNum)
5135             Values += Sep;
5136           ++AllowedCnt;
5137         }
5138       }
5139       S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5140              diag::err_omp_unnamed_if_clause)
5141           << (TotalAllowedNum > 1) << Values;
5142     }
5143     for (SourceLocation Loc : NameModifierLoc) {
5144       S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5145     }
5146     ErrorFound = true;
5147   }
5148   return ErrorFound;
5149 }
5150 
getPrivateItem(Sema & S,Expr * & RefExpr,SourceLocation & ELoc,SourceRange & ERange,bool AllowArraySection,StringRef DiagType)5151 static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5152                                                    SourceLocation &ELoc,
5153                                                    SourceRange &ERange,
5154                                                    bool AllowArraySection,
5155                                                    StringRef DiagType) {
5156   if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5157       RefExpr->containsUnexpandedParameterPack())
5158     return std::make_pair(nullptr, true);
5159 
5160   // OpenMP [3.1, C/C++]
5161   //  A list item is a variable name.
5162   // OpenMP  [2.9.3.3, Restrictions, p.1]
5163   //  A variable that is part of another variable (as an array or
5164   //  structure element) cannot appear in a private clause.
5165   RefExpr = RefExpr->IgnoreParens();
5166   enum {
5167     NoArrayExpr = -1,
5168     ArraySubscript = 0,
5169     OMPArraySection = 1
5170   } IsArrayExpr = NoArrayExpr;
5171   if (AllowArraySection) {
5172     if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5173       Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5174       while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5175         Base = TempASE->getBase()->IgnoreParenImpCasts();
5176       RefExpr = Base;
5177       IsArrayExpr = ArraySubscript;
5178     } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5179       Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5180       while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Base))
5181         Base = TempOASE->getBase()->IgnoreParenImpCasts();
5182       while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5183         Base = TempASE->getBase()->IgnoreParenImpCasts();
5184       RefExpr = Base;
5185       IsArrayExpr = OMPArraySection;
5186     }
5187   }
5188   ELoc = RefExpr->getExprLoc();
5189   ERange = RefExpr->getSourceRange();
5190   RefExpr = RefExpr->IgnoreParenImpCasts();
5191   auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5192   auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5193   if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5194       (S.getCurrentThisType().isNull() || !ME ||
5195        !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5196        !isa<FieldDecl>(ME->getMemberDecl()))) {
5197     if (IsArrayExpr != NoArrayExpr) {
5198       S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5199           << IsArrayExpr << ERange;
5200     } else if (!DiagType.empty()) {
5201       unsigned DiagSelect = S.getLangOpts().CPlusPlus
5202                                 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5203                                 : 0;
5204       S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5205           << DiagSelect << DiagType << ERange;
5206     } else {
5207       S.Diag(ELoc,
5208              AllowArraySection
5209                  ? diag::err_omp_expected_var_name_member_expr_or_array_item
5210                  : diag::err_omp_expected_var_name_member_expr)
5211           << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5212     }
5213     return std::make_pair(nullptr, false);
5214   }
5215   return std::make_pair(
5216       getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5217 }
5218 
5219 namespace {
5220 /// Checks if the allocator is used in uses_allocators clause to be allowed in
5221 /// target regions.
5222 class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5223   DSAStackTy *S = nullptr;
5224 
5225 public:
VisitDeclRefExpr(const DeclRefExpr * E)5226   bool VisitDeclRefExpr(const DeclRefExpr *E) {
5227     return S->isUsesAllocatorsDecl(E->getDecl())
5228                .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5229            DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5230   }
VisitStmt(const Stmt * S)5231   bool VisitStmt(const Stmt *S) {
5232     for (const Stmt *Child : S->children()) {
5233       if (Child && Visit(Child))
5234         return true;
5235     }
5236     return false;
5237   }
AllocatorChecker(DSAStackTy * S)5238   explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5239 };
5240 } // namespace
5241 
checkAllocateClauses(Sema & S,DSAStackTy * Stack,ArrayRef<OMPClause * > Clauses)5242 static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5243                                  ArrayRef<OMPClause *> Clauses) {
5244   assert(!S.CurContext->isDependentContext() &&
5245          "Expected non-dependent context.");
5246   auto AllocateRange =
5247       llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5248   llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5249   auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5250     return isOpenMPPrivate(C->getClauseKind());
5251   });
5252   for (OMPClause *Cl : PrivateRange) {
5253     MutableArrayRef<Expr *>::iterator I, It, Et;
5254     if (Cl->getClauseKind() == OMPC_private) {
5255       auto *PC = cast<OMPPrivateClause>(Cl);
5256       I = PC->private_copies().begin();
5257       It = PC->varlist_begin();
5258       Et = PC->varlist_end();
5259     } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5260       auto *PC = cast<OMPFirstprivateClause>(Cl);
5261       I = PC->private_copies().begin();
5262       It = PC->varlist_begin();
5263       Et = PC->varlist_end();
5264     } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5265       auto *PC = cast<OMPLastprivateClause>(Cl);
5266       I = PC->private_copies().begin();
5267       It = PC->varlist_begin();
5268       Et = PC->varlist_end();
5269     } else if (Cl->getClauseKind() == OMPC_linear) {
5270       auto *PC = cast<OMPLinearClause>(Cl);
5271       I = PC->privates().begin();
5272       It = PC->varlist_begin();
5273       Et = PC->varlist_end();
5274     } else if (Cl->getClauseKind() == OMPC_reduction) {
5275       auto *PC = cast<OMPReductionClause>(Cl);
5276       I = PC->privates().begin();
5277       It = PC->varlist_begin();
5278       Et = PC->varlist_end();
5279     } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5280       auto *PC = cast<OMPTaskReductionClause>(Cl);
5281       I = PC->privates().begin();
5282       It = PC->varlist_begin();
5283       Et = PC->varlist_end();
5284     } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5285       auto *PC = cast<OMPInReductionClause>(Cl);
5286       I = PC->privates().begin();
5287       It = PC->varlist_begin();
5288       Et = PC->varlist_end();
5289     } else {
5290       llvm_unreachable("Expected private clause.");
5291     }
5292     for (Expr *E : llvm::make_range(It, Et)) {
5293       if (!*I) {
5294         ++I;
5295         continue;
5296       }
5297       SourceLocation ELoc;
5298       SourceRange ERange;
5299       Expr *SimpleRefExpr = E;
5300       auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5301                                 /*AllowArraySection=*/true);
5302       DeclToCopy.try_emplace(Res.first,
5303                              cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5304       ++I;
5305     }
5306   }
5307   for (OMPClause *C : AllocateRange) {
5308     auto *AC = cast<OMPAllocateClause>(C);
5309     if (S.getLangOpts().OpenMP >= 50 &&
5310         !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5311         isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5312         AC->getAllocator()) {
5313       Expr *Allocator = AC->getAllocator();
5314       // OpenMP, 2.12.5 target Construct
5315       // Memory allocators that do not appear in a uses_allocators clause cannot
5316       // appear as an allocator in an allocate clause or be used in the target
5317       // region unless a requires directive with the dynamic_allocators clause
5318       // is present in the same compilation unit.
5319       AllocatorChecker Checker(Stack);
5320       if (Checker.Visit(Allocator))
5321         S.Diag(Allocator->getExprLoc(),
5322                diag::err_omp_allocator_not_in_uses_allocators)
5323             << Allocator->getSourceRange();
5324     }
5325     OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5326         getAllocatorKind(S, Stack, AC->getAllocator());
5327     // OpenMP, 2.11.4 allocate Clause, Restrictions.
5328     // For task, taskloop or target directives, allocation requests to memory
5329     // allocators with the trait access set to thread result in unspecified
5330     // behavior.
5331     if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5332         (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5333          isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5334       unsigned OMPVersion = S.getLangOpts().OpenMP;
5335       S.Diag(AC->getAllocator()->getExprLoc(),
5336              diag::warn_omp_allocate_thread_on_task_target_directive)
5337           << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
5338     }
5339     for (Expr *E : AC->varlist()) {
5340       SourceLocation ELoc;
5341       SourceRange ERange;
5342       Expr *SimpleRefExpr = E;
5343       auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5344       ValueDecl *VD = Res.first;
5345       if (!VD)
5346         continue;
5347       DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5348       if (!isOpenMPPrivate(Data.CKind)) {
5349         S.Diag(E->getExprLoc(),
5350                diag::err_omp_expected_private_copy_for_allocate);
5351         continue;
5352       }
5353       VarDecl *PrivateVD = DeclToCopy[VD];
5354       if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5355                                             AllocatorKind, AC->getAllocator()))
5356         continue;
5357       applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5358                                 AC->getAlignment(), E->getSourceRange());
5359     }
5360   }
5361 }
5362 
5363 namespace {
5364 /// Rewrite statements and expressions for Sema \p Actions CurContext.
5365 ///
5366 /// Used to wrap already parsed statements/expressions into a new CapturedStmt
5367 /// context. DeclRefExpr used inside the new context are changed to refer to the
5368 /// captured variable instead.
5369 class CaptureVars : public TreeTransform<CaptureVars> {
5370   using BaseTransform = TreeTransform<CaptureVars>;
5371 
5372 public:
CaptureVars(Sema & Actions)5373   CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5374 
AlwaysRebuild()5375   bool AlwaysRebuild() { return true; }
5376 };
5377 } // namespace
5378 
precomputeExpr(Sema & Actions,SmallVectorImpl<Stmt * > & BodyStmts,Expr * E,StringRef Name)5379 static VarDecl *precomputeExpr(Sema &Actions,
5380                                SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5381                                StringRef Name) {
5382   Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5383   VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5384                                  dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5385   auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5386       Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5387   Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5388   BodyStmts.push_back(NewDeclStmt);
5389   return NewVar;
5390 }
5391 
5392 /// Create a closure that computes the number of iterations of a loop.
5393 ///
5394 /// \param Actions   The Sema object.
5395 /// \param LogicalTy Type for the logical iteration number.
5396 /// \param Rel       Comparison operator of the loop condition.
5397 /// \param StartExpr Value of the loop counter at the first iteration.
5398 /// \param StopExpr  Expression the loop counter is compared against in the loop
5399 /// condition. \param StepExpr      Amount of increment after each iteration.
5400 ///
5401 /// \return Closure (CapturedStmt) of the distance calculation.
buildDistanceFunc(Sema & Actions,QualType LogicalTy,BinaryOperator::Opcode Rel,Expr * StartExpr,Expr * StopExpr,Expr * StepExpr)5402 static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5403                                        BinaryOperator::Opcode Rel,
5404                                        Expr *StartExpr, Expr *StopExpr,
5405                                        Expr *StepExpr) {
5406   ASTContext &Ctx = Actions.getASTContext();
5407   TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5408 
5409   // Captured regions currently don't support return values, we use an
5410   // out-parameter instead. All inputs are implicit captures.
5411   // TODO: Instead of capturing each DeclRefExpr occurring in
5412   // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5413   QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5414   Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5415                                           {StringRef(), QualType()}};
5416   Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5417 
5418   Stmt *Body;
5419   {
5420     Sema::CompoundScopeRAII CompoundScope(Actions);
5421     CapturedDecl *CS = cast<CapturedDecl>(Actions.CurContext);
5422 
5423     // Get the LValue expression for the result.
5424     ImplicitParamDecl *DistParam = CS->getParam(0);
5425     DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5426         DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5427 
5428     SmallVector<Stmt *, 4> BodyStmts;
5429 
5430     // Capture all referenced variable references.
5431     // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5432     // CapturedStmt, we could compute them before and capture the result, to be
5433     // used jointly with the LoopVar function.
5434     VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5435     VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5436     VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5437     auto BuildVarRef = [&](VarDecl *VD) {
5438       return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5439     };
5440 
5441     IntegerLiteral *Zero = IntegerLiteral::Create(
5442         Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5443     IntegerLiteral *One = IntegerLiteral::Create(
5444         Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5445     Expr *Dist;
5446     if (Rel == BO_NE) {
5447       // When using a != comparison, the increment can be +1 or -1. This can be
5448       // dynamic at runtime, so we need to check for the direction.
5449       Expr *IsNegStep = AssertSuccess(
5450           Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5451 
5452       // Positive increment.
5453       Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5454           nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5455       ForwardRange = AssertSuccess(
5456           Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5457       Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5458           nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5459 
5460       // Negative increment.
5461       Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5462           nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5463       BackwardRange = AssertSuccess(
5464           Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5465       Expr *NegIncAmount = AssertSuccess(
5466           Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5467       Expr *BackwardDist = AssertSuccess(
5468           Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5469 
5470       // Use the appropriate case.
5471       Dist = AssertSuccess(Actions.ActOnConditionalOp(
5472           {}, {}, IsNegStep, BackwardDist, ForwardDist));
5473     } else {
5474       assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5475              "Expected one of these relational operators");
5476 
5477       // We can derive the direction from any other comparison operator. It is
5478       // non well-formed OpenMP if Step increments/decrements in the other
5479       // directions. Whether at least the first iteration passes the loop
5480       // condition.
5481       Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5482           nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5483 
5484       // Compute the range between first and last counter value.
5485       Expr *Range;
5486       if (Rel == BO_GE || Rel == BO_GT)
5487         Range = AssertSuccess(Actions.BuildBinOp(
5488             nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5489       else
5490         Range = AssertSuccess(Actions.BuildBinOp(
5491             nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5492 
5493       // Ensure unsigned range space.
5494       Range =
5495           AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5496 
5497       if (Rel == BO_LE || Rel == BO_GE) {
5498         // Add one to the range if the relational operator is inclusive.
5499         Range =
5500             AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5501       }
5502 
5503       // Divide by the absolute step amount. If the range is not a multiple of
5504       // the step size, rounding-up the effective upper bound ensures that the
5505       // last iteration is included.
5506       // Note that the rounding-up may cause an overflow in a temporary that
5507       // could be avoided, but would have occurred in a C-style for-loop as
5508       // well.
5509       Expr *Divisor = BuildVarRef(NewStep);
5510       if (Rel == BO_GE || Rel == BO_GT)
5511         Divisor =
5512             AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5513       Expr *DivisorMinusOne =
5514           AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5515       Expr *RangeRoundUp = AssertSuccess(
5516           Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5517       Dist = AssertSuccess(
5518           Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5519 
5520       // If there is not at least one iteration, the range contains garbage. Fix
5521       // to zero in this case.
5522       Dist = AssertSuccess(
5523           Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5524     }
5525 
5526     // Assign the result to the out-parameter.
5527     Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5528         Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5529     BodyStmts.push_back(ResultAssign);
5530 
5531     Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5532   }
5533 
5534   return cast<CapturedStmt>(
5535       AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5536 }
5537 
5538 /// Create a closure that computes the loop variable from the logical iteration
5539 /// number.
5540 ///
5541 /// \param Actions   The Sema object.
5542 /// \param LoopVarTy Type for the loop variable used for result value.
5543 /// \param LogicalTy Type for the logical iteration number.
5544 /// \param StartExpr Value of the loop counter at the first iteration.
5545 /// \param Step      Amount of increment after each iteration.
5546 /// \param Deref     Whether the loop variable is a dereference of the loop
5547 /// counter variable.
5548 ///
5549 /// \return Closure (CapturedStmt) of the loop value calculation.
buildLoopVarFunc(Sema & Actions,QualType LoopVarTy,QualType LogicalTy,DeclRefExpr * StartExpr,Expr * Step,bool Deref)5550 static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5551                                       QualType LogicalTy,
5552                                       DeclRefExpr *StartExpr, Expr *Step,
5553                                       bool Deref) {
5554   ASTContext &Ctx = Actions.getASTContext();
5555 
5556   // Pass the result as an out-parameter. Passing as return value would require
5557   // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5558   // invoke a copy constructor.
5559   QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5560   SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5561                                                 {"Logical", LogicalTy},
5562                                                 {StringRef(), QualType()}};
5563   Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5564 
5565   // Capture the initial iterator which represents the LoopVar value at the
5566   // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5567   // it in every iteration, capture it by value before it is modified.
5568   VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5569   bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5570                                             TryCaptureKind::ExplicitByVal, {});
5571   (void)Invalid;
5572   assert(!Invalid && "Expecting capture-by-value to work.");
5573 
5574   Expr *Body;
5575   {
5576     Sema::CompoundScopeRAII CompoundScope(Actions);
5577     auto *CS = cast<CapturedDecl>(Actions.CurContext);
5578 
5579     ImplicitParamDecl *TargetParam = CS->getParam(0);
5580     DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5581         TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5582     ImplicitParamDecl *IndvarParam = CS->getParam(1);
5583     DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5584         IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5585 
5586     // Capture the Start expression.
5587     CaptureVars Recap(Actions);
5588     Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5589     Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5590 
5591     Expr *Skip = AssertSuccess(
5592         Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5593     // TODO: Explicitly cast to the iterator's difference_type instead of
5594     // relying on implicit conversion.
5595     Expr *Advanced =
5596         AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5597 
5598     if (Deref) {
5599       // For range-based for-loops convert the loop counter value to a concrete
5600       // loop variable value by dereferencing the iterator.
5601       Advanced =
5602           AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5603     }
5604 
5605     // Assign the result to the output parameter.
5606     Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5607                                             BO_Assign, TargetRef, Advanced));
5608   }
5609   return cast<CapturedStmt>(
5610       AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5611 }
5612 
ActOnOpenMPCanonicalLoop(Stmt * AStmt)5613 StmtResult SemaOpenMP::ActOnOpenMPCanonicalLoop(Stmt *AStmt) {
5614   ASTContext &Ctx = getASTContext();
5615 
5616   // Extract the common elements of ForStmt and CXXForRangeStmt:
5617   // Loop variable, repeat condition, increment
5618   Expr *Cond, *Inc;
5619   VarDecl *LIVDecl, *LUVDecl;
5620   if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5621     Stmt *Init = For->getInit();
5622     if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5623       // For statement declares loop variable.
5624       LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5625     } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5626       // For statement reuses variable.
5627       assert(LCAssign->getOpcode() == BO_Assign &&
5628              "init part must be a loop variable assignment");
5629       auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5630       LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5631     } else
5632       llvm_unreachable("Cannot determine loop variable");
5633     LUVDecl = LIVDecl;
5634 
5635     Cond = For->getCond();
5636     Inc = For->getInc();
5637   } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5638     DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5639     LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5640     LUVDecl = RangeFor->getLoopVariable();
5641 
5642     Cond = RangeFor->getCond();
5643     Inc = RangeFor->getInc();
5644   } else
5645     llvm_unreachable("unhandled kind of loop");
5646 
5647   QualType CounterTy = LIVDecl->getType();
5648   QualType LVTy = LUVDecl->getType();
5649 
5650   // Analyze the loop condition.
5651   Expr *LHS, *RHS;
5652   BinaryOperator::Opcode CondRel;
5653   Cond = Cond->IgnoreImplicit();
5654   if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5655     LHS = CondBinExpr->getLHS();
5656     RHS = CondBinExpr->getRHS();
5657     CondRel = CondBinExpr->getOpcode();
5658   } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5659     assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5660     LHS = CondCXXOp->getArg(0);
5661     RHS = CondCXXOp->getArg(1);
5662     switch (CondCXXOp->getOperator()) {
5663     case OO_ExclaimEqual:
5664       CondRel = BO_NE;
5665       break;
5666     case OO_Less:
5667       CondRel = BO_LT;
5668       break;
5669     case OO_LessEqual:
5670       CondRel = BO_LE;
5671       break;
5672     case OO_Greater:
5673       CondRel = BO_GT;
5674       break;
5675     case OO_GreaterEqual:
5676       CondRel = BO_GE;
5677       break;
5678     default:
5679       llvm_unreachable("unexpected iterator operator");
5680     }
5681   } else
5682     llvm_unreachable("unexpected loop condition");
5683 
5684   // Normalize such that the loop counter is on the LHS.
5685   if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5686       cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5687     std::swap(LHS, RHS);
5688     CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5689   }
5690   auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5691 
5692   // Decide the bit width for the logical iteration counter. By default use the
5693   // unsigned ptrdiff_t integer size (for iterators and pointers).
5694   // TODO: For iterators, use iterator::difference_type,
5695   // std::iterator_traits<>::difference_type or decltype(it - end).
5696   QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5697   if (CounterTy->isIntegerType()) {
5698     unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5699     LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5700   }
5701 
5702   // Analyze the loop increment.
5703   Expr *Step;
5704   if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5705     int Direction;
5706     switch (IncUn->getOpcode()) {
5707     case UO_PreInc:
5708     case UO_PostInc:
5709       Direction = 1;
5710       break;
5711     case UO_PreDec:
5712     case UO_PostDec:
5713       Direction = -1;
5714       break;
5715     default:
5716       llvm_unreachable("unhandled unary increment operator");
5717     }
5718     Step = IntegerLiteral::Create(
5719         Ctx,
5720         llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction, /*isSigned=*/true),
5721         LogicalTy, {});
5722   } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5723     if (IncBin->getOpcode() == BO_AddAssign) {
5724       Step = IncBin->getRHS();
5725     } else if (IncBin->getOpcode() == BO_SubAssign) {
5726       Step = AssertSuccess(
5727           SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5728     } else
5729       llvm_unreachable("unhandled binary increment operator");
5730   } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5731     switch (CondCXXOp->getOperator()) {
5732     case OO_PlusPlus:
5733       Step = IntegerLiteral::Create(
5734           Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5735       break;
5736     case OO_MinusMinus:
5737       Step = IntegerLiteral::Create(
5738           Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5739       break;
5740     case OO_PlusEqual:
5741       Step = CondCXXOp->getArg(1);
5742       break;
5743     case OO_MinusEqual:
5744       Step = AssertSuccess(
5745           SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5746       break;
5747     default:
5748       llvm_unreachable("unhandled overloaded increment operator");
5749     }
5750   } else
5751     llvm_unreachable("unknown increment expression");
5752 
5753   CapturedStmt *DistanceFunc =
5754       buildDistanceFunc(SemaRef, LogicalTy, CondRel, LHS, RHS, Step);
5755   CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5756       SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5757   DeclRefExpr *LVRef =
5758       SemaRef.BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue, {},
5759                                nullptr, nullptr, {}, nullptr);
5760   return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
5761                                   LoopVarFunc, LVRef);
5762 }
5763 
ActOnOpenMPLoopnest(Stmt * AStmt)5764 StmtResult SemaOpenMP::ActOnOpenMPLoopnest(Stmt *AStmt) {
5765   // Handle a literal loop.
5766   if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5767     return ActOnOpenMPCanonicalLoop(AStmt);
5768 
5769   // If not a literal loop, it must be the result of a loop transformation.
5770   OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(AStmt);
5771   assert(
5772       isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
5773       "Loop transformation directive expected");
5774   return LoopTransform;
5775 }
5776 
5777 static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
5778                                             CXXScopeSpec &MapperIdScopeSpec,
5779                                             const DeclarationNameInfo &MapperId,
5780                                             QualType Type,
5781                                             Expr *UnresolvedMapper);
5782 
5783 /// Perform DFS through the structure/class data members trying to find
5784 /// member(s) with user-defined 'default' mapper and generate implicit map
5785 /// clauses for such members with the found 'default' mapper.
5786 static void
processImplicitMapsWithDefaultMappers(Sema & S,DSAStackTy * Stack,SmallVectorImpl<OMPClause * > & Clauses)5787 processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack,
5788                                       SmallVectorImpl<OMPClause *> &Clauses) {
5789   // Check for the default mapper for data members.
5790   if (S.getLangOpts().OpenMP < 50)
5791     return;
5792   for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5793     auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5794     if (!C)
5795       continue;
5796     SmallVector<Expr *, 4> SubExprs;
5797     auto *MI = C->mapperlist_begin();
5798     for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
5799          ++I, ++MI) {
5800       // Expression is mapped using mapper - skip it.
5801       if (*MI)
5802         continue;
5803       Expr *E = *I;
5804       // Expression is dependent - skip it, build the mapper when it gets
5805       // instantiated.
5806       if (E->isTypeDependent() || E->isValueDependent() ||
5807           E->containsUnexpandedParameterPack())
5808         continue;
5809       // Array section - need to check for the mapping of the array section
5810       // element.
5811       QualType CanonType = E->getType().getCanonicalType();
5812       if (CanonType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
5813         const auto *OASE = cast<ArraySectionExpr>(E->IgnoreParenImpCasts());
5814         QualType BaseType =
5815             ArraySectionExpr::getBaseOriginalType(OASE->getBase());
5816         QualType ElemType;
5817         if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
5818           ElemType = ATy->getElementType();
5819         else
5820           ElemType = BaseType->getPointeeType();
5821         CanonType = ElemType;
5822       }
5823 
5824       // DFS over data members in structures/classes.
5825       SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(
5826           1, {CanonType, nullptr});
5827       llvm::DenseMap<const Type *, Expr *> Visited;
5828       SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(
5829           1, {nullptr, 1});
5830       while (!Types.empty()) {
5831         QualType BaseType;
5832         FieldDecl *CurFD;
5833         std::tie(BaseType, CurFD) = Types.pop_back_val();
5834         while (ParentChain.back().second == 0)
5835           ParentChain.pop_back();
5836         --ParentChain.back().second;
5837         if (BaseType.isNull())
5838           continue;
5839         // Only structs/classes are allowed to have mappers.
5840         const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
5841         if (!RD)
5842           continue;
5843         auto It = Visited.find(BaseType.getTypePtr());
5844         if (It == Visited.end()) {
5845           // Try to find the associated user-defined mapper.
5846           CXXScopeSpec MapperIdScopeSpec;
5847           DeclarationNameInfo DefaultMapperId;
5848           DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
5849               &S.Context.Idents.get("default")));
5850           DefaultMapperId.setLoc(E->getExprLoc());
5851           ExprResult ER = buildUserDefinedMapperRef(
5852               S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
5853               BaseType, /*UnresolvedMapper=*/nullptr);
5854           if (ER.isInvalid())
5855             continue;
5856           It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
5857         }
5858         // Found default mapper.
5859         if (It->second) {
5860           auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
5861                                                      VK_LValue, OK_Ordinary, E);
5862           OE->setIsUnique(/*V=*/true);
5863           Expr *BaseExpr = OE;
5864           for (const auto &P : ParentChain) {
5865             if (P.first) {
5866               BaseExpr = S.BuildMemberExpr(
5867                   BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
5868                   NestedNameSpecifierLoc(), SourceLocation(), P.first,
5869                   DeclAccessPair::make(P.first, P.first->getAccess()),
5870                   /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
5871                   P.first->getType(), VK_LValue, OK_Ordinary);
5872               BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
5873             }
5874           }
5875           if (CurFD)
5876             BaseExpr = S.BuildMemberExpr(
5877                 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
5878                 NestedNameSpecifierLoc(), SourceLocation(), CurFD,
5879                 DeclAccessPair::make(CurFD, CurFD->getAccess()),
5880                 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
5881                 CurFD->getType(), VK_LValue, OK_Ordinary);
5882           SubExprs.push_back(BaseExpr);
5883           continue;
5884         }
5885         // Check for the "default" mapper for data members.
5886         bool FirstIter = true;
5887         for (FieldDecl *FD : RD->fields()) {
5888           if (!FD)
5889             continue;
5890           QualType FieldTy = FD->getType();
5891           if (FieldTy.isNull() ||
5892               !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
5893             continue;
5894           if (FirstIter) {
5895             FirstIter = false;
5896             ParentChain.emplace_back(CurFD, 1);
5897           } else {
5898             ++ParentChain.back().second;
5899           }
5900           Types.emplace_back(FieldTy, FD);
5901         }
5902       }
5903     }
5904     if (SubExprs.empty())
5905       continue;
5906     CXXScopeSpec MapperIdScopeSpec;
5907     DeclarationNameInfo MapperId;
5908     if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
5909             nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
5910             MapperIdScopeSpec, MapperId, C->getMapType(),
5911             /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
5912             SubExprs, OMPVarListLocTy()))
5913       Clauses.push_back(NewClause);
5914   }
5915 }
5916 
5917 namespace {
5918 /// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
5919 /// call in the associated loop-nest cannot be a 'parallel for'.
5920 class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
5921   Sema &SemaRef;
5922 
5923 public:
teamsLoopCanBeParallelFor() const5924   bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
5925 
5926   // Is there a nested OpenMP loop bind(parallel)
VisitOMPExecutableDirective(const OMPExecutableDirective * D)5927   void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
5928     if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
5929       if (const auto *C = D->getSingleClause<OMPBindClause>())
5930         if (C->getBindKind() == OMPC_BIND_parallel) {
5931           TeamsLoopCanBeParallelFor = false;
5932           // No need to continue visiting any more
5933           return;
5934         }
5935     }
5936     for (const Stmt *Child : D->children())
5937       if (Child)
5938         Visit(Child);
5939   }
5940 
VisitCallExpr(const CallExpr * C)5941   void VisitCallExpr(const CallExpr *C) {
5942     // Function calls inhibit parallel loop translation of 'target teams loop'
5943     // unless the assume-no-nested-parallelism flag has been specified.
5944     // OpenMP API runtime library calls do not inhibit parallel loop
5945     // translation, regardless of the assume-no-nested-parallelism.
5946     bool IsOpenMPAPI = false;
5947     auto *FD = dyn_cast_or_null<FunctionDecl>(C->getCalleeDecl());
5948     if (FD) {
5949       std::string Name = FD->getNameInfo().getAsString();
5950       IsOpenMPAPI = Name.find("omp_") == 0;
5951     }
5952     TeamsLoopCanBeParallelFor =
5953         IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
5954     if (!TeamsLoopCanBeParallelFor)
5955       return;
5956 
5957     for (const Stmt *Child : C->children())
5958       if (Child)
5959         Visit(Child);
5960   }
5961 
VisitCapturedStmt(const CapturedStmt * S)5962   void VisitCapturedStmt(const CapturedStmt *S) {
5963     if (!S)
5964       return;
5965     Visit(S->getCapturedDecl()->getBody());
5966   }
5967 
VisitStmt(const Stmt * S)5968   void VisitStmt(const Stmt *S) {
5969     if (!S)
5970       return;
5971     for (const Stmt *Child : S->children())
5972       if (Child)
5973         Visit(Child);
5974   }
TeamsLoopChecker(Sema & SemaRef)5975   explicit TeamsLoopChecker(Sema &SemaRef)
5976       : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
5977 
5978 private:
5979   bool TeamsLoopCanBeParallelFor;
5980 };
5981 } // namespace
5982 
teamsLoopCanBeParallelFor(Stmt * AStmt,Sema & SemaRef)5983 static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
5984   TeamsLoopChecker Checker(SemaRef);
5985   Checker.Visit(AStmt);
5986   return Checker.teamsLoopCanBeParallelFor();
5987 }
5988 
ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,const DeclarationNameInfo & DirName,OpenMPDirectiveKind CancelRegion,ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)5989 StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective(
5990     OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
5991     OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
5992     Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
5993   assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
5994 
5995   StmtResult Res = StmtError();
5996   OpenMPBindClauseKind BindKind = OMPC_BIND_unknown;
5997   llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
5998 
5999   if (const OMPBindClause *BC =
6000           OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6001     BindKind = BC->getBindKind();
6002 
6003   if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
6004     const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
6005 
6006     // Setting the enclosing teams or parallel construct for the loop
6007     // directive without bind clause.
6008     // [5.0:129:25-28] If the bind clause is not present on the construct and
6009     // the loop construct is closely nested inside a teams or parallel
6010     // construct, the binding region is the corresponding teams or parallel
6011     // region. If none of those conditions hold, the binding region is not
6012     // defined.
6013     BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6014     ArrayRef<OpenMPDirectiveKind> ParentLeafs =
6015         getLeafConstructsOrSelf(ParentDirective);
6016 
6017     if (ParentDirective == OMPD_unknown) {
6018       Diag(DSAStack->getDefaultDSALocation(),
6019            diag::err_omp_bind_required_on_loop);
6020     } else if (ParentLeafs.back() == OMPD_parallel) {
6021       BindKind = OMPC_BIND_parallel;
6022     } else if (ParentLeafs.back() == OMPD_teams) {
6023       BindKind = OMPC_BIND_teams;
6024     }
6025 
6026     assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind");
6027 
6028     OMPClause *C =
6029         ActOnOpenMPBindClause(BindKind, SourceLocation(), SourceLocation(),
6030                               SourceLocation(), SourceLocation());
6031     ClausesWithImplicit.push_back(C);
6032   }
6033 
6034   // Diagnose "loop bind(teams)" with "reduction".
6035   if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6036     for (OMPClause *C : Clauses) {
6037       if (C->getClauseKind() == OMPC_reduction)
6038         Diag(DSAStack->getDefaultDSALocation(),
6039              diag::err_omp_loop_reduction_clause);
6040     }
6041   }
6042 
6043   // First check CancelRegion which is then used in checkNestingOfRegions.
6044   if (checkCancelRegion(SemaRef, Kind, CancelRegion, StartLoc) ||
6045       checkNestingOfRegions(SemaRef, DSAStack, Kind, DirName, CancelRegion,
6046                             BindKind, StartLoc)) {
6047     return StmtError();
6048   }
6049 
6050   // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6051   if (getLangOpts().HIP && (isOpenMPTargetExecutionDirective(Kind) ||
6052                             isOpenMPTargetDataManagementDirective(Kind)))
6053     Diag(StartLoc, diag::warn_hip_omp_target_directives);
6054 
6055   VarsWithInheritedDSAType VarsWithInheritedDSA;
6056   bool ErrorFound = false;
6057   ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6058 
6059   if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6060       isOpenMPCapturingDirective(Kind)) {
6061     assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6062 
6063     // Check default data sharing attributes for referenced variables.
6064     DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(AStmt));
6065     int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6066     Stmt *S = AStmt;
6067     while (--ThisCaptureLevel >= 0)
6068       S = cast<CapturedStmt>(S)->getCapturedStmt();
6069     DSAChecker.Visit(S);
6070     if (!isOpenMPTargetDataManagementDirective(Kind) &&
6071         !isOpenMPTaskingDirective(Kind)) {
6072       // Visit subcaptures to generate implicit clauses for captured vars.
6073       auto *CS = cast<CapturedStmt>(AStmt);
6074       SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
6075       getOpenMPCaptureRegions(CaptureRegions, Kind);
6076       // Ignore outer tasking regions for target directives.
6077       if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6078         CS = cast<CapturedStmt>(CS->getCapturedStmt());
6079       DSAChecker.visitSubCaptures(CS);
6080     }
6081     if (DSAChecker.isErrorFound())
6082       return StmtError();
6083     // Generate list of implicitly defined firstprivate variables.
6084     VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6085     VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6086 
6087     SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers>
6088         ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6089     // Get the original location of present modifier from Defaultmap clause.
6090     SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6091     for (OMPClause *C : Clauses) {
6092       if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6093         if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6094           PresentModifierLocs[DMC->getDefaultmapKind()] =
6095               DMC->getDefaultmapModifierLoc();
6096     }
6097 
6098     for (OpenMPDefaultmapClauseKind K :
6099          llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6100              OpenMPDefaultmapClauseKind(), OMPC_DEFAULTMAP_unknown)) {
6101       std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[K]),
6102                   ImpInfo.MapModifiers[K].size(), PresentModifierLocs[K]);
6103     }
6104     // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6105     for (OMPClause *C : Clauses) {
6106       if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6107         for (Expr *E : IRC->taskgroup_descriptors())
6108           if (E)
6109             ImpInfo.Firstprivates.insert(E);
6110       }
6111       // OpenMP 5.0, 2.10.1 task Construct
6112       // [detach clause]... The event-handle will be considered as if it was
6113       // specified on a firstprivate clause.
6114       if (auto *DC = dyn_cast<OMPDetachClause>(C))
6115         ImpInfo.Firstprivates.insert(DC->getEventHandler());
6116     }
6117     if (!ImpInfo.Firstprivates.empty()) {
6118       if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
6119               ImpInfo.Firstprivates.getArrayRef(), SourceLocation(),
6120               SourceLocation(), SourceLocation())) {
6121         ClausesWithImplicit.push_back(Implicit);
6122         ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6123                      ImpInfo.Firstprivates.size();
6124       } else {
6125         ErrorFound = true;
6126       }
6127     }
6128     if (!ImpInfo.Privates.empty()) {
6129       if (OMPClause *Implicit = ActOnOpenMPPrivateClause(
6130               ImpInfo.Privates.getArrayRef(), SourceLocation(),
6131               SourceLocation(), SourceLocation())) {
6132         ClausesWithImplicit.push_back(Implicit);
6133         ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6134                      ImpInfo.Privates.size();
6135       } else {
6136         ErrorFound = true;
6137       }
6138     }
6139     // OpenMP 5.0 [2.19.7]
6140     // If a list item appears in a reduction, lastprivate or linear
6141     // clause on a combined target construct then it is treated as
6142     // if it also appears in a map clause with a map-type of tofrom
6143     if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6144         isOpenMPTargetExecutionDirective(Kind)) {
6145       SmallVector<Expr *, 4> ImplicitExprs;
6146       for (OMPClause *C : Clauses) {
6147         if (auto *RC = dyn_cast<OMPReductionClause>(C))
6148           for (Expr *E : RC->varlist())
6149             if (!isa<DeclRefExpr>(E->IgnoreParenImpCasts()))
6150               ImplicitExprs.emplace_back(E);
6151       }
6152       if (!ImplicitExprs.empty()) {
6153         ArrayRef<Expr *> Exprs = ImplicitExprs;
6154         CXXScopeSpec MapperIdScopeSpec;
6155         DeclarationNameInfo MapperId;
6156         if (OMPClause *Implicit = ActOnOpenMPMapClause(
6157                 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(),
6158                 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6159                 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6160                 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6161           ClausesWithImplicit.emplace_back(Implicit);
6162       }
6163     }
6164     for (unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6165       int ClauseKindCnt = -1;
6166       for (unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6167         ArrayRef<Expr *> ImplicitMap = ImpInfo.Mappings[I][J].getArrayRef();
6168         ++ClauseKindCnt;
6169         if (ImplicitMap.empty())
6170           continue;
6171         CXXScopeSpec MapperIdScopeSpec;
6172         DeclarationNameInfo MapperId;
6173         auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6174         if (OMPClause *Implicit = ActOnOpenMPMapClause(
6175                 nullptr, ImpInfo.MapModifiers[I], ImplicitMapModifiersLoc[I],
6176                 MapperIdScopeSpec, MapperId, K, /*IsMapTypeImplicit=*/true,
6177                 SourceLocation(), SourceLocation(), ImplicitMap,
6178                 OMPVarListLocTy())) {
6179           ClausesWithImplicit.emplace_back(Implicit);
6180           ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6181                         ImplicitMap.size();
6182         } else {
6183           ErrorFound = true;
6184         }
6185       }
6186     }
6187     // Build expressions for implicit maps of data members with 'default'
6188     // mappers.
6189     if (getLangOpts().OpenMP >= 50)
6190       processImplicitMapsWithDefaultMappers(SemaRef, DSAStack,
6191                                             ClausesWithImplicit);
6192   }
6193 
6194   switch (Kind) {
6195   case OMPD_parallel:
6196     Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6197                                        EndLoc);
6198     break;
6199   case OMPD_simd:
6200     Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6201                                    VarsWithInheritedDSA);
6202     break;
6203   case OMPD_tile:
6204     Res =
6205         ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6206     break;
6207   case OMPD_stripe:
6208     Res = ActOnOpenMPStripeDirective(ClausesWithImplicit, AStmt, StartLoc,
6209                                      EndLoc);
6210     break;
6211   case OMPD_unroll:
6212     Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6213                                      EndLoc);
6214     break;
6215   case OMPD_reverse:
6216     assert(ClausesWithImplicit.empty() &&
6217            "reverse directive does not support any clauses");
6218     Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6219     break;
6220   case OMPD_interchange:
6221     Res = ActOnOpenMPInterchangeDirective(ClausesWithImplicit, AStmt, StartLoc,
6222                                           EndLoc);
6223     break;
6224   case OMPD_for:
6225     Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6226                                   VarsWithInheritedDSA);
6227     break;
6228   case OMPD_for_simd:
6229     Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6230                                       EndLoc, VarsWithInheritedDSA);
6231     break;
6232   case OMPD_sections:
6233     Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6234                                        EndLoc);
6235     break;
6236   case OMPD_section:
6237     assert(ClausesWithImplicit.empty() &&
6238            "No clauses are allowed for 'omp section' directive");
6239     Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6240     break;
6241   case OMPD_single:
6242     Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6243                                      EndLoc);
6244     break;
6245   case OMPD_master:
6246     assert(ClausesWithImplicit.empty() &&
6247            "No clauses are allowed for 'omp master' directive");
6248     Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6249     break;
6250   case OMPD_masked:
6251     Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6252                                      EndLoc);
6253     break;
6254   case OMPD_critical:
6255     Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6256                                        StartLoc, EndLoc);
6257     break;
6258   case OMPD_parallel_for:
6259     Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6260                                           EndLoc, VarsWithInheritedDSA);
6261     break;
6262   case OMPD_parallel_for_simd:
6263     Res = ActOnOpenMPParallelForSimdDirective(
6264         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6265     break;
6266   case OMPD_scope:
6267     Res =
6268         ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6269     break;
6270   case OMPD_parallel_master:
6271     Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6272                                              StartLoc, EndLoc);
6273     break;
6274   case OMPD_parallel_masked:
6275     Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6276                                              StartLoc, EndLoc);
6277     break;
6278   case OMPD_parallel_sections:
6279     Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6280                                                StartLoc, EndLoc);
6281     break;
6282   case OMPD_task:
6283     Res =
6284         ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6285     break;
6286   case OMPD_taskyield:
6287     assert(ClausesWithImplicit.empty() &&
6288            "No clauses are allowed for 'omp taskyield' directive");
6289     assert(AStmt == nullptr &&
6290            "No associated statement allowed for 'omp taskyield' directive");
6291     Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6292     break;
6293   case OMPD_error:
6294     assert(AStmt == nullptr &&
6295            "No associated statement allowed for 'omp error' directive");
6296     Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6297     break;
6298   case OMPD_barrier:
6299     assert(ClausesWithImplicit.empty() &&
6300            "No clauses are allowed for 'omp barrier' directive");
6301     assert(AStmt == nullptr &&
6302            "No associated statement allowed for 'omp barrier' directive");
6303     Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6304     break;
6305   case OMPD_taskwait:
6306     assert(AStmt == nullptr &&
6307            "No associated statement allowed for 'omp taskwait' directive");
6308     Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6309     break;
6310   case OMPD_taskgroup:
6311     Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6312                                         EndLoc);
6313     break;
6314   case OMPD_flush:
6315     assert(AStmt == nullptr &&
6316            "No associated statement allowed for 'omp flush' directive");
6317     Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6318     break;
6319   case OMPD_depobj:
6320     assert(AStmt == nullptr &&
6321            "No associated statement allowed for 'omp depobj' directive");
6322     Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6323     break;
6324   case OMPD_scan:
6325     assert(AStmt == nullptr &&
6326            "No associated statement allowed for 'omp scan' directive");
6327     Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6328     break;
6329   case OMPD_ordered:
6330     Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6331                                       EndLoc);
6332     break;
6333   case OMPD_atomic:
6334     Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6335                                      EndLoc);
6336     break;
6337   case OMPD_teams:
6338     Res =
6339         ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6340     break;
6341   case OMPD_target:
6342     Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6343                                      EndLoc);
6344     break;
6345   case OMPD_target_parallel:
6346     Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6347                                              StartLoc, EndLoc);
6348     break;
6349   case OMPD_target_parallel_for:
6350     Res = ActOnOpenMPTargetParallelForDirective(
6351         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6352     break;
6353   case OMPD_cancellation_point:
6354     assert(ClausesWithImplicit.empty() &&
6355            "No clauses are allowed for 'omp cancellation point' directive");
6356     assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6357                                "cancellation point' directive");
6358     Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6359     break;
6360   case OMPD_cancel:
6361     assert(AStmt == nullptr &&
6362            "No associated statement allowed for 'omp cancel' directive");
6363     Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6364                                      CancelRegion);
6365     break;
6366   case OMPD_target_data:
6367     Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6368                                          EndLoc);
6369     break;
6370   case OMPD_target_enter_data:
6371     Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6372                                               EndLoc, AStmt);
6373     break;
6374   case OMPD_target_exit_data:
6375     Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6376                                              EndLoc, AStmt);
6377     break;
6378   case OMPD_taskloop:
6379     Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6380                                        EndLoc, VarsWithInheritedDSA);
6381     break;
6382   case OMPD_taskloop_simd:
6383     Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6384                                            EndLoc, VarsWithInheritedDSA);
6385     break;
6386   case OMPD_master_taskloop:
6387     Res = ActOnOpenMPMasterTaskLoopDirective(
6388         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6389     break;
6390   case OMPD_masked_taskloop:
6391     Res = ActOnOpenMPMaskedTaskLoopDirective(
6392         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6393     break;
6394   case OMPD_master_taskloop_simd:
6395     Res = ActOnOpenMPMasterTaskLoopSimdDirective(
6396         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6397     break;
6398   case OMPD_masked_taskloop_simd:
6399     Res = ActOnOpenMPMaskedTaskLoopSimdDirective(
6400         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6401     break;
6402   case OMPD_parallel_master_taskloop:
6403     Res = ActOnOpenMPParallelMasterTaskLoopDirective(
6404         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6405     break;
6406   case OMPD_parallel_masked_taskloop:
6407     Res = ActOnOpenMPParallelMaskedTaskLoopDirective(
6408         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6409     break;
6410   case OMPD_parallel_master_taskloop_simd:
6411     Res = ActOnOpenMPParallelMasterTaskLoopSimdDirective(
6412         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6413     break;
6414   case OMPD_parallel_masked_taskloop_simd:
6415     Res = ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
6416         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6417     break;
6418   case OMPD_distribute:
6419     Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6420                                          EndLoc, VarsWithInheritedDSA);
6421     break;
6422   case OMPD_target_update:
6423     Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6424                                            EndLoc, AStmt);
6425     break;
6426   case OMPD_distribute_parallel_for:
6427     Res = ActOnOpenMPDistributeParallelForDirective(
6428         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6429     break;
6430   case OMPD_distribute_parallel_for_simd:
6431     Res = ActOnOpenMPDistributeParallelForSimdDirective(
6432         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6433     break;
6434   case OMPD_distribute_simd:
6435     Res = ActOnOpenMPDistributeSimdDirective(
6436         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6437     break;
6438   case OMPD_target_parallel_for_simd:
6439     Res = ActOnOpenMPTargetParallelForSimdDirective(
6440         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6441     break;
6442   case OMPD_target_simd:
6443     Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6444                                          EndLoc, VarsWithInheritedDSA);
6445     break;
6446   case OMPD_teams_distribute:
6447     Res = ActOnOpenMPTeamsDistributeDirective(
6448         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6449     break;
6450   case OMPD_teams_distribute_simd:
6451     Res = ActOnOpenMPTeamsDistributeSimdDirective(
6452         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6453     break;
6454   case OMPD_teams_distribute_parallel_for_simd:
6455     Res = ActOnOpenMPTeamsDistributeParallelForSimdDirective(
6456         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6457     break;
6458   case OMPD_teams_distribute_parallel_for:
6459     Res = ActOnOpenMPTeamsDistributeParallelForDirective(
6460         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6461     break;
6462   case OMPD_target_teams:
6463     Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6464                                           EndLoc);
6465     break;
6466   case OMPD_target_teams_distribute:
6467     Res = ActOnOpenMPTargetTeamsDistributeDirective(
6468         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6469     break;
6470   case OMPD_target_teams_distribute_parallel_for:
6471     Res = ActOnOpenMPTargetTeamsDistributeParallelForDirective(
6472         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6473     break;
6474   case OMPD_target_teams_distribute_parallel_for_simd:
6475     Res = ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
6476         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6477     break;
6478   case OMPD_target_teams_distribute_simd:
6479     Res = ActOnOpenMPTargetTeamsDistributeSimdDirective(
6480         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6481     break;
6482   case OMPD_interop:
6483     assert(AStmt == nullptr &&
6484            "No associated statement allowed for 'omp interop' directive");
6485     Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6486     break;
6487   case OMPD_dispatch:
6488     Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6489                                        EndLoc);
6490     break;
6491   case OMPD_loop:
6492     Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6493                                           EndLoc, VarsWithInheritedDSA);
6494     break;
6495   case OMPD_teams_loop:
6496     Res = ActOnOpenMPTeamsGenericLoopDirective(
6497         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6498     break;
6499   case OMPD_target_teams_loop:
6500     Res = ActOnOpenMPTargetTeamsGenericLoopDirective(
6501         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6502     break;
6503   case OMPD_parallel_loop:
6504     Res = ActOnOpenMPParallelGenericLoopDirective(
6505         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6506     break;
6507   case OMPD_target_parallel_loop:
6508     Res = ActOnOpenMPTargetParallelGenericLoopDirective(
6509         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6510     break;
6511   case OMPD_declare_target:
6512   case OMPD_end_declare_target:
6513   case OMPD_threadprivate:
6514   case OMPD_allocate:
6515   case OMPD_declare_reduction:
6516   case OMPD_declare_mapper:
6517   case OMPD_declare_simd:
6518   case OMPD_requires:
6519   case OMPD_declare_variant:
6520   case OMPD_begin_declare_variant:
6521   case OMPD_end_declare_variant:
6522     llvm_unreachable("OpenMP Directive is not allowed");
6523   case OMPD_unknown:
6524   default:
6525     llvm_unreachable("Unknown OpenMP directive");
6526   }
6527 
6528   ErrorFound = Res.isInvalid() || ErrorFound;
6529 
6530   // Check variables in the clauses if default(none) or
6531   // default(firstprivate) was specified.
6532   if (DSAStack->getDefaultDSA() == DSA_none ||
6533       DSAStack->getDefaultDSA() == DSA_private ||
6534       DSAStack->getDefaultDSA() == DSA_firstprivate) {
6535     DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6536     for (OMPClause *C : Clauses) {
6537       switch (C->getClauseKind()) {
6538       case OMPC_num_threads:
6539       case OMPC_dist_schedule:
6540         // Do not analyze if no parent teams directive.
6541         if (isOpenMPTeamsDirective(Kind))
6542           break;
6543         continue;
6544       case OMPC_if:
6545         if (isOpenMPTeamsDirective(Kind) &&
6546             cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6547           break;
6548         if (isOpenMPParallelDirective(Kind) &&
6549             isOpenMPTaskLoopDirective(Kind) &&
6550             cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6551           break;
6552         continue;
6553       case OMPC_schedule:
6554       case OMPC_detach:
6555         break;
6556       case OMPC_grainsize:
6557       case OMPC_num_tasks:
6558       case OMPC_final:
6559       case OMPC_priority:
6560       case OMPC_novariants:
6561       case OMPC_nocontext:
6562         // Do not analyze if no parent parallel directive.
6563         if (isOpenMPParallelDirective(Kind))
6564           break;
6565         continue;
6566       case OMPC_ordered:
6567       case OMPC_device:
6568       case OMPC_num_teams:
6569       case OMPC_thread_limit:
6570       case OMPC_hint:
6571       case OMPC_collapse:
6572       case OMPC_safelen:
6573       case OMPC_simdlen:
6574       case OMPC_sizes:
6575       case OMPC_default:
6576       case OMPC_proc_bind:
6577       case OMPC_private:
6578       case OMPC_firstprivate:
6579       case OMPC_lastprivate:
6580       case OMPC_shared:
6581       case OMPC_reduction:
6582       case OMPC_task_reduction:
6583       case OMPC_in_reduction:
6584       case OMPC_linear:
6585       case OMPC_aligned:
6586       case OMPC_copyin:
6587       case OMPC_copyprivate:
6588       case OMPC_nowait:
6589       case OMPC_untied:
6590       case OMPC_mergeable:
6591       case OMPC_allocate:
6592       case OMPC_read:
6593       case OMPC_write:
6594       case OMPC_update:
6595       case OMPC_capture:
6596       case OMPC_compare:
6597       case OMPC_seq_cst:
6598       case OMPC_acq_rel:
6599       case OMPC_acquire:
6600       case OMPC_release:
6601       case OMPC_relaxed:
6602       case OMPC_depend:
6603       case OMPC_threads:
6604       case OMPC_simd:
6605       case OMPC_map:
6606       case OMPC_nogroup:
6607       case OMPC_defaultmap:
6608       case OMPC_to:
6609       case OMPC_from:
6610       case OMPC_use_device_ptr:
6611       case OMPC_use_device_addr:
6612       case OMPC_is_device_ptr:
6613       case OMPC_has_device_addr:
6614       case OMPC_nontemporal:
6615       case OMPC_order:
6616       case OMPC_destroy:
6617       case OMPC_inclusive:
6618       case OMPC_exclusive:
6619       case OMPC_uses_allocators:
6620       case OMPC_affinity:
6621       case OMPC_bind:
6622       case OMPC_filter:
6623       case OMPC_severity:
6624       case OMPC_message:
6625         continue;
6626       case OMPC_allocator:
6627       case OMPC_flush:
6628       case OMPC_depobj:
6629       case OMPC_threadprivate:
6630       case OMPC_uniform:
6631       case OMPC_unknown:
6632       case OMPC_unified_address:
6633       case OMPC_unified_shared_memory:
6634       case OMPC_reverse_offload:
6635       case OMPC_dynamic_allocators:
6636       case OMPC_atomic_default_mem_order:
6637       case OMPC_self_maps:
6638       case OMPC_device_type:
6639       case OMPC_match:
6640       case OMPC_when:
6641       case OMPC_at:
6642       default:
6643         llvm_unreachable("Unexpected clause");
6644       }
6645       for (Stmt *CC : C->children()) {
6646         if (CC)
6647           DSAChecker.Visit(CC);
6648       }
6649     }
6650     for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6651       VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6652   }
6653   for (const auto &P : VarsWithInheritedDSA) {
6654     if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6655       continue;
6656     ErrorFound = true;
6657     if (DSAStack->getDefaultDSA() == DSA_none ||
6658         DSAStack->getDefaultDSA() == DSA_private ||
6659         DSAStack->getDefaultDSA() == DSA_firstprivate) {
6660       Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6661           << P.first << P.second->getSourceRange();
6662       Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6663     } else if (getLangOpts().OpenMP >= 50) {
6664       Diag(P.second->getExprLoc(),
6665            diag::err_omp_defaultmap_no_attr_for_variable)
6666           << P.first << P.second->getSourceRange();
6667       Diag(DSAStack->getDefaultDSALocation(),
6668            diag::note_omp_defaultmap_attr_none);
6669     }
6670   }
6671 
6672   llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6673   for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(Kind)) {
6674     if (isAllowedClauseForDirective(D, OMPC_if, getLangOpts().OpenMP))
6675       AllowedNameModifiers.push_back(D);
6676   }
6677   if (!AllowedNameModifiers.empty())
6678     ErrorFound = checkIfClauses(SemaRef, Kind, Clauses, AllowedNameModifiers) ||
6679                  ErrorFound;
6680 
6681   if (ErrorFound)
6682     return StmtError();
6683 
6684   if (!SemaRef.CurContext->isDependentContext() &&
6685       isOpenMPTargetExecutionDirective(Kind) &&
6686       !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6687         DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6688         DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6689         DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6690     // Register target to DSA Stack.
6691     DSAStack->addTargetDirLocation(StartLoc);
6692   }
6693 
6694   return Res;
6695 }
6696 
ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG,OMPDeclareSimdDeclAttr::BranchStateTy BS,Expr * Simdlen,ArrayRef<Expr * > Uniforms,ArrayRef<Expr * > Aligneds,ArrayRef<Expr * > Alignments,ArrayRef<Expr * > Linears,ArrayRef<unsigned> LinModifiers,ArrayRef<Expr * > Steps,SourceRange SR)6697 SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareSimdDirective(
6698     DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6699     ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6700     ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6701     ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6702   assert(Aligneds.size() == Alignments.size());
6703   assert(Linears.size() == LinModifiers.size());
6704   assert(Linears.size() == Steps.size());
6705   if (!DG || DG.get().isNull())
6706     return DeclGroupPtrTy();
6707 
6708   const int SimdId = 0;
6709   if (!DG.get().isSingleDecl()) {
6710     Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6711         << SimdId;
6712     return DG;
6713   }
6714   Decl *ADecl = DG.get().getSingleDecl();
6715   if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6716     ADecl = FTD->getTemplatedDecl();
6717 
6718   auto *FD = dyn_cast<FunctionDecl>(ADecl);
6719   if (!FD) {
6720     Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6721     return DeclGroupPtrTy();
6722   }
6723 
6724   // OpenMP [2.8.2, declare simd construct, Description]
6725   // The parameter of the simdlen clause must be a constant positive integer
6726   // expression.
6727   ExprResult SL;
6728   if (Simdlen)
6729     SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6730   // OpenMP [2.8.2, declare simd construct, Description]
6731   // The special this pointer can be used as if was one of the arguments to the
6732   // function in any of the linear, aligned, or uniform clauses.
6733   // The uniform clause declares one or more arguments to have an invariant
6734   // value for all concurrent invocations of the function in the execution of a
6735   // single SIMD loop.
6736   llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6737   const Expr *UniformedLinearThis = nullptr;
6738   for (const Expr *E : Uniforms) {
6739     E = E->IgnoreParenImpCasts();
6740     if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6741       if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6742         if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6743             FD->getParamDecl(PVD->getFunctionScopeIndex())
6744                     ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
6745           UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6746           continue;
6747         }
6748     if (isa<CXXThisExpr>(E)) {
6749       UniformedLinearThis = E;
6750       continue;
6751     }
6752     Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6753         << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6754   }
6755   // OpenMP [2.8.2, declare simd construct, Description]
6756   // The aligned clause declares that the object to which each list item points
6757   // is aligned to the number of bytes expressed in the optional parameter of
6758   // the aligned clause.
6759   // The special this pointer can be used as if was one of the arguments to the
6760   // function in any of the linear, aligned, or uniform clauses.
6761   // The type of list items appearing in the aligned clause must be array,
6762   // pointer, reference to array, or reference to pointer.
6763   llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6764   const Expr *AlignedThis = nullptr;
6765   for (const Expr *E : Aligneds) {
6766     E = E->IgnoreParenImpCasts();
6767     if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6768       if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6769         const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6770         if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6771             FD->getParamDecl(PVD->getFunctionScopeIndex())
6772                     ->getCanonicalDecl() == CanonPVD) {
6773           // OpenMP  [2.8.1, simd construct, Restrictions]
6774           // A list-item cannot appear in more than one aligned clause.
6775           auto [It, Inserted] = AlignedArgs.try_emplace(CanonPVD, E);
6776           if (!Inserted) {
6777             Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6778                 << 1 << getOpenMPClauseNameForDiag(OMPC_aligned)
6779                 << E->getSourceRange();
6780             Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
6781                 << getOpenMPClauseNameForDiag(OMPC_aligned);
6782             continue;
6783           }
6784           QualType QTy = PVD->getType()
6785                              .getNonReferenceType()
6786                              .getUnqualifiedType()
6787                              .getCanonicalType();
6788           const Type *Ty = QTy.getTypePtrOrNull();
6789           if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
6790             Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
6791                 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
6792             Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6793           }
6794           continue;
6795         }
6796       }
6797     if (isa<CXXThisExpr>(E)) {
6798       if (AlignedThis) {
6799         Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6800             << 2 << getOpenMPClauseNameForDiag(OMPC_aligned)
6801             << E->getSourceRange();
6802         Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
6803             << getOpenMPClauseNameForDiag(OMPC_aligned);
6804       }
6805       AlignedThis = E;
6806       continue;
6807     }
6808     Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6809         << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6810   }
6811   // The optional parameter of the aligned clause, alignment, must be a constant
6812   // positive integer expression. If no optional parameter is specified,
6813   // implementation-defined default alignments for SIMD instructions on the
6814   // target platforms are assumed.
6815   SmallVector<const Expr *, 4> NewAligns;
6816   for (Expr *E : Alignments) {
6817     ExprResult Align;
6818     if (E)
6819       Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
6820     NewAligns.push_back(Align.get());
6821   }
6822   // OpenMP [2.8.2, declare simd construct, Description]
6823   // The linear clause declares one or more list items to be private to a SIMD
6824   // lane and to have a linear relationship with respect to the iteration space
6825   // of a loop.
6826   // The special this pointer can be used as if was one of the arguments to the
6827   // function in any of the linear, aligned, or uniform clauses.
6828   // When a linear-step expression is specified in a linear clause it must be
6829   // either a constant integer expression or an integer-typed parameter that is
6830   // specified in a uniform clause on the directive.
6831   llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
6832   const bool IsUniformedThis = UniformedLinearThis != nullptr;
6833   auto MI = LinModifiers.begin();
6834   for (const Expr *E : Linears) {
6835     auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
6836     ++MI;
6837     E = E->IgnoreParenImpCasts();
6838     if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6839       if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6840         const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6841         if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6842             FD->getParamDecl(PVD->getFunctionScopeIndex())
6843                     ->getCanonicalDecl() == CanonPVD) {
6844           // OpenMP  [2.15.3.7, linear Clause, Restrictions]
6845           // A list-item cannot appear in more than one linear clause.
6846           if (auto It = LinearArgs.find(CanonPVD); It != LinearArgs.end()) {
6847             Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6848                 << getOpenMPClauseNameForDiag(OMPC_linear)
6849                 << getOpenMPClauseNameForDiag(OMPC_linear)
6850                 << E->getSourceRange();
6851             Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
6852                 << getOpenMPClauseNameForDiag(OMPC_linear);
6853             continue;
6854           }
6855           // Each argument can appear in at most one uniform or linear clause.
6856           if (auto It = UniformedArgs.find(CanonPVD);
6857               It != UniformedArgs.end()) {
6858             Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6859                 << getOpenMPClauseNameForDiag(OMPC_linear)
6860                 << getOpenMPClauseNameForDiag(OMPC_uniform)
6861                 << E->getSourceRange();
6862             Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
6863                 << getOpenMPClauseNameForDiag(OMPC_uniform);
6864             continue;
6865           }
6866           LinearArgs[CanonPVD] = E;
6867           if (E->isValueDependent() || E->isTypeDependent() ||
6868               E->isInstantiationDependent() ||
6869               E->containsUnexpandedParameterPack())
6870             continue;
6871           (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
6872                                       PVD->getOriginalType(),
6873                                       /*IsDeclareSimd=*/true);
6874           continue;
6875         }
6876       }
6877     if (isa<CXXThisExpr>(E)) {
6878       if (UniformedLinearThis) {
6879         Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6880             << getOpenMPClauseNameForDiag(OMPC_linear)
6881             << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
6882                                                           : OMPC_linear)
6883             << E->getSourceRange();
6884         Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
6885             << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
6886                                                           : OMPC_linear);
6887         continue;
6888       }
6889       UniformedLinearThis = E;
6890       if (E->isValueDependent() || E->isTypeDependent() ||
6891           E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
6892         continue;
6893       (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
6894                                   E->getType(), /*IsDeclareSimd=*/true);
6895       continue;
6896     }
6897     Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6898         << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6899   }
6900   Expr *Step = nullptr;
6901   Expr *NewStep = nullptr;
6902   SmallVector<Expr *, 4> NewSteps;
6903   for (Expr *E : Steps) {
6904     // Skip the same step expression, it was checked already.
6905     if (Step == E || !E) {
6906       NewSteps.push_back(E ? NewStep : nullptr);
6907       continue;
6908     }
6909     Step = E;
6910     if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
6911       if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6912         const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6913         if (UniformedArgs.count(CanonPVD) == 0) {
6914           Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
6915               << Step->getSourceRange();
6916         } else if (E->isValueDependent() || E->isTypeDependent() ||
6917                    E->isInstantiationDependent() ||
6918                    E->containsUnexpandedParameterPack() ||
6919                    CanonPVD->getType()->hasIntegerRepresentation()) {
6920           NewSteps.push_back(Step);
6921         } else {
6922           Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
6923               << Step->getSourceRange();
6924         }
6925         continue;
6926       }
6927     NewStep = Step;
6928     if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
6929         !Step->isInstantiationDependent() &&
6930         !Step->containsUnexpandedParameterPack()) {
6931       NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
6932                     .get();
6933       if (NewStep)
6934         NewStep = SemaRef
6935                       .VerifyIntegerConstantExpression(
6936                           NewStep, /*FIXME*/ AllowFoldKind::Allow)
6937                       .get();
6938     }
6939     NewSteps.push_back(NewStep);
6940   }
6941   auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
6942       getASTContext(), BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
6943       Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
6944       const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
6945       const_cast<Expr **>(Linears.data()), Linears.size(),
6946       const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
6947       NewSteps.data(), NewSteps.size(), SR);
6948   ADecl->addAttr(NewAttr);
6949   return DG;
6950 }
6951 
ActOnOpenMPInformationalDirective(OpenMPDirectiveKind Kind,const DeclarationNameInfo & DirName,ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)6952 StmtResult SemaOpenMP::ActOnOpenMPInformationalDirective(
6953     OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6954     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
6955     SourceLocation EndLoc) {
6956   assert(isOpenMPInformationalDirective(Kind) &&
6957          "Unexpected directive category");
6958 
6959   StmtResult Res = StmtError();
6960 
6961   switch (Kind) {
6962   case OMPD_assume:
6963     Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc);
6964     break;
6965   default:
6966     llvm_unreachable("Unknown OpenMP directive");
6967   }
6968 
6969   return Res;
6970 }
6971 
setPrototype(Sema & S,FunctionDecl * FD,FunctionDecl * FDWithProto,QualType NewType)6972 static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
6973                          QualType NewType) {
6974   assert(NewType->isFunctionProtoType() &&
6975          "Expected function type with prototype.");
6976   assert(FD->getType()->isFunctionNoProtoType() &&
6977          "Expected function with type with no prototype.");
6978   assert(FDWithProto->getType()->isFunctionProtoType() &&
6979          "Expected function with prototype.");
6980   // Synthesize parameters with the same types.
6981   FD->setType(NewType);
6982   SmallVector<ParmVarDecl *, 16> Params;
6983   for (const ParmVarDecl *P : FDWithProto->parameters()) {
6984     auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
6985                                       SourceLocation(), nullptr, P->getType(),
6986                                       /*TInfo=*/nullptr, SC_None, nullptr);
6987     Param->setScopeInfo(0, Params.size());
6988     Param->setImplicit();
6989     Params.push_back(Param);
6990   }
6991 
6992   FD->setParams(Params);
6993 }
6994 
ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl * D)6995 void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) {
6996   if (D->isInvalidDecl())
6997     return;
6998   FunctionDecl *FD = nullptr;
6999   if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7000     FD = UTemplDecl->getTemplatedDecl();
7001   else
7002     FD = cast<FunctionDecl>(D);
7003   assert(FD && "Expected a function declaration!");
7004 
7005   // If we are instantiating templates we do *not* apply scoped assumptions but
7006   // only global ones. We apply scoped assumption to the template definition
7007   // though.
7008   if (!SemaRef.inTemplateInstantiation()) {
7009     for (OMPAssumeAttr *AA : OMPAssumeScoped)
7010       FD->addAttr(AA);
7011   }
7012   for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7013     FD->addAttr(AA);
7014 }
7015 
OMPDeclareVariantScope(OMPTraitInfo & TI)7016 SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7017     : TI(&TI), NameSuffix(TI.getMangledName()) {}
7018 
ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope * S,Declarator & D,MultiTemplateParamsArg TemplateParamLists,SmallVectorImpl<FunctionDecl * > & Bases)7019 void SemaOpenMP::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
7020     Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7021     SmallVectorImpl<FunctionDecl *> &Bases) {
7022   if (!D.getIdentifier())
7023     return;
7024 
7025   OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7026 
7027   // Template specialization is an extension, check if we do it.
7028   bool IsTemplated = !TemplateParamLists.empty();
7029   if (IsTemplated &&
7030       !DVScope.TI->isExtensionActive(
7031           llvm::omp::TraitProperty::implementation_extension_allow_templates))
7032     return;
7033 
7034   const IdentifierInfo *BaseII = D.getIdentifier();
7035   LookupResult Lookup(SemaRef, DeclarationName(BaseII), D.getIdentifierLoc(),
7036                       Sema::LookupOrdinaryName);
7037   SemaRef.LookupParsedName(Lookup, S, &D.getCXXScopeSpec(),
7038                            /*ObjectType=*/QualType());
7039 
7040   TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
7041   QualType FType = TInfo->getType();
7042 
7043   bool IsConstexpr =
7044       D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr;
7045   bool IsConsteval =
7046       D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval;
7047 
7048   for (auto *Candidate : Lookup) {
7049     auto *CandidateDecl = Candidate->getUnderlyingDecl();
7050     FunctionDecl *UDecl = nullptr;
7051     if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7052       auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7053       if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7054         UDecl = FTD->getTemplatedDecl();
7055     } else if (!IsTemplated)
7056       UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7057     if (!UDecl)
7058       continue;
7059 
7060     // Don't specialize constexpr/consteval functions with
7061     // non-constexpr/consteval functions.
7062     if (UDecl->isConstexpr() && !IsConstexpr)
7063       continue;
7064     if (UDecl->isConsteval() && !IsConsteval)
7065       continue;
7066 
7067     QualType UDeclTy = UDecl->getType();
7068     if (!UDeclTy->isDependentType()) {
7069       QualType NewType = getASTContext().mergeFunctionTypes(
7070           FType, UDeclTy, /*OfBlockPointer=*/false,
7071           /*Unqualified=*/false, /*AllowCXX=*/true);
7072       if (NewType.isNull())
7073         continue;
7074     }
7075 
7076     // Found a base!
7077     Bases.push_back(UDecl);
7078   }
7079 
7080   bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7081       llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7082   // If no base was found we create a declaration that we use as base.
7083   if (Bases.empty() && UseImplicitBase) {
7084     D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
7085     Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7086     BaseD->setImplicit(true);
7087     if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7088       Bases.push_back(BaseTemplD->getTemplatedDecl());
7089     else
7090       Bases.push_back(cast<FunctionDecl>(BaseD));
7091   }
7092 
7093   std::string MangledName;
7094   MangledName += D.getIdentifier()->getName();
7095   MangledName += getOpenMPVariantManglingSeparatorStr();
7096   MangledName += DVScope.NameSuffix;
7097   IdentifierInfo &VariantII = getASTContext().Idents.get(MangledName);
7098 
7099   VariantII.setMangledOpenMPVariantName(true);
7100   D.SetIdentifier(&VariantII, D.getBeginLoc());
7101 }
7102 
ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(Decl * D,SmallVectorImpl<FunctionDecl * > & Bases)7103 void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
7104     Decl *D, SmallVectorImpl<FunctionDecl *> &Bases) {
7105   // Do not mark function as is used to prevent its emission if this is the
7106   // only place where it is used.
7107   EnterExpressionEvaluationContext Unevaluated(
7108       SemaRef, Sema::ExpressionEvaluationContext::Unevaluated);
7109 
7110   FunctionDecl *FD = nullptr;
7111   if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7112     FD = UTemplDecl->getTemplatedDecl();
7113   else
7114     FD = cast<FunctionDecl>(D);
7115   auto *VariantFuncRef = DeclRefExpr::Create(
7116       getASTContext(), NestedNameSpecifierLoc(), SourceLocation(), FD,
7117       /*RefersToEnclosingVariableOrCapture=*/false,
7118       /*NameLoc=*/FD->getLocation(), FD->getType(), ExprValueKind::VK_PRValue);
7119 
7120   OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7121   auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7122       getASTContext(), VariantFuncRef, DVScope.TI,
7123       /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7124       /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7125       /*NeedDeviceAddrArgs=*/nullptr, /*NeedDeviceAddrArgsSize=*/0,
7126       /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7127   for (FunctionDecl *BaseFD : Bases)
7128     BaseFD->addAttr(OMPDeclareVariantA);
7129 }
7130 
ActOnOpenMPCall(ExprResult Call,Scope * Scope,SourceLocation LParenLoc,MultiExprArg ArgExprs,SourceLocation RParenLoc,Expr * ExecConfig)7131 ExprResult SemaOpenMP::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
7132                                        SourceLocation LParenLoc,
7133                                        MultiExprArg ArgExprs,
7134                                        SourceLocation RParenLoc,
7135                                        Expr *ExecConfig) {
7136   // The common case is a regular call we do not want to specialize at all. Try
7137   // to make that case fast by bailing early.
7138   CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7139   if (!CE)
7140     return Call;
7141 
7142   FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7143   if (!CalleeFnDecl)
7144     return Call;
7145 
7146   if (getLangOpts().OpenMP >= 50 && getLangOpts().OpenMP <= 60 &&
7147       CalleeFnDecl->getIdentifier() &&
7148       CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7149     // checking for any calls inside an Order region
7150     if (Scope && Scope->isOpenMPOrderClauseScope())
7151       Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7152   }
7153 
7154   if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7155     return Call;
7156 
7157   ASTContext &Context = getASTContext();
7158   std::function<void(StringRef)> DiagUnknownTrait = [this,
7159                                                      CE](StringRef ISATrait) {
7160     // TODO Track the selector locations in a way that is accessible here to
7161     // improve the diagnostic location.
7162     Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7163         << ISATrait;
7164   };
7165   TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7166                           SemaRef.getCurFunctionDecl(),
7167                           DSAStack->getConstructTraits(), getOpenMPDeviceNum());
7168 
7169   QualType CalleeFnType = CalleeFnDecl->getType();
7170 
7171   SmallVector<Expr *, 4> Exprs;
7172   SmallVector<VariantMatchInfo, 4> VMIs;
7173   while (CalleeFnDecl) {
7174     for (OMPDeclareVariantAttr *A :
7175          CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7176       Expr *VariantRef = A->getVariantFuncRef();
7177 
7178       VariantMatchInfo VMI;
7179       OMPTraitInfo &TI = A->getTraitInfo();
7180       TI.getAsVariantMatchInfo(Context, VMI);
7181       if (!isVariantApplicableInContext(VMI, OMPCtx,
7182                                         /*DeviceSetOnly=*/false))
7183         continue;
7184 
7185       VMIs.push_back(VMI);
7186       Exprs.push_back(VariantRef);
7187     }
7188 
7189     CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7190   }
7191 
7192   ExprResult NewCall;
7193   do {
7194     int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7195     if (BestIdx < 0)
7196       return Call;
7197     Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7198     Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7199 
7200     {
7201       // Try to build a (member) call expression for the current best applicable
7202       // variant expression. We allow this to fail in which case we continue
7203       // with the next best variant expression. The fail case is part of the
7204       // implementation defined behavior in the OpenMP standard when it talks
7205       // about what differences in the function prototypes: "Any differences
7206       // that the specific OpenMP context requires in the prototype of the
7207       // variant from the base function prototype are implementation defined."
7208       // This wording is there to allow the specialized variant to have a
7209       // different type than the base function. This is intended and OK but if
7210       // we cannot create a call the difference is not in the "implementation
7211       // defined range" we allow.
7212       Sema::TentativeAnalysisScope Trap(SemaRef);
7213 
7214       if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7215         auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7216         BestExpr = MemberExpr::CreateImplicit(
7217             Context, MemberCall->getImplicitObjectArgument(),
7218             /*IsArrow=*/false, SpecializedMethod, Context.BoundMemberTy,
7219             MemberCall->getValueKind(), MemberCall->getObjectKind());
7220       }
7221       NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs,
7222                                       RParenLoc, ExecConfig);
7223       if (NewCall.isUsable()) {
7224         if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7225           FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7226           QualType NewType = getASTContext().mergeFunctionTypes(
7227               CalleeFnType, NewCalleeFnDecl->getType(),
7228               /*OfBlockPointer=*/false,
7229               /*Unqualified=*/false, /*AllowCXX=*/true);
7230           if (!NewType.isNull())
7231             break;
7232           // Don't use the call if the function type was not compatible.
7233           NewCall = nullptr;
7234         }
7235       }
7236     }
7237 
7238     VMIs.erase(VMIs.begin() + BestIdx);
7239     Exprs.erase(Exprs.begin() + BestIdx);
7240   } while (!VMIs.empty());
7241 
7242   if (!NewCall.isUsable())
7243     return Call;
7244   return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
7245 }
7246 
7247 std::optional<std::pair<FunctionDecl *, Expr *>>
checkOpenMPDeclareVariantFunction(SemaOpenMP::DeclGroupPtrTy DG,Expr * VariantRef,OMPTraitInfo & TI,unsigned NumAppendArgs,SourceRange SR)7248 SemaOpenMP::checkOpenMPDeclareVariantFunction(SemaOpenMP::DeclGroupPtrTy DG,
7249                                               Expr *VariantRef,
7250                                               OMPTraitInfo &TI,
7251                                               unsigned NumAppendArgs,
7252                                               SourceRange SR) {
7253   ASTContext &Context = getASTContext();
7254   if (!DG || DG.get().isNull())
7255     return std::nullopt;
7256 
7257   const int VariantId = 1;
7258   // Must be applied only to single decl.
7259   if (!DG.get().isSingleDecl()) {
7260     Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7261         << VariantId << SR;
7262     return std::nullopt;
7263   }
7264   Decl *ADecl = DG.get().getSingleDecl();
7265   if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7266     ADecl = FTD->getTemplatedDecl();
7267 
7268   // Decl must be a function.
7269   auto *FD = dyn_cast<FunctionDecl>(ADecl);
7270   if (!FD) {
7271     Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7272         << VariantId << SR;
7273     return std::nullopt;
7274   }
7275 
7276   auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7277     // The 'target' attribute needs to be separately checked because it does
7278     // not always signify a multiversion function declaration.
7279     return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7280   };
7281   // OpenMP is not compatible with multiversion function attributes.
7282   if (HasMultiVersionAttributes(FD)) {
7283     Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7284         << SR;
7285     return std::nullopt;
7286   }
7287 
7288   // Allow #pragma omp declare variant only if the function is not used.
7289   if (FD->isUsed(false))
7290     Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7291         << FD->getLocation();
7292 
7293   // Check if the function was emitted already.
7294   const FunctionDecl *Definition;
7295   if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7296       (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7297     Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7298         << FD->getLocation();
7299 
7300   // The VariantRef must point to function.
7301   if (!VariantRef) {
7302     Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7303     return std::nullopt;
7304   }
7305 
7306   auto ShouldDelayChecks = [](Expr *&E, bool) {
7307     return E && (E->isTypeDependent() || E->isValueDependent() ||
7308                  E->containsUnexpandedParameterPack() ||
7309                  E->isInstantiationDependent());
7310   };
7311   // Do not check templates, wait until instantiation.
7312   if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7313       TI.anyScoreOrCondition(ShouldDelayChecks))
7314     return std::make_pair(FD, VariantRef);
7315 
7316   // Deal with non-constant score and user condition expressions.
7317   auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7318                                                      bool IsScore) -> bool {
7319     if (!E || E->isIntegerConstantExpr(getASTContext()))
7320       return false;
7321 
7322     if (IsScore) {
7323       // We warn on non-constant scores and pretend they were not present.
7324       Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7325           << E;
7326       E = nullptr;
7327     } else {
7328       // We could replace a non-constant user condition with "false" but we
7329       // will soon need to handle these anyway for the dynamic version of
7330       // OpenMP context selectors.
7331       Diag(E->getExprLoc(),
7332            diag::err_omp_declare_variant_user_condition_not_constant)
7333           << E;
7334     }
7335     return true;
7336   };
7337   if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7338     return std::nullopt;
7339 
7340   QualType AdjustedFnType = FD->getType();
7341   if (NumAppendArgs) {
7342     const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7343     if (!PTy) {
7344       Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7345           << SR;
7346       return std::nullopt;
7347     }
7348     // Adjust the function type to account for an extra omp_interop_t for each
7349     // specified in the append_args clause.
7350     const TypeDecl *TD = nullptr;
7351     LookupResult Result(SemaRef, &Context.Idents.get("omp_interop_t"),
7352                         SR.getBegin(), Sema::LookupOrdinaryName);
7353     if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
7354       NamedDecl *ND = Result.getFoundDecl();
7355       TD = dyn_cast_or_null<TypeDecl>(ND);
7356     }
7357     if (!TD) {
7358       Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7359       return std::nullopt;
7360     }
7361     QualType InteropType = Context.getTypeDeclType(TD);
7362     if (PTy->isVariadic()) {
7363       Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7364       return std::nullopt;
7365     }
7366     llvm::SmallVector<QualType, 8> Params;
7367     Params.append(PTy->param_type_begin(), PTy->param_type_end());
7368     Params.insert(Params.end(), NumAppendArgs, InteropType);
7369     AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7370                                              PTy->getExtProtoInfo());
7371   }
7372 
7373   // Convert VariantRef expression to the type of the original function to
7374   // resolve possible conflicts.
7375   ExprResult VariantRefCast = VariantRef;
7376   if (getLangOpts().CPlusPlus) {
7377     QualType FnPtrType;
7378     auto *Method = dyn_cast<CXXMethodDecl>(FD);
7379     if (Method && !Method->isStatic()) {
7380       FnPtrType = Context.getMemberPointerType(
7381           AdjustedFnType, /*Qualifier=*/nullptr, Method->getParent());
7382       ExprResult ER;
7383       {
7384         // Build addr_of unary op to correctly handle type checks for member
7385         // functions.
7386         Sema::TentativeAnalysisScope Trap(SemaRef);
7387         ER = SemaRef.CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7388                                           VariantRef);
7389       }
7390       if (!ER.isUsable()) {
7391         Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7392             << VariantId << VariantRef->getSourceRange();
7393         return std::nullopt;
7394       }
7395       VariantRef = ER.get();
7396     } else {
7397       FnPtrType = Context.getPointerType(AdjustedFnType);
7398     }
7399     QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7400     if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7401       ImplicitConversionSequence ICS = SemaRef.TryImplicitConversion(
7402           VariantRef, FnPtrType.getUnqualifiedType(),
7403           /*SuppressUserConversions=*/false, Sema::AllowedExplicit::None,
7404           /*InOverloadResolution=*/false,
7405           /*CStyle=*/false,
7406           /*AllowObjCWritebackConversion=*/false);
7407       if (ICS.isFailure()) {
7408         Diag(VariantRef->getExprLoc(),
7409              diag::err_omp_declare_variant_incompat_types)
7410             << VariantRef->getType()
7411             << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7412             << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7413         return std::nullopt;
7414       }
7415       VariantRefCast = SemaRef.PerformImplicitConversion(
7416           VariantRef, FnPtrType.getUnqualifiedType(),
7417           AssignmentAction::Converting);
7418       if (!VariantRefCast.isUsable())
7419         return std::nullopt;
7420     }
7421     // Drop previously built artificial addr_of unary op for member functions.
7422     if (Method && !Method->isStatic()) {
7423       Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7424       if (auto *UO = dyn_cast<UnaryOperator>(
7425               PossibleAddrOfVariantRef->IgnoreImplicit()))
7426         VariantRefCast = UO->getSubExpr();
7427     }
7428   }
7429 
7430   ExprResult ER = SemaRef.CheckPlaceholderExpr(VariantRefCast.get());
7431   if (!ER.isUsable() ||
7432       !ER.get()->IgnoreParenImpCasts()->getType()->isFunctionType()) {
7433     Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7434         << VariantId << VariantRef->getSourceRange();
7435     return std::nullopt;
7436   }
7437 
7438   // The VariantRef must point to function.
7439   auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7440   if (!DRE) {
7441     Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7442         << VariantId << VariantRef->getSourceRange();
7443     return std::nullopt;
7444   }
7445   auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7446   if (!NewFD) {
7447     Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7448         << VariantId << VariantRef->getSourceRange();
7449     return std::nullopt;
7450   }
7451 
7452   if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7453     Diag(VariantRef->getExprLoc(),
7454          diag::err_omp_declare_variant_same_base_function)
7455         << VariantRef->getSourceRange();
7456     return std::nullopt;
7457   }
7458 
7459   // Check if function types are compatible in C.
7460   if (!getLangOpts().CPlusPlus) {
7461     QualType NewType =
7462         Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7463     if (NewType.isNull()) {
7464       Diag(VariantRef->getExprLoc(),
7465            diag::err_omp_declare_variant_incompat_types)
7466           << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7467           << VariantRef->getSourceRange();
7468       return std::nullopt;
7469     }
7470     if (NewType->isFunctionProtoType()) {
7471       if (FD->getType()->isFunctionNoProtoType())
7472         setPrototype(SemaRef, FD, NewFD, NewType);
7473       else if (NewFD->getType()->isFunctionNoProtoType())
7474         setPrototype(SemaRef, NewFD, FD, NewType);
7475     }
7476   }
7477 
7478   // Check if variant function is not marked with declare variant directive.
7479   if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7480     Diag(VariantRef->getExprLoc(),
7481          diag::warn_omp_declare_variant_marked_as_declare_variant)
7482         << VariantRef->getSourceRange();
7483     SourceRange SR =
7484         NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7485     Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7486     return std::nullopt;
7487   }
7488 
7489   enum DoesntSupport {
7490     VirtFuncs = 1,
7491     Constructors = 3,
7492     Destructors = 4,
7493     DeletedFuncs = 5,
7494     DefaultedFuncs = 6,
7495     ConstexprFuncs = 7,
7496     ConstevalFuncs = 8,
7497   };
7498   if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7499     if (CXXFD->isVirtual()) {
7500       Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7501           << VirtFuncs;
7502       return std::nullopt;
7503     }
7504 
7505     if (isa<CXXConstructorDecl>(FD)) {
7506       Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7507           << Constructors;
7508       return std::nullopt;
7509     }
7510 
7511     if (isa<CXXDestructorDecl>(FD)) {
7512       Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7513           << Destructors;
7514       return std::nullopt;
7515     }
7516   }
7517 
7518   if (FD->isDeleted()) {
7519     Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7520         << DeletedFuncs;
7521     return std::nullopt;
7522   }
7523 
7524   if (FD->isDefaulted()) {
7525     Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7526         << DefaultedFuncs;
7527     return std::nullopt;
7528   }
7529 
7530   if (FD->isConstexpr()) {
7531     Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7532         << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7533     return std::nullopt;
7534   }
7535 
7536   // Check general compatibility.
7537   if (SemaRef.areMultiversionVariantFunctionsCompatible(
7538           FD, NewFD, PartialDiagnostic::NullDiagnostic(),
7539           PartialDiagnosticAt(SourceLocation(),
7540                               PartialDiagnostic::NullDiagnostic()),
7541           PartialDiagnosticAt(
7542               VariantRef->getExprLoc(),
7543               SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7544           PartialDiagnosticAt(VariantRef->getExprLoc(),
7545                               SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7546                                   << FD->getLocation()),
7547           /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7548           /*CLinkageMayDiffer=*/true))
7549     return std::nullopt;
7550   return std::make_pair(FD, cast<Expr>(DRE));
7551 }
7552 
ActOnOpenMPDeclareVariantDirective(FunctionDecl * FD,Expr * VariantRef,OMPTraitInfo & TI,ArrayRef<Expr * > AdjustArgsNothing,ArrayRef<Expr * > AdjustArgsNeedDevicePtr,ArrayRef<Expr * > AdjustArgsNeedDeviceAddr,ArrayRef<OMPInteropInfo> AppendArgs,SourceLocation AdjustArgsLoc,SourceLocation AppendArgsLoc,SourceRange SR)7553 void SemaOpenMP::ActOnOpenMPDeclareVariantDirective(
7554     FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7555     ArrayRef<Expr *> AdjustArgsNothing,
7556     ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7557     ArrayRef<Expr *> AdjustArgsNeedDeviceAddr,
7558     ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7559     SourceLocation AppendArgsLoc, SourceRange SR) {
7560 
7561   // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7562   // An adjust_args clause or append_args clause can only be specified if the
7563   // dispatch selector of the construct selector set appears in the match
7564   // clause.
7565 
7566   SmallVector<Expr *, 8> AllAdjustArgs;
7567   llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7568   llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7569   llvm::append_range(AllAdjustArgs, AdjustArgsNeedDeviceAddr);
7570 
7571   if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7572     VariantMatchInfo VMI;
7573     TI.getAsVariantMatchInfo(getASTContext(), VMI);
7574     if (!llvm::is_contained(
7575             VMI.ConstructTraits,
7576             llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7577       if (!AllAdjustArgs.empty())
7578         Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7579             << getOpenMPClauseNameForDiag(OMPC_adjust_args);
7580       if (!AppendArgs.empty())
7581         Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7582             << getOpenMPClauseNameForDiag(OMPC_append_args);
7583       return;
7584     }
7585   }
7586 
7587   // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7588   // Each argument can only appear in a single adjust_args clause for each
7589   // declare variant directive.
7590   llvm::SmallPtrSet<const VarDecl *, 4> AdjustVars;
7591 
7592   for (Expr *E : AllAdjustArgs) {
7593     E = E->IgnoreParenImpCasts();
7594     if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7595       if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7596         const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7597         if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7598             FD->getParamDecl(PVD->getFunctionScopeIndex())
7599                     ->getCanonicalDecl() == CanonPVD) {
7600           // It's a parameter of the function, check duplicates.
7601           if (!AdjustVars.insert(CanonPVD).second) {
7602             Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7603                 << PVD;
7604             return;
7605           }
7606           continue;
7607         }
7608       }
7609     }
7610     // Anything that is not a function parameter is an error.
7611     Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7612     return;
7613   }
7614 
7615   auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7616       getASTContext(), VariantRef, &TI,
7617       const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7618       const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7619       AdjustArgsNeedDevicePtr.size(),
7620       const_cast<Expr **>(AdjustArgsNeedDeviceAddr.data()),
7621       AdjustArgsNeedDeviceAddr.size(),
7622       const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7623   FD->addAttr(NewAttr);
7624 }
7625 
7626 static CapturedStmt *
setBranchProtectedScope(Sema & SemaRef,OpenMPDirectiveKind DKind,Stmt * AStmt)7627 setBranchProtectedScope(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt) {
7628   auto *CS = dyn_cast<CapturedStmt>(AStmt);
7629   assert(CS && "Captured statement expected");
7630   // 1.2.2 OpenMP Language Terminology
7631   // Structured block - An executable statement with a single entry at the
7632   // top and a single exit at the bottom.
7633   // The point of exit cannot be a branch out of the structured block.
7634   // longjmp() and throw() must not violate the entry/exit criteria.
7635   CS->getCapturedDecl()->setNothrow();
7636 
7637   for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
7638        ThisCaptureLevel > 1; --ThisCaptureLevel) {
7639     CS = cast<CapturedStmt>(CS->getCapturedStmt());
7640     // 1.2.2 OpenMP Language Terminology
7641     // Structured block - An executable statement with a single entry at the
7642     // top and a single exit at the bottom.
7643     // The point of exit cannot be a branch out of the structured block.
7644     // longjmp() and throw() must not violate the entry/exit criteria.
7645     CS->getCapturedDecl()->setNothrow();
7646   }
7647   SemaRef.setFunctionHasBranchProtectedScope();
7648   return CS;
7649 }
7650 
7651 StmtResult
ActOnOpenMPParallelDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)7652 SemaOpenMP::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
7653                                          Stmt *AStmt, SourceLocation StartLoc,
7654                                          SourceLocation EndLoc) {
7655   if (!AStmt)
7656     return StmtError();
7657 
7658   setBranchProtectedScope(SemaRef, OMPD_parallel, AStmt);
7659 
7660   return OMPParallelDirective::Create(
7661       getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
7662       DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
7663 }
7664 
7665 namespace {
7666 /// Iteration space of a single for loop.
7667 struct LoopIterationSpace final {
7668   /// True if the condition operator is the strict compare operator (<, > or
7669   /// !=).
7670   bool IsStrictCompare = false;
7671   /// Condition of the loop.
7672   Expr *PreCond = nullptr;
7673   /// This expression calculates the number of iterations in the loop.
7674   /// It is always possible to calculate it before starting the loop.
7675   Expr *NumIterations = nullptr;
7676   /// The loop counter variable.
7677   Expr *CounterVar = nullptr;
7678   /// Private loop counter variable.
7679   Expr *PrivateCounterVar = nullptr;
7680   /// This is initializer for the initial value of #CounterVar.
7681   Expr *CounterInit = nullptr;
7682   /// This is step for the #CounterVar used to generate its update:
7683   /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7684   Expr *CounterStep = nullptr;
7685   /// Should step be subtracted?
7686   bool Subtract = false;
7687   /// Source range of the loop init.
7688   SourceRange InitSrcRange;
7689   /// Source range of the loop condition.
7690   SourceRange CondSrcRange;
7691   /// Source range of the loop increment.
7692   SourceRange IncSrcRange;
7693   /// Minimum value that can have the loop control variable. Used to support
7694   /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7695   /// since only such variables can be used in non-loop invariant expressions.
7696   Expr *MinValue = nullptr;
7697   /// Maximum value that can have the loop control variable. Used to support
7698   /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7699   /// since only such variables can be used in non-loop invariant expressions.
7700   Expr *MaxValue = nullptr;
7701   /// true, if the lower bound depends on the outer loop control var.
7702   bool IsNonRectangularLB = false;
7703   /// true, if the upper bound depends on the outer loop control var.
7704   bool IsNonRectangularUB = false;
7705   /// Index of the loop this loop depends on and forms non-rectangular loop
7706   /// nest.
7707   unsigned LoopDependentIdx = 0;
7708   /// Final condition for the non-rectangular loop nest support. It is used to
7709   /// check that the number of iterations for this particular counter must be
7710   /// finished.
7711   Expr *FinalCondition = nullptr;
7712 };
7713 
7714 /// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls
7715 /// set are referenced.  Used for verifying loop nest structure before
7716 /// performing a loop collapse operation.
7717 class ForSubExprChecker : public DynamicRecursiveASTVisitor {
7718   const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7719   VarDecl *ForbiddenVar = nullptr;
7720   SourceRange ErrLoc;
7721 
7722 public:
ForSubExprChecker(const llvm::SmallPtrSetImpl<const Decl * > & CollapsedLoopVarDecls)7723   explicit ForSubExprChecker(
7724       const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7725       : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
7726     // We want to visit implicit code, i.e. synthetic initialisation statements
7727     // created during range-for lowering.
7728     ShouldVisitImplicitCode = true;
7729   }
7730 
VisitDeclRefExpr(DeclRefExpr * E)7731   bool VisitDeclRefExpr(DeclRefExpr *E) override {
7732     ValueDecl *VD = E->getDecl();
7733     if (!isa<VarDecl, BindingDecl>(VD))
7734       return true;
7735     VarDecl *V = VD->getPotentiallyDecomposedVarDecl();
7736     if (V->getType()->isReferenceType()) {
7737       VarDecl *VD = V->getDefinition();
7738       if (VD->hasInit()) {
7739         Expr *I = VD->getInit();
7740         DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
7741         if (!DRE)
7742           return true;
7743         V = DRE->getDecl()->getPotentiallyDecomposedVarDecl();
7744       }
7745     }
7746     Decl *Canon = V->getCanonicalDecl();
7747     if (CollapsedLoopVarDecls.contains(Canon)) {
7748       ForbiddenVar = V;
7749       ErrLoc = E->getSourceRange();
7750       return false;
7751     }
7752 
7753     return true;
7754   }
7755 
getForbiddenVar() const7756   VarDecl *getForbiddenVar() const { return ForbiddenVar; }
getErrRange() const7757   SourceRange getErrRange() const { return ErrLoc; }
7758 };
7759 
7760 /// Helper class for checking canonical form of the OpenMP loops and
7761 /// extracting iteration space of each loop in the loop nest, that will be used
7762 /// for IR generation.
7763 class OpenMPIterationSpaceChecker {
7764   /// Reference to Sema.
7765   Sema &SemaRef;
7766   /// Does the loop associated directive support non-rectangular loops?
7767   bool SupportsNonRectangular;
7768   /// Data-sharing stack.
7769   DSAStackTy &Stack;
7770   /// A location for diagnostics (when there is no some better location).
7771   SourceLocation DefaultLoc;
7772   /// A location for diagnostics (when increment is not compatible).
7773   SourceLocation ConditionLoc;
7774   /// The set of variables declared within the (to be collapsed) loop nest.
7775   const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7776   /// A source location for referring to loop init later.
7777   SourceRange InitSrcRange;
7778   /// A source location for referring to condition later.
7779   SourceRange ConditionSrcRange;
7780   /// A source location for referring to increment later.
7781   SourceRange IncrementSrcRange;
7782   /// Loop variable.
7783   ValueDecl *LCDecl = nullptr;
7784   /// Reference to loop variable.
7785   Expr *LCRef = nullptr;
7786   /// Lower bound (initializer for the var).
7787   Expr *LB = nullptr;
7788   /// Upper bound.
7789   Expr *UB = nullptr;
7790   /// Loop step (increment).
7791   Expr *Step = nullptr;
7792   /// This flag is true when condition is one of:
7793   ///   Var <  UB
7794   ///   Var <= UB
7795   ///   UB  >  Var
7796   ///   UB  >= Var
7797   /// This will have no value when the condition is !=
7798   std::optional<bool> TestIsLessOp;
7799   /// This flag is true when condition is strict ( < or > ).
7800   bool TestIsStrictOp = false;
7801   /// This flag is true when step is subtracted on each iteration.
7802   bool SubtractStep = false;
7803   /// The outer loop counter this loop depends on (if any).
7804   const ValueDecl *DepDecl = nullptr;
7805   /// Contains number of loop (starts from 1) on which loop counter init
7806   /// expression of this loop depends on.
7807   std::optional<unsigned> InitDependOnLC;
7808   /// Contains number of loop (starts from 1) on which loop counter condition
7809   /// expression of this loop depends on.
7810   std::optional<unsigned> CondDependOnLC;
7811   /// Checks if the provide statement depends on the loop counter.
7812   std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
7813                                                   bool IsInitializer);
7814   /// Original condition required for checking of the exit condition for
7815   /// non-rectangular loop.
7816   Expr *Condition = nullptr;
7817 
7818 public:
OpenMPIterationSpaceChecker(Sema & SemaRef,bool SupportsNonRectangular,DSAStackTy & Stack,SourceLocation DefaultLoc,const llvm::SmallPtrSetImpl<const Decl * > & CollapsedLoopDecls)7819   OpenMPIterationSpaceChecker(
7820       Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack,
7821       SourceLocation DefaultLoc,
7822       const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
7823       : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7824         Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
7825         CollapsedLoopVarDecls(CollapsedLoopDecls) {}
7826   /// Check init-expr for canonical loop form and save loop counter
7827   /// variable - #Var and its initialization value - #LB.
7828   bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
7829   /// Check test-expr for canonical form, save upper-bound (#UB), flags
7830   /// for less/greater and for strict/non-strict comparison.
7831   bool checkAndSetCond(Expr *S);
7832   /// Check incr-expr for canonical loop form and return true if it
7833   /// does not conform, otherwise save loop step (#Step).
7834   bool checkAndSetInc(Expr *S);
7835   /// Return the loop counter variable.
getLoopDecl() const7836   ValueDecl *getLoopDecl() const { return LCDecl; }
7837   /// Return the reference expression to loop counter variable.
getLoopDeclRefExpr() const7838   Expr *getLoopDeclRefExpr() const { return LCRef; }
7839   /// Source range of the loop init.
getInitSrcRange() const7840   SourceRange getInitSrcRange() const { return InitSrcRange; }
7841   /// Source range of the loop condition.
getConditionSrcRange() const7842   SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
7843   /// Source range of the loop increment.
getIncrementSrcRange() const7844   SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
7845   /// True if the step should be subtracted.
shouldSubtractStep() const7846   bool shouldSubtractStep() const { return SubtractStep; }
7847   /// True, if the compare operator is strict (<, > or !=).
isStrictTestOp() const7848   bool isStrictTestOp() const { return TestIsStrictOp; }
7849   /// Build the expression to calculate the number of iterations.
7850   Expr *buildNumIterations(
7851       Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
7852       llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7853   /// Build the precondition expression for the loops.
7854   Expr *
7855   buildPreCond(Scope *S, Expr *Cond,
7856                llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7857   /// Build reference expression to the counter be used for codegen.
7858   DeclRefExpr *
7859   buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7860                   DSAStackTy &DSA) const;
7861   /// Build reference expression to the private counter be used for
7862   /// codegen.
7863   Expr *buildPrivateCounterVar() const;
7864   /// Build initialization of the counter be used for codegen.
7865   Expr *buildCounterInit() const;
7866   /// Build step of the counter be used for codegen.
7867   Expr *buildCounterStep() const;
7868   /// Build loop data with counter value for depend clauses in ordered
7869   /// directives.
7870   Expr *
7871   buildOrderedLoopData(Scope *S, Expr *Counter,
7872                        llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7873                        SourceLocation Loc, Expr *Inc = nullptr,
7874                        OverloadedOperatorKind OOK = OO_Amp);
7875   /// Builds the minimum value for the loop counter.
7876   std::pair<Expr *, Expr *> buildMinMaxValues(
7877       Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7878   /// Builds final condition for the non-rectangular loops.
7879   Expr *buildFinalCondition(Scope *S) const;
7880   /// Return true if any expression is dependent.
7881   bool dependent() const;
7882   /// Returns true if the initializer forms non-rectangular loop.
doesInitDependOnLC() const7883   bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
7884   /// Returns true if the condition forms non-rectangular loop.
doesCondDependOnLC() const7885   bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
7886   /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
getLoopDependentIdx() const7887   unsigned getLoopDependentIdx() const {
7888     return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
7889   }
7890 
7891 private:
7892   /// Check the right-hand side of an assignment in the increment
7893   /// expression.
7894   bool checkAndSetIncRHS(Expr *RHS);
7895   /// Helper to set loop counter variable and its initializer.
7896   bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
7897                       bool EmitDiags);
7898   /// Helper to set upper bound.
7899   bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
7900              SourceRange SR, SourceLocation SL);
7901   /// Helper to set loop increment.
7902   bool setStep(Expr *NewStep, bool Subtract);
7903 };
7904 
dependent() const7905 bool OpenMPIterationSpaceChecker::dependent() const {
7906   if (!LCDecl) {
7907     assert(!LB && !UB && !Step);
7908     return false;
7909   }
7910   return LCDecl->getType()->isDependentType() ||
7911          (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
7912          (Step && Step->isValueDependent());
7913 }
7914 
setLCDeclAndLB(ValueDecl * NewLCDecl,Expr * NewLCRefExpr,Expr * NewLB,bool EmitDiags)7915 bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
7916                                                  Expr *NewLCRefExpr,
7917                                                  Expr *NewLB, bool EmitDiags) {
7918   // State consistency checking to ensure correct usage.
7919   assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
7920          UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7921   if (!NewLCDecl || !NewLB || NewLB->containsErrors())
7922     return true;
7923   LCDecl = getCanonicalDecl(NewLCDecl);
7924   LCRef = NewLCRefExpr;
7925   if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
7926     if (const CXXConstructorDecl *Ctor = CE->getConstructor())
7927       if ((Ctor->isCopyOrMoveConstructor() ||
7928            Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
7929           CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
7930         NewLB = CE->getArg(0)->IgnoreParenImpCasts();
7931   LB = NewLB;
7932   if (EmitDiags)
7933     InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
7934   return false;
7935 }
7936 
setUB(Expr * NewUB,std::optional<bool> LessOp,bool StrictOp,SourceRange SR,SourceLocation SL)7937 bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
7938                                         bool StrictOp, SourceRange SR,
7939                                         SourceLocation SL) {
7940   // State consistency checking to ensure correct usage.
7941   assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
7942          Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7943   if (!NewUB || NewUB->containsErrors())
7944     return true;
7945   UB = NewUB;
7946   if (LessOp)
7947     TestIsLessOp = LessOp;
7948   TestIsStrictOp = StrictOp;
7949   ConditionSrcRange = SR;
7950   ConditionLoc = SL;
7951   CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
7952   return false;
7953 }
7954 
setStep(Expr * NewStep,bool Subtract)7955 bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
7956   // State consistency checking to ensure correct usage.
7957   assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
7958   if (!NewStep || NewStep->containsErrors())
7959     return true;
7960   if (!NewStep->isValueDependent()) {
7961     // Check that the step is integer expression.
7962     SourceLocation StepLoc = NewStep->getBeginLoc();
7963     ExprResult Val = SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(
7964         StepLoc, getExprAsWritten(NewStep));
7965     if (Val.isInvalid())
7966       return true;
7967     NewStep = Val.get();
7968 
7969     // OpenMP [2.6, Canonical Loop Form, Restrictions]
7970     //  If test-expr is of form var relational-op b and relational-op is < or
7971     //  <= then incr-expr must cause var to increase on each iteration of the
7972     //  loop. If test-expr is of form var relational-op b and relational-op is
7973     //  > or >= then incr-expr must cause var to decrease on each iteration of
7974     //  the loop.
7975     //  If test-expr is of form b relational-op var and relational-op is < or
7976     //  <= then incr-expr must cause var to decrease on each iteration of the
7977     //  loop. If test-expr is of form b relational-op var and relational-op is
7978     //  > or >= then incr-expr must cause var to increase on each iteration of
7979     //  the loop.
7980     std::optional<llvm::APSInt> Result =
7981         NewStep->getIntegerConstantExpr(SemaRef.Context);
7982     bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
7983     bool IsConstNeg =
7984         Result && Result->isSigned() && (Subtract != Result->isNegative());
7985     bool IsConstPos =
7986         Result && Result->isSigned() && (Subtract == Result->isNegative());
7987     bool IsConstZero = Result && !Result->getBoolValue();
7988 
7989     // != with increment is treated as <; != with decrement is treated as >
7990     if (!TestIsLessOp)
7991       TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
7992     if (UB && (IsConstZero ||
7993                (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
7994                               : (IsConstPos || (IsUnsigned && !Subtract))))) {
7995       SemaRef.Diag(NewStep->getExprLoc(),
7996                    diag::err_omp_loop_incr_not_compatible)
7997           << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
7998       SemaRef.Diag(ConditionLoc,
7999                    diag::note_omp_loop_cond_requires_compatible_incr)
8000           << *TestIsLessOp << ConditionSrcRange;
8001       return true;
8002     }
8003     if (*TestIsLessOp == Subtract) {
8004       NewStep =
8005           SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
8006               .get();
8007       Subtract = !Subtract;
8008     }
8009   }
8010 
8011   Step = NewStep;
8012   SubtractStep = Subtract;
8013   return false;
8014 }
8015 
8016 namespace {
8017 /// Checker for the non-rectangular loops. Checks if the initializer or
8018 /// condition expression references loop counter variable.
8019 class LoopCounterRefChecker final
8020     : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8021   Sema &SemaRef;
8022   DSAStackTy &Stack;
8023   const ValueDecl *CurLCDecl = nullptr;
8024   const ValueDecl *DepDecl = nullptr;
8025   const ValueDecl *PrevDepDecl = nullptr;
8026   bool IsInitializer = true;
8027   bool SupportsNonRectangular;
8028   unsigned BaseLoopId = 0;
checkDecl(const Expr * E,const ValueDecl * VD)8029   bool checkDecl(const Expr *E, const ValueDecl *VD) {
8030     if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
8031       SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8032           << (IsInitializer ? 0 : 1);
8033       return false;
8034     }
8035     const auto &&Data = Stack.isLoopControlVariable(VD);
8036     // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8037     // The type of the loop iterator on which we depend may not have a random
8038     // access iterator type.
8039     if (Data.first && VD->getType()->isRecordType()) {
8040       SmallString<128> Name;
8041       llvm::raw_svector_ostream OS(Name);
8042       VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8043                                /*Qualified=*/true);
8044       SemaRef.Diag(E->getExprLoc(),
8045                    diag::err_omp_wrong_dependency_iterator_type)
8046           << OS.str();
8047       SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8048       return false;
8049     }
8050     if (Data.first && !SupportsNonRectangular) {
8051       SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8052       return false;
8053     }
8054     if (Data.first &&
8055         (DepDecl || (PrevDepDecl &&
8056                      getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8057       if (!DepDecl && PrevDepDecl)
8058         DepDecl = PrevDepDecl;
8059       SmallString<128> Name;
8060       llvm::raw_svector_ostream OS(Name);
8061       DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8062                                     /*Qualified=*/true);
8063       SemaRef.Diag(E->getExprLoc(),
8064                    diag::err_omp_invariant_or_linear_dependency)
8065           << OS.str();
8066       return false;
8067     }
8068     if (Data.first) {
8069       DepDecl = VD;
8070       BaseLoopId = Data.first;
8071     }
8072     return Data.first;
8073   }
8074 
8075 public:
VisitDeclRefExpr(const DeclRefExpr * E)8076   bool VisitDeclRefExpr(const DeclRefExpr *E) {
8077     const ValueDecl *VD = E->getDecl();
8078     if (isa<VarDecl>(VD))
8079       return checkDecl(E, VD);
8080     return false;
8081   }
VisitMemberExpr(const MemberExpr * E)8082   bool VisitMemberExpr(const MemberExpr *E) {
8083     if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8084       const ValueDecl *VD = E->getMemberDecl();
8085       if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8086         return checkDecl(E, VD);
8087     }
8088     return false;
8089   }
VisitStmt(const Stmt * S)8090   bool VisitStmt(const Stmt *S) {
8091     bool Res = false;
8092     for (const Stmt *Child : S->children())
8093       Res = (Child && Visit(Child)) || Res;
8094     return Res;
8095   }
LoopCounterRefChecker(Sema & SemaRef,DSAStackTy & Stack,const ValueDecl * CurLCDecl,bool IsInitializer,const ValueDecl * PrevDepDecl=nullptr,bool SupportsNonRectangular=true)8096   explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8097                                  const ValueDecl *CurLCDecl, bool IsInitializer,
8098                                  const ValueDecl *PrevDepDecl = nullptr,
8099                                  bool SupportsNonRectangular = true)
8100       : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8101         PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8102         SupportsNonRectangular(SupportsNonRectangular) {}
getBaseLoopId() const8103   unsigned getBaseLoopId() const {
8104     assert(CurLCDecl && "Expected loop dependency.");
8105     return BaseLoopId;
8106   }
getDepDecl() const8107   const ValueDecl *getDepDecl() const {
8108     assert(CurLCDecl && "Expected loop dependency.");
8109     return DepDecl;
8110   }
8111 };
8112 } // namespace
8113 
8114 std::optional<unsigned>
doesDependOnLoopCounter(const Stmt * S,bool IsInitializer)8115 OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8116                                                      bool IsInitializer) {
8117   // Check for the non-rectangular loops.
8118   LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8119                                         DepDecl, SupportsNonRectangular);
8120   if (LoopStmtChecker.Visit(S)) {
8121     DepDecl = LoopStmtChecker.getDepDecl();
8122     return LoopStmtChecker.getBaseLoopId();
8123   }
8124   return std::nullopt;
8125 }
8126 
checkAndSetInit(Stmt * S,bool EmitDiags)8127 bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8128   // Check init-expr for canonical loop form and save loop counter
8129   // variable - #Var and its initialization value - #LB.
8130   // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8131   //   var = lb
8132   //   integer-type var = lb
8133   //   random-access-iterator-type var = lb
8134   //   pointer-type var = lb
8135   //
8136   if (!S) {
8137     if (EmitDiags) {
8138       SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8139     }
8140     return true;
8141   }
8142   if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8143     if (!ExprTemp->cleanupsHaveSideEffects())
8144       S = ExprTemp->getSubExpr();
8145 
8146   if (!CollapsedLoopVarDecls.empty()) {
8147     ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8148     if (!FSEC.TraverseStmt(S)) {
8149       SourceRange Range = FSEC.getErrRange();
8150       SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8151           << Range.getEnd() << 0 << FSEC.getForbiddenVar();
8152       return true;
8153     }
8154   }
8155 
8156   InitSrcRange = S->getSourceRange();
8157   if (Expr *E = dyn_cast<Expr>(S))
8158     S = E->IgnoreParens();
8159   if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8160     if (BO->getOpcode() == BO_Assign) {
8161       Expr *LHS = BO->getLHS()->IgnoreParens();
8162       if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8163         if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8164           if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8165             return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8166                                   EmitDiags);
8167         return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8168       }
8169       if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8170         if (ME->isArrow() &&
8171             isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8172           return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8173                                 EmitDiags);
8174       }
8175     }
8176   } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8177     if (DS->isSingleDecl()) {
8178       if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8179         if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8180           // Accept non-canonical init form here but emit ext. warning.
8181           if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8182             SemaRef.Diag(S->getBeginLoc(),
8183                          diag::ext_omp_loop_not_canonical_init)
8184                 << S->getSourceRange();
8185           return setLCDeclAndLB(
8186               Var,
8187               buildDeclRefExpr(SemaRef, Var,
8188                                Var->getType().getNonReferenceType(),
8189                                DS->getBeginLoc()),
8190               Var->getInit(), EmitDiags);
8191         }
8192       }
8193     }
8194   } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8195     if (CE->getOperator() == OO_Equal) {
8196       Expr *LHS = CE->getArg(0);
8197       if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8198         if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8199           if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8200             return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8201                                   EmitDiags);
8202         return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8203       }
8204       if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8205         if (ME->isArrow() &&
8206             isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8207           return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8208                                 EmitDiags);
8209       }
8210     }
8211   }
8212 
8213   if (dependent() || SemaRef.CurContext->isDependentContext())
8214     return false;
8215   if (EmitDiags) {
8216     SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8217         << S->getSourceRange();
8218   }
8219   return true;
8220 }
8221 
8222 /// Ignore parenthesizes, implicit casts, copy constructor and return the
8223 /// variable (which may be the loop variable) if possible.
getInitLCDecl(const Expr * E)8224 static const ValueDecl *getInitLCDecl(const Expr *E) {
8225   if (!E)
8226     return nullptr;
8227   E = getExprAsWritten(E);
8228   if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8229     if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8230       if ((Ctor->isCopyOrMoveConstructor() ||
8231            Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8232           CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8233         E = CE->getArg(0)->IgnoreParenImpCasts();
8234   if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8235     if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8236       return getCanonicalDecl(VD);
8237   }
8238   if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8239     if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8240       return getCanonicalDecl(ME->getMemberDecl());
8241   return nullptr;
8242 }
8243 
checkAndSetCond(Expr * S)8244 bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8245   // Check test-expr for canonical form, save upper-bound UB, flags for
8246   // less/greater and for strict/non-strict comparison.
8247   // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8248   //   var relational-op b
8249   //   b relational-op var
8250   //
8251   bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8252   if (!S) {
8253     SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8254         << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8255     return true;
8256   }
8257   Condition = S;
8258   S = getExprAsWritten(S);
8259 
8260   if (!CollapsedLoopVarDecls.empty()) {
8261     ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8262     if (!FSEC.TraverseStmt(S)) {
8263       SourceRange Range = FSEC.getErrRange();
8264       SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8265           << Range.getEnd() << 1 << FSEC.getForbiddenVar();
8266       return true;
8267     }
8268   }
8269 
8270   SourceLocation CondLoc = S->getBeginLoc();
8271   auto &&CheckAndSetCond =
8272       [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8273                                   const Expr *RHS, SourceRange SR,
8274                                   SourceLocation OpLoc) -> std::optional<bool> {
8275     if (BinaryOperator::isRelationalOp(Opcode)) {
8276       if (getInitLCDecl(LHS) == LCDecl)
8277         return setUB(const_cast<Expr *>(RHS),
8278                      (Opcode == BO_LT || Opcode == BO_LE),
8279                      (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8280       if (getInitLCDecl(RHS) == LCDecl)
8281         return setUB(const_cast<Expr *>(LHS),
8282                      (Opcode == BO_GT || Opcode == BO_GE),
8283                      (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8284     } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8285       return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8286                    /*LessOp=*/std::nullopt,
8287                    /*StrictOp=*/true, SR, OpLoc);
8288     }
8289     return std::nullopt;
8290   };
8291   std::optional<bool> Res;
8292   if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8293     CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8294     Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8295                           RBO->getOperatorLoc());
8296   } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8297     Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8298                           BO->getSourceRange(), BO->getOperatorLoc());
8299   } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8300     if (CE->getNumArgs() == 2) {
8301       Res = CheckAndSetCond(
8302           BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8303           CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8304     }
8305   }
8306   if (Res)
8307     return *Res;
8308   if (dependent() || SemaRef.CurContext->isDependentContext())
8309     return false;
8310   SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8311       << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8312   return true;
8313 }
8314 
checkAndSetIncRHS(Expr * RHS)8315 bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8316   // RHS of canonical loop form increment can be:
8317   //   var + incr
8318   //   incr + var
8319   //   var - incr
8320   //
8321   RHS = RHS->IgnoreParenImpCasts();
8322   if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8323     if (BO->isAdditiveOp()) {
8324       bool IsAdd = BO->getOpcode() == BO_Add;
8325       if (getInitLCDecl(BO->getLHS()) == LCDecl)
8326         return setStep(BO->getRHS(), !IsAdd);
8327       if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8328         return setStep(BO->getLHS(), /*Subtract=*/false);
8329     }
8330   } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8331     bool IsAdd = CE->getOperator() == OO_Plus;
8332     if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8333       if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8334         return setStep(CE->getArg(1), !IsAdd);
8335       if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8336         return setStep(CE->getArg(0), /*Subtract=*/false);
8337     }
8338   }
8339   if (dependent() || SemaRef.CurContext->isDependentContext())
8340     return false;
8341   SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8342       << RHS->getSourceRange() << LCDecl;
8343   return true;
8344 }
8345 
checkAndSetInc(Expr * S)8346 bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8347   // Check incr-expr for canonical loop form and return true if it
8348   // does not conform.
8349   // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8350   //   ++var
8351   //   var++
8352   //   --var
8353   //   var--
8354   //   var += incr
8355   //   var -= incr
8356   //   var = var + incr
8357   //   var = incr + var
8358   //   var = var - incr
8359   //
8360   if (!S) {
8361     SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8362     return true;
8363   }
8364   if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8365     if (!ExprTemp->cleanupsHaveSideEffects())
8366       S = ExprTemp->getSubExpr();
8367 
8368   if (!CollapsedLoopVarDecls.empty()) {
8369     ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8370     if (!FSEC.TraverseStmt(S)) {
8371       SourceRange Range = FSEC.getErrRange();
8372       SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8373           << Range.getEnd() << 2 << FSEC.getForbiddenVar();
8374       return true;
8375     }
8376   }
8377 
8378   IncrementSrcRange = S->getSourceRange();
8379   S = S->IgnoreParens();
8380   if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8381     if (UO->isIncrementDecrementOp() &&
8382         getInitLCDecl(UO->getSubExpr()) == LCDecl)
8383       return setStep(SemaRef
8384                          .ActOnIntegerConstant(UO->getBeginLoc(),
8385                                                (UO->isDecrementOp() ? -1 : 1))
8386                          .get(),
8387                      /*Subtract=*/false);
8388   } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8389     switch (BO->getOpcode()) {
8390     case BO_AddAssign:
8391     case BO_SubAssign:
8392       if (getInitLCDecl(BO->getLHS()) == LCDecl)
8393         return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8394       break;
8395     case BO_Assign:
8396       if (getInitLCDecl(BO->getLHS()) == LCDecl)
8397         return checkAndSetIncRHS(BO->getRHS());
8398       break;
8399     default:
8400       break;
8401     }
8402   } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8403     switch (CE->getOperator()) {
8404     case OO_PlusPlus:
8405     case OO_MinusMinus:
8406       if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8407         return setStep(SemaRef
8408                            .ActOnIntegerConstant(
8409                                CE->getBeginLoc(),
8410                                ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8411                            .get(),
8412                        /*Subtract=*/false);
8413       break;
8414     case OO_PlusEqual:
8415     case OO_MinusEqual:
8416       if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8417         return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8418       break;
8419     case OO_Equal:
8420       if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8421         return checkAndSetIncRHS(CE->getArg(1));
8422       break;
8423     default:
8424       break;
8425     }
8426   }
8427   if (dependent() || SemaRef.CurContext->isDependentContext())
8428     return false;
8429   SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8430       << S->getSourceRange() << LCDecl;
8431   return true;
8432 }
8433 
8434 static ExprResult
tryBuildCapture(Sema & SemaRef,Expr * Capture,llvm::MapVector<const Expr *,DeclRefExpr * > & Captures,StringRef Name=".capture_expr.")8435 tryBuildCapture(Sema &SemaRef, Expr *Capture,
8436                 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8437                 StringRef Name = ".capture_expr.") {
8438   if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8439     return Capture;
8440   if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8441     return SemaRef.PerformImplicitConversion(Capture->IgnoreImpCasts(),
8442                                              Capture->getType(),
8443                                              AssignmentAction::Converting,
8444                                              /*AllowExplicit=*/true);
8445   auto I = Captures.find(Capture);
8446   if (I != Captures.end())
8447     return buildCapture(SemaRef, Capture, I->second, Name);
8448   DeclRefExpr *Ref = nullptr;
8449   ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8450   Captures[Capture] = Ref;
8451   return Res;
8452 }
8453 
8454 /// Calculate number of iterations, transforming to unsigned, if number of
8455 /// iterations may be larger than the original type.
8456 static Expr *
calculateNumIters(Sema & SemaRef,Scope * S,SourceLocation DefaultLoc,Expr * Lower,Expr * Upper,Expr * Step,QualType LCTy,bool TestIsStrictOp,bool RoundToStep,llvm::MapVector<const Expr *,DeclRefExpr * > & Captures)8457 calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8458                   Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8459                   bool TestIsStrictOp, bool RoundToStep,
8460                   llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8461   ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8462   if (!NewStep.isUsable())
8463     return nullptr;
8464   llvm::APSInt LRes, SRes;
8465   bool IsLowerConst = false, IsStepConst = false;
8466   if (std::optional<llvm::APSInt> Res =
8467           Lower->getIntegerConstantExpr(SemaRef.Context)) {
8468     LRes = *Res;
8469     IsLowerConst = true;
8470   }
8471   if (std::optional<llvm::APSInt> Res =
8472           Step->getIntegerConstantExpr(SemaRef.Context)) {
8473     SRes = *Res;
8474     IsStepConst = true;
8475   }
8476   bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8477                          ((!TestIsStrictOp && LRes.isNonNegative()) ||
8478                           (TestIsStrictOp && LRes.isStrictlyPositive()));
8479   bool NeedToReorganize = false;
8480   // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8481   if (!NoNeedToConvert && IsLowerConst &&
8482       (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8483     NoNeedToConvert = true;
8484     if (RoundToStep) {
8485       unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8486                         ? LRes.getBitWidth()
8487                         : SRes.getBitWidth();
8488       LRes = LRes.extend(BW + 1);
8489       LRes.setIsSigned(true);
8490       SRes = SRes.extend(BW + 1);
8491       SRes.setIsSigned(true);
8492       LRes -= SRes;
8493       NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8494       LRes = LRes.trunc(BW);
8495     }
8496     if (TestIsStrictOp) {
8497       unsigned BW = LRes.getBitWidth();
8498       LRes = LRes.extend(BW + 1);
8499       LRes.setIsSigned(true);
8500       ++LRes;
8501       NoNeedToConvert =
8502           NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8503       // truncate to the original bitwidth.
8504       LRes = LRes.trunc(BW);
8505     }
8506     NeedToReorganize = NoNeedToConvert;
8507   }
8508   llvm::APSInt URes;
8509   bool IsUpperConst = false;
8510   if (std::optional<llvm::APSInt> Res =
8511           Upper->getIntegerConstantExpr(SemaRef.Context)) {
8512     URes = *Res;
8513     IsUpperConst = true;
8514   }
8515   if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8516       (!RoundToStep || IsStepConst)) {
8517     unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8518                                                           : URes.getBitWidth();
8519     LRes = LRes.extend(BW + 1);
8520     LRes.setIsSigned(true);
8521     URes = URes.extend(BW + 1);
8522     URes.setIsSigned(true);
8523     URes -= LRes;
8524     NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8525     NeedToReorganize = NoNeedToConvert;
8526   }
8527   // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8528   // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8529   // unsigned.
8530   if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8531       !LCTy->isDependentType() && LCTy->isIntegerType()) {
8532     QualType LowerTy = Lower->getType();
8533     QualType UpperTy = Upper->getType();
8534     uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8535     uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8536     if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8537         (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8538       QualType CastType = SemaRef.Context.getIntTypeForBitwidth(
8539           LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8540       Upper =
8541           SemaRef
8542               .PerformImplicitConversion(
8543                   SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8544                   CastType, AssignmentAction::Converting)
8545               .get();
8546       Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8547       NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8548     }
8549   }
8550   if (!Lower || !Upper || NewStep.isInvalid())
8551     return nullptr;
8552 
8553   ExprResult Diff;
8554   // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8555   // 1]).
8556   if (NeedToReorganize) {
8557     Diff = Lower;
8558 
8559     if (RoundToStep) {
8560       // Lower - Step
8561       Diff =
8562           SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8563       if (!Diff.isUsable())
8564         return nullptr;
8565     }
8566 
8567     // Lower - Step [+ 1]
8568     if (TestIsStrictOp)
8569       Diff = SemaRef.BuildBinOp(
8570           S, DefaultLoc, BO_Add, Diff.get(),
8571           SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8572     if (!Diff.isUsable())
8573       return nullptr;
8574 
8575     Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8576     if (!Diff.isUsable())
8577       return nullptr;
8578 
8579     // Upper - (Lower - Step [+ 1]).
8580     Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8581     if (!Diff.isUsable())
8582       return nullptr;
8583   } else {
8584     Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8585 
8586     if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8587       // BuildBinOp already emitted error, this one is to point user to upper
8588       // and lower bound, and to tell what is passed to 'operator-'.
8589       SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8590           << Upper->getSourceRange() << Lower->getSourceRange();
8591       return nullptr;
8592     }
8593 
8594     if (!Diff.isUsable())
8595       return nullptr;
8596 
8597     // Upper - Lower [- 1]
8598     if (TestIsStrictOp)
8599       Diff = SemaRef.BuildBinOp(
8600           S, DefaultLoc, BO_Sub, Diff.get(),
8601           SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8602     if (!Diff.isUsable())
8603       return nullptr;
8604 
8605     if (RoundToStep) {
8606       // Upper - Lower [- 1] + Step
8607       Diff =
8608           SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8609       if (!Diff.isUsable())
8610         return nullptr;
8611     }
8612   }
8613 
8614   // Parentheses (for dumping/debugging purposes only).
8615   Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8616   if (!Diff.isUsable())
8617     return nullptr;
8618 
8619   // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8620   Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8621   if (!Diff.isUsable())
8622     return nullptr;
8623 
8624   return Diff.get();
8625 }
8626 
8627 /// Build the expression to calculate the number of iterations.
buildNumIterations(Scope * S,ArrayRef<LoopIterationSpace> ResultIterSpaces,bool LimitedType,llvm::MapVector<const Expr *,DeclRefExpr * > & Captures) const8628 Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8629     Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8630     llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8631   QualType VarType = LCDecl->getType().getNonReferenceType();
8632   if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8633       !SemaRef.getLangOpts().CPlusPlus)
8634     return nullptr;
8635   Expr *LBVal = LB;
8636   Expr *UBVal = UB;
8637   // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8638   // max(LB(MinVal), LB(MaxVal)))
8639   if (InitDependOnLC) {
8640     const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8641     if (!IS.MinValue || !IS.MaxValue)
8642       return nullptr;
8643     // OuterVar = Min
8644     ExprResult MinValue =
8645         SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8646     if (!MinValue.isUsable())
8647       return nullptr;
8648 
8649     ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8650                                              IS.CounterVar, MinValue.get());
8651     if (!LBMinVal.isUsable())
8652       return nullptr;
8653     // OuterVar = Min, LBVal
8654     LBMinVal =
8655         SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8656     if (!LBMinVal.isUsable())
8657       return nullptr;
8658     // (OuterVar = Min, LBVal)
8659     LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8660     if (!LBMinVal.isUsable())
8661       return nullptr;
8662 
8663     // OuterVar = Max
8664     ExprResult MaxValue =
8665         SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8666     if (!MaxValue.isUsable())
8667       return nullptr;
8668 
8669     ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8670                                              IS.CounterVar, MaxValue.get());
8671     if (!LBMaxVal.isUsable())
8672       return nullptr;
8673     // OuterVar = Max, LBVal
8674     LBMaxVal =
8675         SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8676     if (!LBMaxVal.isUsable())
8677       return nullptr;
8678     // (OuterVar = Max, LBVal)
8679     LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8680     if (!LBMaxVal.isUsable())
8681       return nullptr;
8682 
8683     Expr *LBMin =
8684         tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
8685     Expr *LBMax =
8686         tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
8687     if (!LBMin || !LBMax)
8688       return nullptr;
8689     // LB(MinVal) < LB(MaxVal)
8690     ExprResult MinLessMaxRes =
8691         SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8692     if (!MinLessMaxRes.isUsable())
8693       return nullptr;
8694     Expr *MinLessMax =
8695         tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
8696             .get();
8697     if (!MinLessMax)
8698       return nullptr;
8699     if (*TestIsLessOp) {
8700       // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8701       // LB(MaxVal))
8702       ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8703                                                     MinLessMax, LBMin, LBMax);
8704       if (!MinLB.isUsable())
8705         return nullptr;
8706       LBVal = MinLB.get();
8707     } else {
8708       // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8709       // LB(MaxVal))
8710       ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8711                                                     MinLessMax, LBMax, LBMin);
8712       if (!MaxLB.isUsable())
8713         return nullptr;
8714       LBVal = MaxLB.get();
8715     }
8716     // OuterVar = LB
8717     LBMinVal =
8718         SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8719     if (!LBMinVal.isUsable())
8720       return nullptr;
8721     LBVal = LBMinVal.get();
8722   }
8723   // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8724   // min(UB(MinVal), UB(MaxVal))
8725   if (CondDependOnLC) {
8726     const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8727     if (!IS.MinValue || !IS.MaxValue)
8728       return nullptr;
8729     // OuterVar = Min
8730     ExprResult MinValue =
8731         SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8732     if (!MinValue.isUsable())
8733       return nullptr;
8734 
8735     ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8736                                              IS.CounterVar, MinValue.get());
8737     if (!UBMinVal.isUsable())
8738       return nullptr;
8739     // OuterVar = Min, UBVal
8740     UBMinVal =
8741         SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
8742     if (!UBMinVal.isUsable())
8743       return nullptr;
8744     // (OuterVar = Min, UBVal)
8745     UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
8746     if (!UBMinVal.isUsable())
8747       return nullptr;
8748 
8749     // OuterVar = Max
8750     ExprResult MaxValue =
8751         SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8752     if (!MaxValue.isUsable())
8753       return nullptr;
8754 
8755     ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8756                                              IS.CounterVar, MaxValue.get());
8757     if (!UBMaxVal.isUsable())
8758       return nullptr;
8759     // OuterVar = Max, UBVal
8760     UBMaxVal =
8761         SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
8762     if (!UBMaxVal.isUsable())
8763       return nullptr;
8764     // (OuterVar = Max, UBVal)
8765     UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
8766     if (!UBMaxVal.isUsable())
8767       return nullptr;
8768 
8769     Expr *UBMin =
8770         tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
8771     Expr *UBMax =
8772         tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
8773     if (!UBMin || !UBMax)
8774       return nullptr;
8775     // UB(MinVal) > UB(MaxVal)
8776     ExprResult MinGreaterMaxRes =
8777         SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8778     if (!MinGreaterMaxRes.isUsable())
8779       return nullptr;
8780     Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
8781                                           Captures, ".min_greater_max")
8782                               .get();
8783     if (!MinGreaterMax)
8784       return nullptr;
8785     if (*TestIsLessOp) {
8786       // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8787       // UB(MaxVal))
8788       ExprResult MaxUB = SemaRef.ActOnConditionalOp(
8789           DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8790       if (!MaxUB.isUsable())
8791         return nullptr;
8792       UBVal = MaxUB.get();
8793     } else {
8794       // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
8795       // UB(MaxVal))
8796       ExprResult MinUB = SemaRef.ActOnConditionalOp(
8797           DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
8798       if (!MinUB.isUsable())
8799         return nullptr;
8800       UBVal = MinUB.get();
8801     }
8802   }
8803   Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
8804   Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
8805   Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
8806   Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
8807   if (!Upper || !Lower)
8808     return nullptr;
8809 
8810   ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8811                                       Step, VarType, TestIsStrictOp,
8812                                       /*RoundToStep=*/true, Captures);
8813   if (!Diff.isUsable())
8814     return nullptr;
8815 
8816   // OpenMP runtime requires 32-bit or 64-bit loop variables.
8817   QualType Type = Diff.get()->getType();
8818   ASTContext &C = SemaRef.Context;
8819   bool UseVarType = VarType->hasIntegerRepresentation() &&
8820                     C.getTypeSize(Type) > C.getTypeSize(VarType);
8821   if (!Type->isIntegerType() || UseVarType) {
8822     unsigned NewSize =
8823         UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
8824     bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
8825                                : Type->hasSignedIntegerRepresentation();
8826     Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
8827     if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
8828       Diff = SemaRef.PerformImplicitConversion(Diff.get(), Type,
8829                                                AssignmentAction::Converting,
8830                                                /*AllowExplicit=*/true);
8831       if (!Diff.isUsable())
8832         return nullptr;
8833     }
8834   }
8835   if (LimitedType) {
8836     unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
8837     if (NewSize != C.getTypeSize(Type)) {
8838       if (NewSize < C.getTypeSize(Type)) {
8839         assert(NewSize == 64 && "incorrect loop var size");
8840         SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8841             << InitSrcRange << ConditionSrcRange;
8842       }
8843       QualType NewType = C.getIntTypeForBitwidth(
8844           NewSize, Type->hasSignedIntegerRepresentation() ||
8845                        C.getTypeSize(Type) < NewSize);
8846       if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
8847         Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
8848                                                  AssignmentAction::Converting,
8849                                                  /*AllowExplicit=*/true);
8850         if (!Diff.isUsable())
8851           return nullptr;
8852       }
8853     }
8854   }
8855 
8856   return Diff.get();
8857 }
8858 
buildMinMaxValues(Scope * S,llvm::MapVector<const Expr *,DeclRefExpr * > & Captures) const8859 std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
8860     Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8861   // Do not build for iterators, they cannot be used in non-rectangular loop
8862   // nests.
8863   if (LCDecl->getType()->isRecordType())
8864     return std::make_pair(nullptr, nullptr);
8865   // If we subtract, the min is in the condition, otherwise the min is in the
8866   // init value.
8867   Expr *MinExpr = nullptr;
8868   Expr *MaxExpr = nullptr;
8869   Expr *LBExpr = *TestIsLessOp ? LB : UB;
8870   Expr *UBExpr = *TestIsLessOp ? UB : LB;
8871   bool LBNonRect =
8872       *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
8873   bool UBNonRect =
8874       *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
8875   Expr *Lower =
8876       LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
8877   Expr *Upper =
8878       UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
8879   if (!Upper || !Lower)
8880     return std::make_pair(nullptr, nullptr);
8881 
8882   if (*TestIsLessOp)
8883     MinExpr = Lower;
8884   else
8885     MaxExpr = Upper;
8886 
8887   // Build minimum/maximum value based on number of iterations.
8888   QualType VarType = LCDecl->getType().getNonReferenceType();
8889 
8890   ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8891                                       Step, VarType, TestIsStrictOp,
8892                                       /*RoundToStep=*/false, Captures);
8893   if (!Diff.isUsable())
8894     return std::make_pair(nullptr, nullptr);
8895 
8896   // ((Upper - Lower [- 1]) / Step) * Step
8897   // Parentheses (for dumping/debugging purposes only).
8898   Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8899   if (!Diff.isUsable())
8900     return std::make_pair(nullptr, nullptr);
8901 
8902   ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8903   if (!NewStep.isUsable())
8904     return std::make_pair(nullptr, nullptr);
8905   Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
8906   if (!Diff.isUsable())
8907     return std::make_pair(nullptr, nullptr);
8908 
8909   // Parentheses (for dumping/debugging purposes only).
8910   Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8911   if (!Diff.isUsable())
8912     return std::make_pair(nullptr, nullptr);
8913 
8914   // Convert to the ptrdiff_t, if original type is pointer.
8915   if (VarType->isAnyPointerType() &&
8916       !SemaRef.Context.hasSameType(
8917           Diff.get()->getType(),
8918           SemaRef.Context.getUnsignedPointerDiffType())) {
8919     Diff = SemaRef.PerformImplicitConversion(
8920         Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
8921         AssignmentAction::Converting, /*AllowExplicit=*/true);
8922   }
8923   if (!Diff.isUsable())
8924     return std::make_pair(nullptr, nullptr);
8925 
8926   if (*TestIsLessOp) {
8927     // MinExpr = Lower;
8928     // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
8929     Diff = SemaRef.BuildBinOp(
8930         S, DefaultLoc, BO_Add,
8931         SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
8932         Diff.get());
8933     if (!Diff.isUsable())
8934       return std::make_pair(nullptr, nullptr);
8935   } else {
8936     // MaxExpr = Upper;
8937     // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
8938     Diff = SemaRef.BuildBinOp(
8939         S, DefaultLoc, BO_Sub,
8940         SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8941         Diff.get());
8942     if (!Diff.isUsable())
8943       return std::make_pair(nullptr, nullptr);
8944   }
8945 
8946   // Convert to the original type.
8947   if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
8948     Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
8949                                              AssignmentAction::Converting,
8950                                              /*AllowExplicit=*/true);
8951   if (!Diff.isUsable())
8952     return std::make_pair(nullptr, nullptr);
8953 
8954   Sema::TentativeAnalysisScope Trap(SemaRef);
8955   Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
8956   if (!Diff.isUsable())
8957     return std::make_pair(nullptr, nullptr);
8958 
8959   if (*TestIsLessOp)
8960     MaxExpr = Diff.get();
8961   else
8962     MinExpr = Diff.get();
8963 
8964   return std::make_pair(MinExpr, MaxExpr);
8965 }
8966 
buildFinalCondition(Scope * S) const8967 Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
8968   if (InitDependOnLC || CondDependOnLC)
8969     return Condition;
8970   return nullptr;
8971 }
8972 
buildPreCond(Scope * S,Expr * Cond,llvm::MapVector<const Expr *,DeclRefExpr * > & Captures) const8973 Expr *OpenMPIterationSpaceChecker::buildPreCond(
8974     Scope *S, Expr *Cond,
8975     llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8976   // Do not build a precondition when the condition/initialization is dependent
8977   // to prevent pessimistic early loop exit.
8978   // TODO: this can be improved by calculating min/max values but not sure that
8979   // it will be very effective.
8980   if (CondDependOnLC || InitDependOnLC)
8981     return SemaRef
8982         .PerformImplicitConversion(
8983             SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
8984             SemaRef.Context.BoolTy, /*Action=*/AssignmentAction::Casting,
8985             /*AllowExplicit=*/true)
8986         .get();
8987 
8988   // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
8989   Sema::TentativeAnalysisScope Trap(SemaRef);
8990 
8991   ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
8992   ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
8993   if (!NewLB.isUsable() || !NewUB.isUsable())
8994     return nullptr;
8995 
8996   ExprResult CondExpr =
8997       SemaRef.BuildBinOp(S, DefaultLoc,
8998                          *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
8999                                        : (TestIsStrictOp ? BO_GT : BO_GE),
9000                          NewLB.get(), NewUB.get());
9001   if (CondExpr.isUsable()) {
9002     if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
9003                                                 SemaRef.Context.BoolTy))
9004       CondExpr = SemaRef.PerformImplicitConversion(
9005           CondExpr.get(), SemaRef.Context.BoolTy,
9006           /*Action=*/AssignmentAction::Casting,
9007           /*AllowExplicit=*/true);
9008   }
9009 
9010   // Otherwise use original loop condition and evaluate it in runtime.
9011   return CondExpr.isUsable() ? CondExpr.get() : Cond;
9012 }
9013 
9014 /// Build reference expression to the counter be used for codegen.
buildCounterVar(llvm::MapVector<const Expr *,DeclRefExpr * > & Captures,DSAStackTy & DSA) const9015 DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9016     llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9017     DSAStackTy &DSA) const {
9018   auto *VD = dyn_cast<VarDecl>(LCDecl);
9019   if (!VD) {
9020     VD = SemaRef.OpenMP().isOpenMPCapturedDecl(LCDecl);
9021     DeclRefExpr *Ref = buildDeclRefExpr(
9022         SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
9023     const DSAStackTy::DSAVarData Data =
9024         DSA.getTopDSA(LCDecl, /*FromParent=*/false);
9025     // If the loop control decl is explicitly marked as private, do not mark it
9026     // as captured again.
9027     if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
9028       Captures.insert(std::make_pair(LCRef, Ref));
9029     return Ref;
9030   }
9031   return cast<DeclRefExpr>(LCRef);
9032 }
9033 
buildPrivateCounterVar() const9034 Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9035   if (LCDecl && !LCDecl->isInvalidDecl()) {
9036     QualType Type = LCDecl->getType().getNonReferenceType();
9037     VarDecl *PrivateVar = buildVarDecl(
9038         SemaRef, DefaultLoc, Type, LCDecl->getName(),
9039         LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9040         isa<VarDecl>(LCDecl)
9041             ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
9042             : nullptr);
9043     if (PrivateVar->isInvalidDecl())
9044       return nullptr;
9045     return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
9046   }
9047   return nullptr;
9048 }
9049 
9050 /// Build initialization of the counter to be used for codegen.
buildCounterInit() const9051 Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9052 
9053 /// Build step of the counter be used for codegen.
buildCounterStep() const9054 Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9055 
buildOrderedLoopData(Scope * S,Expr * Counter,llvm::MapVector<const Expr *,DeclRefExpr * > & Captures,SourceLocation Loc,Expr * Inc,OverloadedOperatorKind OOK)9056 Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9057     Scope *S, Expr *Counter,
9058     llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9059     Expr *Inc, OverloadedOperatorKind OOK) {
9060   Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
9061   if (!Cnt)
9062     return nullptr;
9063   if (Inc) {
9064     assert((OOK == OO_Plus || OOK == OO_Minus) &&
9065            "Expected only + or - operations for depend clauses.");
9066     BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9067     Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
9068     if (!Cnt)
9069       return nullptr;
9070   }
9071   QualType VarType = LCDecl->getType().getNonReferenceType();
9072   if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9073       !SemaRef.getLangOpts().CPlusPlus)
9074     return nullptr;
9075   // Upper - Lower
9076   Expr *Upper =
9077       *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9078   Expr *Lower =
9079       *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9080   if (!Upper || !Lower)
9081     return nullptr;
9082 
9083   ExprResult Diff = calculateNumIters(
9084       SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9085       /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9086   if (!Diff.isUsable())
9087     return nullptr;
9088 
9089   return Diff.get();
9090 }
9091 } // namespace
9092 
ActOnOpenMPLoopInitialization(SourceLocation ForLoc,Stmt * Init)9093 void SemaOpenMP::ActOnOpenMPLoopInitialization(SourceLocation ForLoc,
9094                                                Stmt *Init) {
9095   assert(getLangOpts().OpenMP && "OpenMP is not active.");
9096   assert(Init && "Expected loop in canonical form.");
9097   unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9098   OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9099   if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
9100     return;
9101 
9102   DSAStack->loopStart();
9103   llvm::SmallPtrSet<const Decl *, 1> EmptyDeclSet;
9104   OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9105                                   *DSAStack, ForLoc, EmptyDeclSet);
9106   if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9107     if (ValueDecl *D = ISC.getLoopDecl()) {
9108       auto *VD = dyn_cast<VarDecl>(D);
9109       DeclRefExpr *PrivateRef = nullptr;
9110       if (!VD) {
9111         if (VarDecl *Private = isOpenMPCapturedDecl(D)) {
9112           VD = Private;
9113         } else {
9114           PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(),
9115                                     /*WithInit=*/false);
9116           VD = cast<VarDecl>(PrivateRef->getDecl());
9117         }
9118       }
9119       DSAStack->addLoopControlVariable(D, VD);
9120       const Decl *LD = DSAStack->getPossiblyLoopCounter();
9121       if (LD != D->getCanonicalDecl()) {
9122         DSAStack->resetPossibleLoopCounter();
9123         if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9124           SemaRef.MarkDeclarationsReferencedInExpr(buildDeclRefExpr(
9125               SemaRef, const_cast<VarDecl *>(Var),
9126               Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
9127               /*RefersToCapture=*/true));
9128       }
9129       // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9130       // Referenced in a Construct, C/C++]. The loop iteration variable in the
9131       // associated for-loop of a simd construct with just one associated
9132       // for-loop may be listed in a linear clause with a constant-linear-step
9133       // that is the increment of the associated for-loop. The loop iteration
9134       // variable(s) in the associated for-loop(s) of a for or parallel for
9135       // construct may be listed in a private or lastprivate clause.
9136       DSAStackTy::DSAVarData DVar =
9137           DSAStack->getTopDSA(D, /*FromParent=*/false);
9138       // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9139       // is declared in the loop and it is predetermined as a private.
9140       Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9141       OpenMPClauseKind PredeterminedCKind =
9142           isOpenMPSimdDirective(DKind)
9143               ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9144               : OMPC_private;
9145       auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
9146         return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9147       };
9148       if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9149             DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9150             (getLangOpts().OpenMP <= 45 ||
9151              (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9152            ((isOpenMPWorksharingDirective(DKind) ||
9153              IsOpenMPTaskloopDirective(DKind) ||
9154              isOpenMPDistributeDirective(DKind)) &&
9155             !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9156             DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9157           (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9158         unsigned OMPVersion = getLangOpts().OpenMP;
9159         Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9160             << getOpenMPClauseNameForDiag(DVar.CKind)
9161             << getOpenMPDirectiveName(DKind, OMPVersion)
9162             << getOpenMPClauseNameForDiag(PredeterminedCKind);
9163         if (DVar.RefExpr == nullptr)
9164           DVar.CKind = PredeterminedCKind;
9165         reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
9166       } else if (LoopDeclRefExpr) {
9167         // Make the loop iteration variable private (for worksharing
9168         // constructs), linear (for simd directives with the only one
9169         // associated loop) or lastprivate (for simd directives with several
9170         // collapsed or ordered loops).
9171         if (DVar.CKind == OMPC_unknown)
9172           DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9173       }
9174     }
9175   }
9176   DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9177 }
9178 
9179 namespace {
9180 // Utility for OpenMP doacross clause kind
9181 class OMPDoacrossKind {
9182 public:
isSource(const OMPDoacrossClause * C)9183   bool isSource(const OMPDoacrossClause *C) {
9184     return C->getDependenceType() == OMPC_DOACROSS_source ||
9185            C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9186   }
isSink(const OMPDoacrossClause * C)9187   bool isSink(const OMPDoacrossClause *C) {
9188     return C->getDependenceType() == OMPC_DOACROSS_sink;
9189   }
isSinkIter(const OMPDoacrossClause * C)9190   bool isSinkIter(const OMPDoacrossClause *C) {
9191     return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9192   }
9193 };
9194 } // namespace
9195 /// Called on a for stmt to check and extract its iteration space
9196 /// for further processing (such as collapsing).
checkOpenMPIterationSpace(OpenMPDirectiveKind DKind,Stmt * S,Sema & SemaRef,DSAStackTy & DSA,unsigned CurrentNestedLoopCount,unsigned NestedLoopCount,unsigned TotalNestedLoopCount,Expr * CollapseLoopCountExpr,Expr * OrderedLoopCountExpr,SemaOpenMP::VarsWithInheritedDSAType & VarsWithImplicitDSA,llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces,llvm::MapVector<const Expr *,DeclRefExpr * > & Captures,const llvm::SmallPtrSetImpl<const Decl * > & CollapsedLoopVarDecls)9197 static bool checkOpenMPIterationSpace(
9198     OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9199     unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9200     unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9201     Expr *OrderedLoopCountExpr,
9202     SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9203     llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces,
9204     llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9205     const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9206   bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9207   // OpenMP [2.9.1, Canonical Loop Form]
9208   //   for (init-expr; test-expr; incr-expr) structured-block
9209   //   for (range-decl: range-expr) structured-block
9210   if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9211     S = CanonLoop->getLoopStmt();
9212   auto *For = dyn_cast_or_null<ForStmt>(S);
9213   auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9214   // Ranged for is supported only in OpenMP 5.0.
9215   if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9216     unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
9217     SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9218         << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9219         << getOpenMPDirectiveName(DKind, OMPVersion) << TotalNestedLoopCount
9220         << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9221     if (TotalNestedLoopCount > 1) {
9222       if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9223         SemaRef.Diag(DSA.getConstructLoc(),
9224                      diag::note_omp_collapse_ordered_expr)
9225             << 2 << CollapseLoopCountExpr->getSourceRange()
9226             << OrderedLoopCountExpr->getSourceRange();
9227       else if (CollapseLoopCountExpr)
9228         SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9229                      diag::note_omp_collapse_ordered_expr)
9230             << 0 << CollapseLoopCountExpr->getSourceRange();
9231       else if (OrderedLoopCountExpr)
9232         SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9233                      diag::note_omp_collapse_ordered_expr)
9234             << 1 << OrderedLoopCountExpr->getSourceRange();
9235     }
9236     return true;
9237   }
9238   assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9239          "No loop body.");
9240   // Postpone analysis in dependent contexts for ranged for loops.
9241   if (CXXFor && SemaRef.CurContext->isDependentContext())
9242     return false;
9243 
9244   OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9245                                   For ? For->getForLoc() : CXXFor->getForLoc(),
9246                                   CollapsedLoopVarDecls);
9247 
9248   // Check init.
9249   Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9250   if (ISC.checkAndSetInit(Init))
9251     return true;
9252 
9253   bool HasErrors = false;
9254 
9255   // Check loop variable's type.
9256   if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9257     // OpenMP [2.6, Canonical Loop Form]
9258     // Var is one of the following:
9259     //   A variable of signed or unsigned integer type.
9260     //   For C++, a variable of a random access iterator type.
9261     //   For C, a variable of a pointer type.
9262     QualType VarType = LCDecl->getType().getNonReferenceType();
9263     if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9264         !VarType->isPointerType() &&
9265         !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9266       SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9267           << SemaRef.getLangOpts().CPlusPlus;
9268       HasErrors = true;
9269     }
9270 
9271     // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9272     // a Construct
9273     // The loop iteration variable(s) in the associated for-loop(s) of a for or
9274     // parallel for construct is (are) private.
9275     // The loop iteration variable in the associated for-loop of a simd
9276     // construct with just one associated for-loop is linear with a
9277     // constant-linear-step that is the increment of the associated for-loop.
9278     // Exclude loop var from the list of variables with implicitly defined data
9279     // sharing attributes.
9280     VarsWithImplicitDSA.erase(LCDecl);
9281 
9282     assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
9283 
9284     // Check test-expr.
9285     HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9286 
9287     // Check incr-expr.
9288     HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9289   }
9290 
9291   if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9292     return HasErrors;
9293 
9294   // Build the loop's iteration space representation.
9295   ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9296       DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9297   ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9298       ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9299                              (isOpenMPWorksharingDirective(DKind) ||
9300                               isOpenMPGenericLoopDirective(DKind) ||
9301                               isOpenMPTaskLoopDirective(DKind) ||
9302                               isOpenMPDistributeDirective(DKind) ||
9303                               isOpenMPLoopTransformationDirective(DKind)),
9304                              Captures);
9305   ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9306       ISC.buildCounterVar(Captures, DSA);
9307   ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9308       ISC.buildPrivateCounterVar();
9309   ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9310   ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9311   ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9312   ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9313       ISC.getConditionSrcRange();
9314   ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9315       ISC.getIncrementSrcRange();
9316   ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9317   ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9318       ISC.isStrictTestOp();
9319   std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9320            ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9321       ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9322   ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9323       ISC.buildFinalCondition(DSA.getCurScope());
9324   ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9325       ISC.doesInitDependOnLC();
9326   ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9327       ISC.doesCondDependOnLC();
9328   ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9329       ISC.getLoopDependentIdx();
9330 
9331   HasErrors |=
9332       (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9333        ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9334        ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9335        ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9336        ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9337        ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9338   if (!HasErrors && DSA.isOrderedRegion()) {
9339     if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9340       if (CurrentNestedLoopCount <
9341           DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9342         DSA.getOrderedRegionParam().second->setLoopNumIterations(
9343             CurrentNestedLoopCount,
9344             ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9345         DSA.getOrderedRegionParam().second->setLoopCounter(
9346             CurrentNestedLoopCount,
9347             ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9348       }
9349     }
9350     for (auto &Pair : DSA.getDoacrossDependClauses()) {
9351       auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9352       auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9353       unsigned NumLoops =
9354           DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9355       if (CurrentNestedLoopCount >= NumLoops) {
9356         // Erroneous case - clause has some problems.
9357         continue;
9358       }
9359       if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9360           Pair.second.size() <= CurrentNestedLoopCount) {
9361         // Erroneous case - clause has some problems.
9362         DependC->setLoopData(CurrentNestedLoopCount, nullptr);
9363         continue;
9364       }
9365       OMPDoacrossKind ODK;
9366       if (DoacrossC && ODK.isSink(DoacrossC) &&
9367           Pair.second.size() <= CurrentNestedLoopCount) {
9368         // Erroneous case - clause has some problems.
9369         DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
9370         continue;
9371       }
9372       Expr *CntValue;
9373       SourceLocation DepLoc =
9374           DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9375       if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9376           (DoacrossC && ODK.isSource(DoacrossC)))
9377         CntValue = ISC.buildOrderedLoopData(
9378             DSA.getCurScope(),
9379             ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9380             DepLoc);
9381       else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9382         Expr *Cnt = SemaRef
9383                         .DefaultLvalueConversion(
9384                             ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9385                         .get();
9386         if (!Cnt)
9387           continue;
9388         // build CounterVar - 1
9389         Expr *Inc =
9390             SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
9391                 .get();
9392         CntValue = ISC.buildOrderedLoopData(
9393             DSA.getCurScope(),
9394             ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9395             DepLoc, Inc, clang::OO_Minus);
9396       } else
9397         CntValue = ISC.buildOrderedLoopData(
9398             DSA.getCurScope(),
9399             ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9400             DepLoc, Pair.second[CurrentNestedLoopCount].first,
9401             Pair.second[CurrentNestedLoopCount].second);
9402       if (DependC)
9403         DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9404       else
9405         DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9406     }
9407   }
9408 
9409   return HasErrors;
9410 }
9411 
9412 /// Build 'VarRef = Start.
9413 static ExprResult
buildCounterInit(Sema & SemaRef,Scope * S,SourceLocation Loc,ExprResult VarRef,ExprResult Start,bool IsNonRectangularLB,llvm::MapVector<const Expr *,DeclRefExpr * > & Captures)9414 buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9415                  ExprResult Start, bool IsNonRectangularLB,
9416                  llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9417   // Build 'VarRef = Start.
9418   ExprResult NewStart = IsNonRectangularLB
9419                             ? Start.get()
9420                             : tryBuildCapture(SemaRef, Start.get(), Captures);
9421   if (!NewStart.isUsable())
9422     return ExprError();
9423   if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9424                                    VarRef.get()->getType())) {
9425     NewStart = SemaRef.PerformImplicitConversion(
9426         NewStart.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9427         /*AllowExplicit=*/true);
9428     if (!NewStart.isUsable())
9429       return ExprError();
9430   }
9431 
9432   ExprResult Init =
9433       SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9434   return Init;
9435 }
9436 
9437 /// Build 'VarRef = Start + Iter * Step'.
buildCounterUpdate(Sema & SemaRef,Scope * S,SourceLocation Loc,ExprResult VarRef,ExprResult Start,ExprResult Iter,ExprResult Step,bool Subtract,bool IsNonRectangularLB,llvm::MapVector<const Expr *,DeclRefExpr * > * Captures=nullptr)9438 static ExprResult buildCounterUpdate(
9439     Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9440     ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9441     bool IsNonRectangularLB,
9442     llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9443   // Add parentheses (for debugging purposes only).
9444   Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9445   if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9446       !Step.isUsable())
9447     return ExprError();
9448 
9449   ExprResult NewStep = Step;
9450   if (Captures)
9451     NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9452   if (NewStep.isInvalid())
9453     return ExprError();
9454   ExprResult Update =
9455       SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9456   if (!Update.isUsable())
9457     return ExprError();
9458 
9459   // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9460   // 'VarRef = Start (+|-) Iter * Step'.
9461   if (!Start.isUsable())
9462     return ExprError();
9463   ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9464   if (!NewStart.isUsable())
9465     return ExprError();
9466   if (Captures && !IsNonRectangularLB)
9467     NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9468   if (NewStart.isInvalid())
9469     return ExprError();
9470 
9471   // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9472   ExprResult SavedUpdate = Update;
9473   ExprResult UpdateVal;
9474   if (VarRef.get()->getType()->isOverloadableType() ||
9475       NewStart.get()->getType()->isOverloadableType() ||
9476       Update.get()->getType()->isOverloadableType()) {
9477     Sema::TentativeAnalysisScope Trap(SemaRef);
9478 
9479     Update =
9480         SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9481     if (Update.isUsable()) {
9482       UpdateVal =
9483           SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9484                              VarRef.get(), SavedUpdate.get());
9485       if (UpdateVal.isUsable()) {
9486         Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9487                                             UpdateVal.get());
9488       }
9489     }
9490   }
9491 
9492   // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9493   if (!Update.isUsable() || !UpdateVal.isUsable()) {
9494     Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9495                                 NewStart.get(), SavedUpdate.get());
9496     if (!Update.isUsable())
9497       return ExprError();
9498 
9499     if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9500                                      VarRef.get()->getType())) {
9501       Update = SemaRef.PerformImplicitConversion(
9502           Update.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9503           /*AllowExplicit=*/true);
9504       if (!Update.isUsable())
9505         return ExprError();
9506     }
9507 
9508     Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9509   }
9510   return Update;
9511 }
9512 
9513 /// Convert integer expression \a E to make it have at least \a Bits
9514 /// bits.
widenIterationCount(unsigned Bits,Expr * E,Sema & SemaRef)9515 static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9516   if (E == nullptr)
9517     return ExprError();
9518   ASTContext &C = SemaRef.Context;
9519   QualType OldType = E->getType();
9520   unsigned HasBits = C.getTypeSize(OldType);
9521   if (HasBits >= Bits)
9522     return ExprResult(E);
9523   // OK to convert to signed, because new type has more bits than old.
9524   QualType NewType = C.getIntTypeForBitwidth(Bits, /*Signed=*/true);
9525   return SemaRef.PerformImplicitConversion(
9526       E, NewType, AssignmentAction::Converting, /*AllowExplicit=*/true);
9527 }
9528 
9529 /// Check if the given expression \a E is a constant integer that fits
9530 /// into \a Bits bits.
fitsInto(unsigned Bits,bool Signed,const Expr * E,Sema & SemaRef)9531 static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9532   if (E == nullptr)
9533     return false;
9534   if (std::optional<llvm::APSInt> Result =
9535           E->getIntegerConstantExpr(SemaRef.Context))
9536     return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9537   return false;
9538 }
9539 
9540 /// Build preinits statement for the given declarations.
buildPreInits(ASTContext & Context,MutableArrayRef<Decl * > PreInits)9541 static Stmt *buildPreInits(ASTContext &Context,
9542                            MutableArrayRef<Decl *> PreInits) {
9543   if (!PreInits.empty()) {
9544     return new (Context) DeclStmt(
9545         DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9546         SourceLocation(), SourceLocation());
9547   }
9548   return nullptr;
9549 }
9550 
9551 /// Append the \p Item or the content of a CompoundStmt to the list \p
9552 /// TargetList.
9553 ///
9554 /// A CompoundStmt is used as container in case multiple statements need to be
9555 /// stored in lieu of using an explicit list. Flattening is necessary because
9556 /// contained DeclStmts need to be visible after the execution of the list. Used
9557 /// for OpenMP pre-init declarations/statements.
appendFlattenedStmtList(SmallVectorImpl<Stmt * > & TargetList,Stmt * Item)9558 static void appendFlattenedStmtList(SmallVectorImpl<Stmt *> &TargetList,
9559                                     Stmt *Item) {
9560   // nullptr represents an empty list.
9561   if (!Item)
9562     return;
9563 
9564   if (auto *CS = dyn_cast<CompoundStmt>(Item))
9565     llvm::append_range(TargetList, CS->body());
9566   else
9567     TargetList.push_back(Item);
9568 }
9569 
9570 /// Build preinits statement for the given declarations.
9571 static Stmt *
buildPreInits(ASTContext & Context,const llvm::MapVector<const Expr *,DeclRefExpr * > & Captures)9572 buildPreInits(ASTContext &Context,
9573               const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9574   if (!Captures.empty()) {
9575     SmallVector<Decl *, 16> PreInits;
9576     for (const auto &Pair : Captures)
9577       PreInits.push_back(Pair.second->getDecl());
9578     return buildPreInits(Context, PreInits);
9579   }
9580   return nullptr;
9581 }
9582 
9583 /// Build pre-init statement for the given statements.
buildPreInits(ASTContext & Context,ArrayRef<Stmt * > PreInits)9584 static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
9585   if (PreInits.empty())
9586     return nullptr;
9587 
9588   SmallVector<Stmt *> Stmts;
9589   for (Stmt *S : PreInits)
9590     appendFlattenedStmtList(Stmts, S);
9591   return CompoundStmt::Create(Context, PreInits, FPOptionsOverride(), {}, {});
9592 }
9593 
9594 /// Build postupdate expression for the given list of postupdates expressions.
buildPostUpdate(Sema & S,ArrayRef<Expr * > PostUpdates)9595 static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9596   Expr *PostUpdate = nullptr;
9597   if (!PostUpdates.empty()) {
9598     for (Expr *E : PostUpdates) {
9599       Expr *ConvE = S.BuildCStyleCastExpr(
9600                          E->getExprLoc(),
9601                          S.Context.getTrivialTypeSourceInfo(S.Context.VoidTy),
9602                          E->getExprLoc(), E)
9603                         .get();
9604       PostUpdate = PostUpdate
9605                        ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9606                                               PostUpdate, ConvE)
9607                              .get()
9608                        : ConvE;
9609     }
9610   }
9611   return PostUpdate;
9612 }
9613 
9614 /// Look for variables declared in the body parts of a for-loop nest.  Used
9615 /// for verifying loop nest structure before performing a loop collapse
9616 /// operation.
9617 class ForVarDeclFinder : public DynamicRecursiveASTVisitor {
9618   int NestingDepth = 0;
9619   llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9620 
9621 public:
ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl * > & VD)9622   explicit ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl *> &VD)
9623       : VarDecls(VD) {}
9624 
VisitForStmt(ForStmt * F)9625   bool VisitForStmt(ForStmt *F) override {
9626     ++NestingDepth;
9627     TraverseStmt(F->getBody());
9628     --NestingDepth;
9629     return false;
9630   }
9631 
VisitCXXForRangeStmt(CXXForRangeStmt * RF)9632   bool VisitCXXForRangeStmt(CXXForRangeStmt *RF) override {
9633     ++NestingDepth;
9634     TraverseStmt(RF->getBody());
9635     --NestingDepth;
9636     return false;
9637   }
9638 
VisitVarDecl(VarDecl * D)9639   bool VisitVarDecl(VarDecl *D) override {
9640     Decl *C = D->getCanonicalDecl();
9641     if (NestingDepth > 0)
9642       VarDecls.insert(C);
9643     return true;
9644   }
9645 };
9646 
9647 /// Called on a for stmt to check itself and nested loops (if any).
9648 /// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9649 /// number of collapsed loops otherwise.
9650 static unsigned
checkOpenMPLoop(OpenMPDirectiveKind DKind,Expr * CollapseLoopCountExpr,Expr * OrderedLoopCountExpr,Stmt * AStmt,Sema & SemaRef,DSAStackTy & DSA,SemaOpenMP::VarsWithInheritedDSAType & VarsWithImplicitDSA,OMPLoopBasedDirective::HelperExprs & Built)9651 checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9652                 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9653                 DSAStackTy &DSA,
9654                 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9655                 OMPLoopBasedDirective::HelperExprs &Built) {
9656   // If either of the loop expressions exist and contain errors, we bail out
9657   // early because diagnostics have already been emitted and we can't reliably
9658   // check more about the loop.
9659   if ((CollapseLoopCountExpr && CollapseLoopCountExpr->containsErrors()) ||
9660       (OrderedLoopCountExpr && OrderedLoopCountExpr->containsErrors()))
9661     return 0;
9662 
9663   unsigned NestedLoopCount = 1;
9664   bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9665                                     !isOpenMPLoopTransformationDirective(DKind);
9666   llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopVarDecls;
9667 
9668   if (CollapseLoopCountExpr) {
9669     // Found 'collapse' clause - calculate collapse number.
9670     Expr::EvalResult Result;
9671     if (!CollapseLoopCountExpr->isValueDependent() &&
9672         CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9673       NestedLoopCount = Result.Val.getInt().getLimitedValue();
9674 
9675       ForVarDeclFinder FVDF{CollapsedLoopVarDecls};
9676       FVDF.TraverseStmt(AStmt);
9677     } else {
9678       Built.clear(/*Size=*/1);
9679       return 1;
9680     }
9681   }
9682   unsigned OrderedLoopCount = 1;
9683   if (OrderedLoopCountExpr) {
9684     // Found 'ordered' clause - calculate collapse number.
9685     Expr::EvalResult EVResult;
9686     if (!OrderedLoopCountExpr->isValueDependent() &&
9687         OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9688                                             SemaRef.getASTContext())) {
9689       llvm::APSInt Result = EVResult.Val.getInt();
9690       if (Result.getLimitedValue() < NestedLoopCount) {
9691         SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9692                      diag::err_omp_wrong_ordered_loop_count)
9693             << OrderedLoopCountExpr->getSourceRange();
9694         SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9695                      diag::note_collapse_loop_count)
9696             << CollapseLoopCountExpr->getSourceRange();
9697       }
9698       OrderedLoopCount = Result.getLimitedValue();
9699     } else {
9700       Built.clear(/*Size=*/1);
9701       return 1;
9702     }
9703   }
9704   // This is helper routine for loop directives (e.g., 'for', 'simd',
9705   // 'for simd', etc.).
9706   llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9707   unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9708   SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9709   if (!OMPLoopBasedDirective::doForAllLoops(
9710           AStmt->IgnoreContainers(!isOpenMPLoopTransformationDirective(DKind)),
9711           SupportsNonPerfectlyNested, NumLoops,
9712           [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9713            CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9714            &IterSpaces, &Captures,
9715            &CollapsedLoopVarDecls](unsigned Cnt, Stmt *CurStmt) {
9716             if (checkOpenMPIterationSpace(
9717                     DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9718                     NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9719                     VarsWithImplicitDSA, IterSpaces, Captures,
9720                     CollapsedLoopVarDecls))
9721               return true;
9722             if (Cnt > 0 && Cnt >= NestedLoopCount &&
9723                 IterSpaces[Cnt].CounterVar) {
9724               // Handle initialization of captured loop iterator variables.
9725               auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9726               if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9727                 Captures[DRE] = DRE;
9728               }
9729             }
9730             return false;
9731           },
9732           [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9733             Stmt *DependentPreInits = Transform->getPreInits();
9734             if (!DependentPreInits)
9735               return;
9736 
9737             // Search for pre-init declared variables that need to be captured
9738             // to be referenceable inside the directive.
9739             SmallVector<Stmt *> Constituents;
9740             appendFlattenedStmtList(Constituents, DependentPreInits);
9741             for (Stmt *S : Constituents) {
9742               if (auto *DC = dyn_cast<DeclStmt>(S)) {
9743                 for (Decl *C : DC->decls()) {
9744                   auto *D = cast<VarDecl>(C);
9745                   DeclRefExpr *Ref = buildDeclRefExpr(
9746                       SemaRef, D, D->getType().getNonReferenceType(),
9747                       Transform->getBeginLoc());
9748                   Captures[Ref] = Ref;
9749                 }
9750               }
9751             }
9752           }))
9753     return 0;
9754 
9755   Built.clear(/*size=*/NestedLoopCount);
9756 
9757   if (SemaRef.CurContext->isDependentContext())
9758     return NestedLoopCount;
9759 
9760   // An example of what is generated for the following code:
9761   //
9762   //   #pragma omp simd collapse(2) ordered(2)
9763   //   for (i = 0; i < NI; ++i)
9764   //     for (k = 0; k < NK; ++k)
9765   //       for (j = J0; j < NJ; j+=2) {
9766   //         <loop body>
9767   //       }
9768   //
9769   // We generate the code below.
9770   // Note: the loop body may be outlined in CodeGen.
9771   // Note: some counters may be C++ classes, operator- is used to find number of
9772   // iterations and operator+= to calculate counter value.
9773   // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9774   // or i64 is currently supported).
9775   //
9776   //   #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9777   //   for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9778   //     .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9779   //     .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9780   //     // similar updates for vars in clauses (e.g. 'linear')
9781   //     <loop body (using local i and j)>
9782   //   }
9783   //   i = NI; // assign final values of counters
9784   //   j = NJ;
9785   //
9786 
9787   // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9788   // the iteration counts of the collapsed for loops.
9789   // Precondition tests if there is at least one iteration (all conditions are
9790   // true).
9791   auto PreCond = ExprResult(IterSpaces[0].PreCond);
9792   Expr *N0 = IterSpaces[0].NumIterations;
9793   ExprResult LastIteration32 = widenIterationCount(
9794       /*Bits=*/32,
9795       SemaRef
9796           .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
9797                                      AssignmentAction::Converting,
9798                                      /*AllowExplicit=*/true)
9799           .get(),
9800       SemaRef);
9801   ExprResult LastIteration64 = widenIterationCount(
9802       /*Bits=*/64,
9803       SemaRef
9804           .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
9805                                      AssignmentAction::Converting,
9806                                      /*AllowExplicit=*/true)
9807           .get(),
9808       SemaRef);
9809 
9810   if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
9811     return NestedLoopCount;
9812 
9813   ASTContext &C = SemaRef.Context;
9814   bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
9815 
9816   Scope *CurScope = DSA.getCurScope();
9817   for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9818     if (PreCond.isUsable()) {
9819       PreCond =
9820           SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
9821                              PreCond.get(), IterSpaces[Cnt].PreCond);
9822     }
9823     Expr *N = IterSpaces[Cnt].NumIterations;
9824     SourceLocation Loc = N->getExprLoc();
9825     AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
9826     if (LastIteration32.isUsable())
9827       LastIteration32 = SemaRef.BuildBinOp(
9828           CurScope, Loc, BO_Mul, LastIteration32.get(),
9829           SemaRef
9830               .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
9831                                          AssignmentAction::Converting,
9832                                          /*AllowExplicit=*/true)
9833               .get());
9834     if (LastIteration64.isUsable())
9835       LastIteration64 = SemaRef.BuildBinOp(
9836           CurScope, Loc, BO_Mul, LastIteration64.get(),
9837           SemaRef
9838               .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
9839                                          AssignmentAction::Converting,
9840                                          /*AllowExplicit=*/true)
9841               .get());
9842   }
9843 
9844   // Choose either the 32-bit or 64-bit version.
9845   ExprResult LastIteration = LastIteration64;
9846   if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
9847       (LastIteration32.isUsable() &&
9848        C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
9849        (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9850         fitsInto(
9851             /*Bits=*/32,
9852             LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
9853             LastIteration64.get(), SemaRef))))
9854     LastIteration = LastIteration32;
9855   QualType VType = LastIteration.get()->getType();
9856   QualType RealVType = VType;
9857   QualType StrideVType = VType;
9858   if (isOpenMPTaskLoopDirective(DKind)) {
9859     VType =
9860         SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9861     StrideVType =
9862         SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9863   }
9864 
9865   if (!LastIteration.isUsable())
9866     return 0;
9867 
9868   // Save the number of iterations.
9869   ExprResult NumIterations = LastIteration;
9870   {
9871     LastIteration = SemaRef.BuildBinOp(
9872         CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
9873         LastIteration.get(),
9874         SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9875     if (!LastIteration.isUsable())
9876       return 0;
9877   }
9878 
9879   // Calculate the last iteration number beforehand instead of doing this on
9880   // each iteration. Do not do this if the number of iterations may be kfold-ed.
9881   bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
9882   ExprResult CalcLastIteration;
9883   if (!IsConstant) {
9884     ExprResult SaveRef =
9885         tryBuildCapture(SemaRef, LastIteration.get(), Captures);
9886     LastIteration = SaveRef;
9887 
9888     // Prepare SaveRef + 1.
9889     NumIterations = SemaRef.BuildBinOp(
9890         CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
9891         SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9892     if (!NumIterations.isUsable())
9893       return 0;
9894   }
9895 
9896   SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
9897 
9898   // Build variables passed into runtime, necessary for worksharing directives.
9899   ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9900   if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
9901       isOpenMPDistributeDirective(DKind) ||
9902       isOpenMPGenericLoopDirective(DKind) ||
9903       isOpenMPLoopTransformationDirective(DKind)) {
9904     // Lower bound variable, initialized with zero.
9905     VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
9906     LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
9907     SemaRef.AddInitializerToDecl(LBDecl,
9908                                  SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9909                                  /*DirectInit=*/false);
9910 
9911     // Upper bound variable, initialized with last iteration number.
9912     VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
9913     UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
9914     SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
9915                                  /*DirectInit=*/false);
9916 
9917     // A 32-bit variable-flag where runtime returns 1 for the last iteration.
9918     // This will be used to implement clause 'lastprivate'.
9919     QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
9920     VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
9921     IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
9922     SemaRef.AddInitializerToDecl(ILDecl,
9923                                  SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9924                                  /*DirectInit=*/false);
9925 
9926     // Stride variable returned by runtime (we initialize it to 1 by default).
9927     VarDecl *STDecl =
9928         buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
9929     ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
9930     SemaRef.AddInitializerToDecl(STDecl,
9931                                  SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
9932                                  /*DirectInit=*/false);
9933 
9934     // Build expression: UB = min(UB, LastIteration)
9935     // It is necessary for CodeGen of directives with static scheduling.
9936     ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
9937                                                 UB.get(), LastIteration.get());
9938     ExprResult CondOp = SemaRef.ActOnConditionalOp(
9939         LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
9940         LastIteration.get(), UB.get());
9941     EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
9942                              CondOp.get());
9943     EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue=*/false);
9944 
9945     // If we have a combined directive that combines 'distribute', 'for' or
9946     // 'simd' we need to be able to access the bounds of the schedule of the
9947     // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
9948     // by scheduling 'distribute' have to be passed to the schedule of 'for'.
9949     if (isOpenMPLoopBoundSharingDirective(DKind)) {
9950       // Lower bound variable, initialized with zero.
9951       VarDecl *CombLBDecl =
9952           buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
9953       CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
9954       SemaRef.AddInitializerToDecl(
9955           CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9956           /*DirectInit=*/false);
9957 
9958       // Upper bound variable, initialized with last iteration number.
9959       VarDecl *CombUBDecl =
9960           buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
9961       CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
9962       SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
9963                                    /*DirectInit=*/false);
9964 
9965       ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
9966           CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
9967       ExprResult CombCondOp =
9968           SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
9969                                      LastIteration.get(), CombUB.get());
9970       CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
9971                                    CombCondOp.get());
9972       CombEUB =
9973           SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue=*/false);
9974 
9975       const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
9976       // We expect to have at least 2 more parameters than the 'parallel'
9977       // directive does - the lower and upper bounds of the previous schedule.
9978       assert(CD->getNumParams() >= 4 &&
9979              "Unexpected number of parameters in loop combined directive");
9980 
9981       // Set the proper type for the bounds given what we learned from the
9982       // enclosed loops.
9983       ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
9984       ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
9985 
9986       // Previous lower and upper bounds are obtained from the region
9987       // parameters.
9988       PrevLB =
9989           buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
9990       PrevUB =
9991           buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
9992     }
9993   }
9994 
9995   // Build the iteration variable and its initialization before loop.
9996   ExprResult IV;
9997   ExprResult Init, CombInit;
9998   {
9999     VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
10000     IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
10001     Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
10002                  isOpenMPGenericLoopDirective(DKind) ||
10003                  isOpenMPTaskLoopDirective(DKind) ||
10004                  isOpenMPDistributeDirective(DKind) ||
10005                  isOpenMPLoopTransformationDirective(DKind))
10006                     ? LB.get()
10007                     : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10008     Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
10009     Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue=*/false);
10010 
10011     if (isOpenMPLoopBoundSharingDirective(DKind)) {
10012       Expr *CombRHS =
10013           (isOpenMPWorksharingDirective(DKind) ||
10014            isOpenMPGenericLoopDirective(DKind) ||
10015            isOpenMPTaskLoopDirective(DKind) ||
10016            isOpenMPDistributeDirective(DKind))
10017               ? CombLB.get()
10018               : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10019       CombInit =
10020           SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
10021       CombInit =
10022           SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue=*/false);
10023     }
10024   }
10025 
10026   bool UseStrictCompare =
10027       RealVType->hasUnsignedIntegerRepresentation() &&
10028       llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
10029         return LIS.IsStrictCompare;
10030       });
10031   // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10032   // unsigned IV)) for worksharing loops.
10033   SourceLocation CondLoc = AStmt->getBeginLoc();
10034   Expr *BoundUB = UB.get();
10035   if (UseStrictCompare) {
10036     BoundUB =
10037         SemaRef
10038             .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10039                         SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10040             .get();
10041     BoundUB =
10042         SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue=*/false).get();
10043   }
10044   ExprResult Cond =
10045       (isOpenMPWorksharingDirective(DKind) ||
10046        isOpenMPGenericLoopDirective(DKind) ||
10047        isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind) ||
10048        isOpenMPLoopTransformationDirective(DKind))
10049           ? SemaRef.BuildBinOp(CurScope, CondLoc,
10050                                UseStrictCompare ? BO_LT : BO_LE, IV.get(),
10051                                BoundUB)
10052           : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10053                                NumIterations.get());
10054   ExprResult CombDistCond;
10055   if (isOpenMPLoopBoundSharingDirective(DKind)) {
10056     CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10057                                       NumIterations.get());
10058   }
10059 
10060   ExprResult CombCond;
10061   if (isOpenMPLoopBoundSharingDirective(DKind)) {
10062     Expr *BoundCombUB = CombUB.get();
10063     if (UseStrictCompare) {
10064       BoundCombUB =
10065           SemaRef
10066               .BuildBinOp(
10067                   CurScope, CondLoc, BO_Add, BoundCombUB,
10068                   SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10069               .get();
10070       BoundCombUB =
10071           SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue=*/false)
10072               .get();
10073     }
10074     CombCond =
10075         SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10076                            IV.get(), BoundCombUB);
10077   }
10078   // Loop increment (IV = IV + 1)
10079   SourceLocation IncLoc = AStmt->getBeginLoc();
10080   ExprResult Inc =
10081       SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
10082                          SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
10083   if (!Inc.isUsable())
10084     return 0;
10085   Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
10086   Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue=*/false);
10087   if (!Inc.isUsable())
10088     return 0;
10089 
10090   // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10091   // Used for directives with static scheduling.
10092   // In combined construct, add combined version that use CombLB and CombUB
10093   // base variables for the update
10094   ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10095   if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
10096       isOpenMPGenericLoopDirective(DKind) ||
10097       isOpenMPDistributeDirective(DKind) ||
10098       isOpenMPLoopTransformationDirective(DKind)) {
10099     // LB + ST
10100     NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
10101     if (!NextLB.isUsable())
10102       return 0;
10103     // LB = LB + ST
10104     NextLB =
10105         SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
10106     NextLB =
10107         SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue=*/false);
10108     if (!NextLB.isUsable())
10109       return 0;
10110     // UB + ST
10111     NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
10112     if (!NextUB.isUsable())
10113       return 0;
10114     // UB = UB + ST
10115     NextUB =
10116         SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
10117     NextUB =
10118         SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue=*/false);
10119     if (!NextUB.isUsable())
10120       return 0;
10121     if (isOpenMPLoopBoundSharingDirective(DKind)) {
10122       CombNextLB =
10123           SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
10124       if (!NextLB.isUsable())
10125         return 0;
10126       // LB = LB + ST
10127       CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
10128                                       CombNextLB.get());
10129       CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
10130                                                /*DiscardedValue=*/false);
10131       if (!CombNextLB.isUsable())
10132         return 0;
10133       // UB + ST
10134       CombNextUB =
10135           SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
10136       if (!CombNextUB.isUsable())
10137         return 0;
10138       // UB = UB + ST
10139       CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
10140                                       CombNextUB.get());
10141       CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
10142                                                /*DiscardedValue=*/false);
10143       if (!CombNextUB.isUsable())
10144         return 0;
10145     }
10146   }
10147 
10148   // Create increment expression for distribute loop when combined in a same
10149   // directive with for as IV = IV + ST; ensure upper bound expression based
10150   // on PrevUB instead of NumIterations - used to implement 'for' when found
10151   // in combination with 'distribute', like in 'distribute parallel for'
10152   SourceLocation DistIncLoc = AStmt->getBeginLoc();
10153   ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10154   if (isOpenMPLoopBoundSharingDirective(DKind)) {
10155     DistCond = SemaRef.BuildBinOp(
10156         CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10157     assert(DistCond.isUsable() && "distribute cond expr was not built");
10158 
10159     DistInc =
10160         SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10161     assert(DistInc.isUsable() && "distribute inc expr was not built");
10162     DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10163                                  DistInc.get());
10164     DistInc =
10165         SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue=*/false);
10166     assert(DistInc.isUsable() && "distribute inc expr was not built");
10167 
10168     // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10169     // construct
10170     ExprResult NewPrevUB = PrevUB;
10171     SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10172     if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10173                                      PrevUB.get()->getType())) {
10174       NewPrevUB = SemaRef.BuildCStyleCastExpr(
10175           DistEUBLoc,
10176           SemaRef.Context.getTrivialTypeSourceInfo(UB.get()->getType()),
10177           DistEUBLoc, NewPrevUB.get());
10178       if (!NewPrevUB.isUsable())
10179         return 0;
10180     }
10181     ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10182                                                 UB.get(), NewPrevUB.get());
10183     ExprResult CondOp = SemaRef.ActOnConditionalOp(
10184         DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10185     PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10186                                  CondOp.get());
10187     PrevEUB =
10188         SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue=*/false);
10189 
10190     // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10191     // parallel for is in combination with a distribute directive with
10192     // schedule(static, 1)
10193     Expr *BoundPrevUB = PrevUB.get();
10194     if (UseStrictCompare) {
10195       BoundPrevUB =
10196           SemaRef
10197               .BuildBinOp(
10198                   CurScope, CondLoc, BO_Add, BoundPrevUB,
10199                   SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10200               .get();
10201       BoundPrevUB =
10202           SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue=*/false)
10203               .get();
10204     }
10205     ParForInDistCond =
10206         SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10207                            IV.get(), BoundPrevUB);
10208   }
10209 
10210   // Build updates and final values of the loop counters.
10211   bool HasErrors = false;
10212   Built.Counters.resize(NestedLoopCount);
10213   Built.Inits.resize(NestedLoopCount);
10214   Built.Updates.resize(NestedLoopCount);
10215   Built.Finals.resize(NestedLoopCount);
10216   Built.DependentCounters.resize(NestedLoopCount);
10217   Built.DependentInits.resize(NestedLoopCount);
10218   Built.FinalsConditions.resize(NestedLoopCount);
10219   {
10220     // We implement the following algorithm for obtaining the
10221     // original loop iteration variable values based on the
10222     // value of the collapsed loop iteration variable IV.
10223     //
10224     // Let n+1 be the number of collapsed loops in the nest.
10225     // Iteration variables (I0, I1, .... In)
10226     // Iteration counts (N0, N1, ... Nn)
10227     //
10228     // Acc = IV;
10229     //
10230     // To compute Ik for loop k, 0 <= k <= n, generate:
10231     //    Prod = N(k+1) * N(k+2) * ... * Nn;
10232     //    Ik = Acc / Prod;
10233     //    Acc -= Ik * Prod;
10234     //
10235     ExprResult Acc = IV;
10236     for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10237       LoopIterationSpace &IS = IterSpaces[Cnt];
10238       SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10239       ExprResult Iter;
10240 
10241       // Compute prod
10242       ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10243       for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10244         Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10245                                   IterSpaces[K].NumIterations);
10246 
10247       // Iter = Acc / Prod
10248       // If there is at least one more inner loop to avoid
10249       // multiplication by 1.
10250       if (Cnt + 1 < NestedLoopCount)
10251         Iter =
10252             SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10253       else
10254         Iter = Acc;
10255       if (!Iter.isUsable()) {
10256         HasErrors = true;
10257         break;
10258       }
10259 
10260       // Update Acc:
10261       // Acc -= Iter * Prod
10262       // Check if there is at least one more inner loop to avoid
10263       // multiplication by 1.
10264       if (Cnt + 1 < NestedLoopCount)
10265         Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10266                                   Prod.get());
10267       else
10268         Prod = Iter;
10269       Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10270 
10271       // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10272       auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10273       DeclRefExpr *CounterVar = buildDeclRefExpr(
10274           SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10275           /*RefersToCapture=*/true);
10276       ExprResult Init =
10277           buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10278                            IS.CounterInit, IS.IsNonRectangularLB, Captures);
10279       if (!Init.isUsable()) {
10280         HasErrors = true;
10281         break;
10282       }
10283       ExprResult Update = buildCounterUpdate(
10284           SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10285           IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10286       if (!Update.isUsable()) {
10287         HasErrors = true;
10288         break;
10289       }
10290 
10291       // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10292       ExprResult Final =
10293           buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10294                              IS.CounterInit, IS.NumIterations, IS.CounterStep,
10295                              IS.Subtract, IS.IsNonRectangularLB, &Captures);
10296       if (!Final.isUsable()) {
10297         HasErrors = true;
10298         break;
10299       }
10300 
10301       if (!Update.isUsable() || !Final.isUsable()) {
10302         HasErrors = true;
10303         break;
10304       }
10305       // Save results
10306       Built.Counters[Cnt] = IS.CounterVar;
10307       Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10308       Built.Inits[Cnt] = Init.get();
10309       Built.Updates[Cnt] = Update.get();
10310       Built.Finals[Cnt] = Final.get();
10311       Built.DependentCounters[Cnt] = nullptr;
10312       Built.DependentInits[Cnt] = nullptr;
10313       Built.FinalsConditions[Cnt] = nullptr;
10314       if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10315         Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10316         Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10317         Built.FinalsConditions[Cnt] = IS.FinalCondition;
10318       }
10319     }
10320   }
10321 
10322   if (HasErrors)
10323     return 0;
10324 
10325   // Save results
10326   Built.IterationVarRef = IV.get();
10327   Built.LastIteration = LastIteration.get();
10328   Built.NumIterations = NumIterations.get();
10329   Built.CalcLastIteration = SemaRef
10330                                 .ActOnFinishFullExpr(CalcLastIteration.get(),
10331                                                      /*DiscardedValue=*/false)
10332                                 .get();
10333   Built.PreCond = PreCond.get();
10334   Built.PreInits = buildPreInits(C, Captures);
10335   Built.Cond = Cond.get();
10336   Built.Init = Init.get();
10337   Built.Inc = Inc.get();
10338   Built.LB = LB.get();
10339   Built.UB = UB.get();
10340   Built.IL = IL.get();
10341   Built.ST = ST.get();
10342   Built.EUB = EUB.get();
10343   Built.NLB = NextLB.get();
10344   Built.NUB = NextUB.get();
10345   Built.PrevLB = PrevLB.get();
10346   Built.PrevUB = PrevUB.get();
10347   Built.DistInc = DistInc.get();
10348   Built.PrevEUB = PrevEUB.get();
10349   Built.DistCombinedFields.LB = CombLB.get();
10350   Built.DistCombinedFields.UB = CombUB.get();
10351   Built.DistCombinedFields.EUB = CombEUB.get();
10352   Built.DistCombinedFields.Init = CombInit.get();
10353   Built.DistCombinedFields.Cond = CombCond.get();
10354   Built.DistCombinedFields.NLB = CombNextLB.get();
10355   Built.DistCombinedFields.NUB = CombNextUB.get();
10356   Built.DistCombinedFields.DistCond = CombDistCond.get();
10357   Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10358 
10359   return NestedLoopCount;
10360 }
10361 
getCollapseNumberExpr(ArrayRef<OMPClause * > Clauses)10362 static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {
10363   auto CollapseClauses =
10364       OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10365   if (CollapseClauses.begin() != CollapseClauses.end())
10366     return (*CollapseClauses.begin())->getNumForLoops();
10367   return nullptr;
10368 }
10369 
getOrderedNumberExpr(ArrayRef<OMPClause * > Clauses)10370 static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) {
10371   auto OrderedClauses =
10372       OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10373   if (OrderedClauses.begin() != OrderedClauses.end())
10374     return (*OrderedClauses.begin())->getNumForLoops();
10375   return nullptr;
10376 }
10377 
checkSimdlenSafelenSpecified(Sema & S,const ArrayRef<OMPClause * > Clauses)10378 static bool checkSimdlenSafelenSpecified(Sema &S,
10379                                          const ArrayRef<OMPClause *> Clauses) {
10380   const OMPSafelenClause *Safelen = nullptr;
10381   const OMPSimdlenClause *Simdlen = nullptr;
10382 
10383   for (const OMPClause *Clause : Clauses) {
10384     if (Clause->getClauseKind() == OMPC_safelen)
10385       Safelen = cast<OMPSafelenClause>(Clause);
10386     else if (Clause->getClauseKind() == OMPC_simdlen)
10387       Simdlen = cast<OMPSimdlenClause>(Clause);
10388     if (Safelen && Simdlen)
10389       break;
10390   }
10391 
10392   if (Simdlen && Safelen) {
10393     const Expr *SimdlenLength = Simdlen->getSimdlen();
10394     const Expr *SafelenLength = Safelen->getSafelen();
10395     if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10396         SimdlenLength->isInstantiationDependent() ||
10397         SimdlenLength->containsUnexpandedParameterPack())
10398       return false;
10399     if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10400         SafelenLength->isInstantiationDependent() ||
10401         SafelenLength->containsUnexpandedParameterPack())
10402       return false;
10403     Expr::EvalResult SimdlenResult, SafelenResult;
10404     SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10405     SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10406     llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10407     llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10408     // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10409     // If both simdlen and safelen clauses are specified, the value of the
10410     // simdlen parameter must be less than or equal to the value of the safelen
10411     // parameter.
10412     if (SimdlenRes > SafelenRes) {
10413       S.Diag(SimdlenLength->getExprLoc(),
10414              diag::err_omp_wrong_simdlen_safelen_values)
10415           << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10416       return true;
10417     }
10418   }
10419   return false;
10420 }
10421 
ActOnOpenMPSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10422 StmtResult SemaOpenMP::ActOnOpenMPSimdDirective(
10423     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10424     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10425   if (!AStmt)
10426     return StmtError();
10427 
10428   CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_simd, AStmt);
10429 
10430   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10431   OMPLoopBasedDirective::HelperExprs B;
10432   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10433   // define the nested loops number.
10434   unsigned NestedLoopCount = checkOpenMPLoop(
10435       OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10436       CS, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10437   if (NestedLoopCount == 0)
10438     return StmtError();
10439 
10440   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10441     return StmtError();
10442 
10443   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
10444     return StmtError();
10445 
10446   auto *SimdDirective = OMPSimdDirective::Create(
10447       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10448   return SimdDirective;
10449 }
10450 
ActOnOpenMPForDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10451 StmtResult SemaOpenMP::ActOnOpenMPForDirective(
10452     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10453     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10454   if (!AStmt)
10455     return StmtError();
10456 
10457   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10458   OMPLoopBasedDirective::HelperExprs B;
10459   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10460   // define the nested loops number.
10461   unsigned NestedLoopCount = checkOpenMPLoop(
10462       OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10463       AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10464   if (NestedLoopCount == 0)
10465     return StmtError();
10466 
10467   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10468     return StmtError();
10469 
10470   auto *ForDirective = OMPForDirective::Create(
10471       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10472       DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10473   return ForDirective;
10474 }
10475 
ActOnOpenMPForSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10476 StmtResult SemaOpenMP::ActOnOpenMPForSimdDirective(
10477     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10478     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10479   if (!AStmt)
10480     return StmtError();
10481 
10482   CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_for_simd, AStmt);
10483 
10484   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10485   OMPLoopBasedDirective::HelperExprs B;
10486   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10487   // define the nested loops number.
10488   unsigned NestedLoopCount =
10489       checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10490                       getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10491                       VarsWithImplicitDSA, B);
10492   if (NestedLoopCount == 0)
10493     return StmtError();
10494 
10495   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10496     return StmtError();
10497 
10498   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
10499     return StmtError();
10500 
10501   return OMPForSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
10502                                      NestedLoopCount, Clauses, AStmt, B);
10503 }
10504 
checkSectionsDirective(Sema & SemaRef,OpenMPDirectiveKind DKind,Stmt * AStmt,DSAStackTy * Stack)10505 static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind,
10506                                    Stmt *AStmt, DSAStackTy *Stack) {
10507   if (!AStmt)
10508     return true;
10509 
10510   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10511   unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
10512   auto BaseStmt = AStmt;
10513   while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10514     BaseStmt = CS->getCapturedStmt();
10515   if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10516     auto S = C->children();
10517     if (S.begin() == S.end())
10518       return true;
10519     // All associated statements must be '#pragma omp section' except for
10520     // the first one.
10521     for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10522       if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10523         if (SectionStmt)
10524           SemaRef.Diag(SectionStmt->getBeginLoc(),
10525                        diag::err_omp_sections_substmt_not_section)
10526               << getOpenMPDirectiveName(DKind, OMPVersion);
10527         return true;
10528       }
10529       cast<OMPSectionDirective>(SectionStmt)
10530           ->setHasCancel(Stack->isCancelRegion());
10531     }
10532   } else {
10533     SemaRef.Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10534         << getOpenMPDirectiveName(DKind, OMPVersion);
10535     return true;
10536   }
10537   return false;
10538 }
10539 
10540 StmtResult
ActOnOpenMPSectionsDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10541 SemaOpenMP::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
10542                                          Stmt *AStmt, SourceLocation StartLoc,
10543                                          SourceLocation EndLoc) {
10544   if (checkSectionsDirective(SemaRef, OMPD_sections, AStmt, DSAStack))
10545     return StmtError();
10546 
10547   SemaRef.setFunctionHasBranchProtectedScope();
10548 
10549   return OMPSectionsDirective::Create(
10550       getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10551       DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10552 }
10553 
ActOnOpenMPSectionDirective(Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10554 StmtResult SemaOpenMP::ActOnOpenMPSectionDirective(Stmt *AStmt,
10555                                                    SourceLocation StartLoc,
10556                                                    SourceLocation EndLoc) {
10557   if (!AStmt)
10558     return StmtError();
10559 
10560   SemaRef.setFunctionHasBranchProtectedScope();
10561   DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10562 
10563   return OMPSectionDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt,
10564                                      DSAStack->isCancelRegion());
10565 }
10566 
getDirectCallExpr(Expr * E)10567 static Expr *getDirectCallExpr(Expr *E) {
10568   E = E->IgnoreParenCasts()->IgnoreImplicit();
10569   if (auto *CE = dyn_cast<CallExpr>(E))
10570     if (CE->getDirectCallee())
10571       return E;
10572   return nullptr;
10573 }
10574 
10575 StmtResult
ActOnOpenMPDispatchDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10576 SemaOpenMP::ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses,
10577                                          Stmt *AStmt, SourceLocation StartLoc,
10578                                          SourceLocation EndLoc) {
10579   if (!AStmt)
10580     return StmtError();
10581 
10582   Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10583 
10584   // 5.1 OpenMP
10585   // expression-stmt : an expression statement with one of the following forms:
10586   //   expression = target-call ( [expression-list] );
10587   //   target-call ( [expression-list] );
10588 
10589   SourceLocation TargetCallLoc;
10590 
10591   if (!SemaRef.CurContext->isDependentContext()) {
10592     Expr *TargetCall = nullptr;
10593 
10594     auto *E = dyn_cast<Expr>(S);
10595     if (!E) {
10596       Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10597       return StmtError();
10598     }
10599 
10600     E = E->IgnoreParenCasts()->IgnoreImplicit();
10601 
10602     if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10603       if (BO->getOpcode() == BO_Assign)
10604         TargetCall = getDirectCallExpr(BO->getRHS());
10605     } else {
10606       if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10607         if (COCE->getOperator() == OO_Equal)
10608           TargetCall = getDirectCallExpr(COCE->getArg(1));
10609       if (!TargetCall)
10610         TargetCall = getDirectCallExpr(E);
10611     }
10612     if (!TargetCall) {
10613       Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10614       return StmtError();
10615     }
10616     TargetCallLoc = TargetCall->getExprLoc();
10617   }
10618 
10619   SemaRef.setFunctionHasBranchProtectedScope();
10620 
10621   return OMPDispatchDirective::Create(getASTContext(), StartLoc, EndLoc,
10622                                       Clauses, AStmt, TargetCallLoc);
10623 }
10624 
checkGenericLoopLastprivate(Sema & S,ArrayRef<OMPClause * > Clauses,OpenMPDirectiveKind K,DSAStackTy * Stack)10625 static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses,
10626                                         OpenMPDirectiveKind K,
10627                                         DSAStackTy *Stack) {
10628   bool ErrorFound = false;
10629   for (OMPClause *C : Clauses) {
10630     if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10631       for (Expr *RefExpr : LPC->varlist()) {
10632         SourceLocation ELoc;
10633         SourceRange ERange;
10634         Expr *SimpleRefExpr = RefExpr;
10635         auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10636         if (ValueDecl *D = Res.first) {
10637           auto &&Info = Stack->isLoopControlVariable(D);
10638           if (!Info.first) {
10639             unsigned OMPVersion = S.getLangOpts().OpenMP;
10640             S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10641                 << getOpenMPDirectiveName(K, OMPVersion);
10642             ErrorFound = true;
10643           }
10644         }
10645       }
10646     }
10647   }
10648   return ErrorFound;
10649 }
10650 
ActOnOpenMPGenericLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10651 StmtResult SemaOpenMP::ActOnOpenMPGenericLoopDirective(
10652     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10653     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10654   if (!AStmt)
10655     return StmtError();
10656 
10657   // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10658   // A list item may not appear in a lastprivate clause unless it is the
10659   // loop iteration variable of a loop that is associated with the construct.
10660   if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack))
10661     return StmtError();
10662 
10663   setBranchProtectedScope(SemaRef, OMPD_loop, AStmt);
10664 
10665   OMPLoopDirective::HelperExprs B;
10666   // In presence of clause 'collapse', it will define the nested loops number.
10667   unsigned NestedLoopCount = checkOpenMPLoop(
10668       OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10669       AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10670   if (NestedLoopCount == 0)
10671     return StmtError();
10672 
10673   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10674          "omp loop exprs were not built");
10675 
10676   return OMPGenericLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
10677                                          NestedLoopCount, Clauses, AStmt, B);
10678 }
10679 
ActOnOpenMPTeamsGenericLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10680 StmtResult SemaOpenMP::ActOnOpenMPTeamsGenericLoopDirective(
10681     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10682     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10683   if (!AStmt)
10684     return StmtError();
10685 
10686   // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10687   // A list item may not appear in a lastprivate clause unless it is the
10688   // loop iteration variable of a loop that is associated with the construct.
10689   if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack))
10690     return StmtError();
10691 
10692   CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_teams_loop, AStmt);
10693 
10694   OMPLoopDirective::HelperExprs B;
10695   // In presence of clause 'collapse', it will define the nested loops number.
10696   unsigned NestedLoopCount =
10697       checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10698                       /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10699                       VarsWithImplicitDSA, B);
10700   if (NestedLoopCount == 0)
10701     return StmtError();
10702 
10703   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10704          "omp loop exprs were not built");
10705 
10706   DSAStack->setParentTeamsRegionLoc(StartLoc);
10707 
10708   return OMPTeamsGenericLoopDirective::Create(
10709       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10710 }
10711 
ActOnOpenMPTargetTeamsGenericLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10712 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsGenericLoopDirective(
10713     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10714     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10715   if (!AStmt)
10716     return StmtError();
10717 
10718   // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10719   // A list item may not appear in a lastprivate clause unless it is the
10720   // loop iteration variable of a loop that is associated with the construct.
10721   if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop,
10722                                   DSAStack))
10723     return StmtError();
10724 
10725   CapturedStmt *CS =
10726       setBranchProtectedScope(SemaRef, OMPD_target_teams_loop, AStmt);
10727 
10728   OMPLoopDirective::HelperExprs B;
10729   // In presence of clause 'collapse', it will define the nested loops number.
10730   unsigned NestedLoopCount =
10731       checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10732                       /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10733                       VarsWithImplicitDSA, B);
10734   if (NestedLoopCount == 0)
10735     return StmtError();
10736 
10737   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10738          "omp loop exprs were not built");
10739 
10740   return OMPTargetTeamsGenericLoopDirective::Create(
10741       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10742       teamsLoopCanBeParallelFor(AStmt, SemaRef));
10743 }
10744 
ActOnOpenMPParallelGenericLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10745 StmtResult SemaOpenMP::ActOnOpenMPParallelGenericLoopDirective(
10746     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10747     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10748   if (!AStmt)
10749     return StmtError();
10750 
10751   // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10752   // A list item may not appear in a lastprivate clause unless it is the
10753   // loop iteration variable of a loop that is associated with the construct.
10754   if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_parallel_loop,
10755                                   DSAStack))
10756     return StmtError();
10757 
10758   CapturedStmt *CS =
10759       setBranchProtectedScope(SemaRef, OMPD_parallel_loop, AStmt);
10760 
10761   OMPLoopDirective::HelperExprs B;
10762   // In presence of clause 'collapse', it will define the nested loops number.
10763   unsigned NestedLoopCount =
10764       checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
10765                       /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10766                       VarsWithImplicitDSA, B);
10767   if (NestedLoopCount == 0)
10768     return StmtError();
10769 
10770   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10771          "omp loop exprs were not built");
10772 
10773   return OMPParallelGenericLoopDirective::Create(
10774       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10775 }
10776 
ActOnOpenMPTargetParallelGenericLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10777 StmtResult SemaOpenMP::ActOnOpenMPTargetParallelGenericLoopDirective(
10778     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10779     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10780   if (!AStmt)
10781     return StmtError();
10782 
10783   // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10784   // A list item may not appear in a lastprivate clause unless it is the
10785   // loop iteration variable of a loop that is associated with the construct.
10786   if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_parallel_loop,
10787                                   DSAStack))
10788     return StmtError();
10789 
10790   CapturedStmt *CS =
10791       setBranchProtectedScope(SemaRef, OMPD_target_parallel_loop, AStmt);
10792 
10793   OMPLoopDirective::HelperExprs B;
10794   // In presence of clause 'collapse', it will define the nested loops number.
10795   unsigned NestedLoopCount =
10796       checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
10797                       /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10798                       VarsWithImplicitDSA, B);
10799   if (NestedLoopCount == 0)
10800     return StmtError();
10801 
10802   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10803          "omp loop exprs were not built");
10804 
10805   return OMPTargetParallelGenericLoopDirective::Create(
10806       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10807 }
10808 
ActOnOpenMPSingleDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10809 StmtResult SemaOpenMP::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
10810                                                   Stmt *AStmt,
10811                                                   SourceLocation StartLoc,
10812                                                   SourceLocation EndLoc) {
10813   if (!AStmt)
10814     return StmtError();
10815 
10816   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10817 
10818   SemaRef.setFunctionHasBranchProtectedScope();
10819 
10820   // OpenMP [2.7.3, single Construct, Restrictions]
10821   // The copyprivate clause must not be used with the nowait clause.
10822   const OMPClause *Nowait = nullptr;
10823   const OMPClause *Copyprivate = nullptr;
10824   for (const OMPClause *Clause : Clauses) {
10825     if (Clause->getClauseKind() == OMPC_nowait)
10826       Nowait = Clause;
10827     else if (Clause->getClauseKind() == OMPC_copyprivate)
10828       Copyprivate = Clause;
10829     if (Copyprivate && Nowait) {
10830       Diag(Copyprivate->getBeginLoc(),
10831            diag::err_omp_single_copyprivate_with_nowait);
10832       Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
10833       return StmtError();
10834     }
10835   }
10836 
10837   return OMPSingleDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
10838                                     AStmt);
10839 }
10840 
ActOnOpenMPMasterDirective(Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10841 StmtResult SemaOpenMP::ActOnOpenMPMasterDirective(Stmt *AStmt,
10842                                                   SourceLocation StartLoc,
10843                                                   SourceLocation EndLoc) {
10844   if (!AStmt)
10845     return StmtError();
10846 
10847   SemaRef.setFunctionHasBranchProtectedScope();
10848 
10849   return OMPMasterDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt);
10850 }
10851 
ActOnOpenMPMaskedDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10852 StmtResult SemaOpenMP::ActOnOpenMPMaskedDirective(ArrayRef<OMPClause *> Clauses,
10853                                                   Stmt *AStmt,
10854                                                   SourceLocation StartLoc,
10855                                                   SourceLocation EndLoc) {
10856   if (!AStmt)
10857     return StmtError();
10858 
10859   SemaRef.setFunctionHasBranchProtectedScope();
10860 
10861   return OMPMaskedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
10862                                     AStmt);
10863 }
10864 
ActOnOpenMPCriticalDirective(const DeclarationNameInfo & DirName,ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10865 StmtResult SemaOpenMP::ActOnOpenMPCriticalDirective(
10866     const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
10867     Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
10868   if (!AStmt)
10869     return StmtError();
10870 
10871   bool ErrorFound = false;
10872   llvm::APSInt Hint;
10873   SourceLocation HintLoc;
10874   bool DependentHint = false;
10875   for (const OMPClause *C : Clauses) {
10876     if (C->getClauseKind() == OMPC_hint) {
10877       if (!DirName.getName()) {
10878         Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
10879         ErrorFound = true;
10880       }
10881       Expr *E = cast<OMPHintClause>(C)->getHint();
10882       if (E->isTypeDependent() || E->isValueDependent() ||
10883           E->isInstantiationDependent()) {
10884         DependentHint = true;
10885       } else {
10886         Hint = E->EvaluateKnownConstInt(getASTContext());
10887         HintLoc = C->getBeginLoc();
10888       }
10889     }
10890   }
10891   if (ErrorFound)
10892     return StmtError();
10893   const auto Pair = DSAStack->getCriticalWithHint(DirName);
10894   if (Pair.first && DirName.getName() && !DependentHint) {
10895     if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
10896       Diag(StartLoc, diag::err_omp_critical_with_hint);
10897       if (HintLoc.isValid())
10898         Diag(HintLoc, diag::note_omp_critical_hint_here)
10899             << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
10900       else
10901         Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
10902       if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
10903         Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
10904             << 1
10905             << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()),
10906                         /*Radix=*/10, /*Signed=*/false);
10907       } else {
10908         Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
10909       }
10910     }
10911   }
10912 
10913   SemaRef.setFunctionHasBranchProtectedScope();
10914 
10915   auto *Dir = OMPCriticalDirective::Create(getASTContext(), DirName, StartLoc,
10916                                            EndLoc, Clauses, AStmt);
10917   if (!Pair.first && DirName.getName() && !DependentHint)
10918     DSAStack->addCriticalWithHint(Dir, Hint);
10919   return Dir;
10920 }
10921 
ActOnOpenMPParallelForDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10922 StmtResult SemaOpenMP::ActOnOpenMPParallelForDirective(
10923     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10924     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10925   if (!AStmt)
10926     return StmtError();
10927 
10928   setBranchProtectedScope(SemaRef, OMPD_parallel_for, AStmt);
10929 
10930   OMPLoopBasedDirective::HelperExprs B;
10931   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10932   // define the nested loops number.
10933   unsigned NestedLoopCount =
10934       checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
10935                       getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
10936                       VarsWithImplicitDSA, B);
10937   if (NestedLoopCount == 0)
10938     return StmtError();
10939 
10940   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10941     return StmtError();
10942 
10943   return OMPParallelForDirective::Create(
10944       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10945       DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10946 }
10947 
ActOnOpenMPParallelForSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10948 StmtResult SemaOpenMP::ActOnOpenMPParallelForSimdDirective(
10949     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10950     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10951   if (!AStmt)
10952     return StmtError();
10953 
10954   CapturedStmt *CS =
10955       setBranchProtectedScope(SemaRef, OMPD_parallel_for_simd, AStmt);
10956 
10957   OMPLoopBasedDirective::HelperExprs B;
10958   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10959   // define the nested loops number.
10960   unsigned NestedLoopCount =
10961       checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
10962                       getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10963                       VarsWithImplicitDSA, B);
10964   if (NestedLoopCount == 0)
10965     return StmtError();
10966 
10967   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10968     return StmtError();
10969 
10970   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
10971     return StmtError();
10972 
10973   return OMPParallelForSimdDirective::Create(
10974       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10975 }
10976 
ActOnOpenMPParallelMasterDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10977 StmtResult SemaOpenMP::ActOnOpenMPParallelMasterDirective(
10978     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10979     SourceLocation EndLoc) {
10980   if (!AStmt)
10981     return StmtError();
10982 
10983   setBranchProtectedScope(SemaRef, OMPD_parallel_master, AStmt);
10984 
10985   return OMPParallelMasterDirective::Create(
10986       getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10987       DSAStack->getTaskgroupReductionRef());
10988 }
10989 
ActOnOpenMPParallelMaskedDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10990 StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedDirective(
10991     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10992     SourceLocation EndLoc) {
10993   if (!AStmt)
10994     return StmtError();
10995 
10996   setBranchProtectedScope(SemaRef, OMPD_parallel_masked, AStmt);
10997 
10998   return OMPParallelMaskedDirective::Create(
10999       getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11000       DSAStack->getTaskgroupReductionRef());
11001 }
11002 
ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)11003 StmtResult SemaOpenMP::ActOnOpenMPParallelSectionsDirective(
11004     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11005     SourceLocation EndLoc) {
11006   if (checkSectionsDirective(SemaRef, OMPD_parallel_sections, AStmt, DSAStack))
11007     return StmtError();
11008 
11009   SemaRef.setFunctionHasBranchProtectedScope();
11010 
11011   return OMPParallelSectionsDirective::Create(
11012       getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11013       DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11014 }
11015 
11016 /// Find and diagnose mutually exclusive clause kinds.
checkMutuallyExclusiveClauses(Sema & S,ArrayRef<OMPClause * > Clauses,ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses)11017 static bool checkMutuallyExclusiveClauses(
11018     Sema &S, ArrayRef<OMPClause *> Clauses,
11019     ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11020   const OMPClause *PrevClause = nullptr;
11021   bool ErrorFound = false;
11022   for (const OMPClause *C : Clauses) {
11023     if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
11024       if (!PrevClause) {
11025         PrevClause = C;
11026       } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11027         S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11028             << getOpenMPClauseNameForDiag(C->getClauseKind())
11029             << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11030         S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
11031             << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11032         ErrorFound = true;
11033       }
11034     }
11035   }
11036   return ErrorFound;
11037 }
11038 
ActOnOpenMPTaskDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)11039 StmtResult SemaOpenMP::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
11040                                                 Stmt *AStmt,
11041                                                 SourceLocation StartLoc,
11042                                                 SourceLocation EndLoc) {
11043   if (!AStmt)
11044     return StmtError();
11045 
11046   // OpenMP 5.0, 2.10.1 task Construct
11047   // If a detach clause appears on the directive, then a mergeable clause cannot
11048   // appear on the same directive.
11049   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
11050                                     {OMPC_detach, OMPC_mergeable}))
11051     return StmtError();
11052 
11053   setBranchProtectedScope(SemaRef, OMPD_task, AStmt);
11054 
11055   return OMPTaskDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11056                                   AStmt, DSAStack->isCancelRegion());
11057 }
11058 
ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,SourceLocation EndLoc)11059 StmtResult SemaOpenMP::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
11060                                                      SourceLocation EndLoc) {
11061   return OMPTaskyieldDirective::Create(getASTContext(), StartLoc, EndLoc);
11062 }
11063 
ActOnOpenMPBarrierDirective(SourceLocation StartLoc,SourceLocation EndLoc)11064 StmtResult SemaOpenMP::ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
11065                                                    SourceLocation EndLoc) {
11066   return OMPBarrierDirective::Create(getASTContext(), StartLoc, EndLoc);
11067 }
11068 
ActOnOpenMPErrorDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc,bool InExContext)11069 StmtResult SemaOpenMP::ActOnOpenMPErrorDirective(ArrayRef<OMPClause *> Clauses,
11070                                                  SourceLocation StartLoc,
11071                                                  SourceLocation EndLoc,
11072                                                  bool InExContext) {
11073   const OMPAtClause *AtC =
11074       OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11075 
11076   if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11077     Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11078     return StmtError();
11079   }
11080 
11081   const OMPSeverityClause *SeverityC =
11082       OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11083   const OMPMessageClause *MessageC =
11084       OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11085   Expr *ME = MessageC ? MessageC->getMessageString() : nullptr;
11086 
11087   if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11088     if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11089       Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11090           << (ME ? cast<StringLiteral>(ME)->getString() : "WARNING");
11091     else
11092       Diag(StartLoc, diag::err_diagnose_if_succeeded)
11093           << (ME ? cast<StringLiteral>(ME)->getString() : "ERROR");
11094     if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11095       return StmtError();
11096   }
11097   return OMPErrorDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11098 }
11099 
11100 StmtResult
ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc)11101 SemaOpenMP::ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause *> Clauses,
11102                                          SourceLocation StartLoc,
11103                                          SourceLocation EndLoc) {
11104   const OMPNowaitClause *NowaitC =
11105       OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11106   bool HasDependC =
11107       !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11108            .empty();
11109   if (NowaitC && !HasDependC) {
11110     Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11111     return StmtError();
11112   }
11113 
11114   return OMPTaskwaitDirective::Create(getASTContext(), StartLoc, EndLoc,
11115                                       Clauses);
11116 }
11117 
11118 StmtResult
ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)11119 SemaOpenMP::ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
11120                                           Stmt *AStmt, SourceLocation StartLoc,
11121                                           SourceLocation EndLoc) {
11122   if (!AStmt)
11123     return StmtError();
11124 
11125   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11126 
11127   SemaRef.setFunctionHasBranchProtectedScope();
11128 
11129   return OMPTaskgroupDirective::Create(getASTContext(), StartLoc, EndLoc,
11130                                        Clauses, AStmt,
11131                                        DSAStack->getTaskgroupReductionRef());
11132 }
11133 
ActOnOpenMPFlushDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc)11134 StmtResult SemaOpenMP::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
11135                                                  SourceLocation StartLoc,
11136                                                  SourceLocation EndLoc) {
11137   OMPFlushClause *FC = nullptr;
11138   OMPClause *OrderClause = nullptr;
11139   for (OMPClause *C : Clauses) {
11140     if (C->getClauseKind() == OMPC_flush)
11141       FC = cast<OMPFlushClause>(C);
11142     else
11143       OrderClause = C;
11144   }
11145   unsigned OMPVersion = getLangOpts().OpenMP;
11146   OpenMPClauseKind MemOrderKind = OMPC_unknown;
11147   SourceLocation MemOrderLoc;
11148   for (const OMPClause *C : Clauses) {
11149     if (C->getClauseKind() == OMPC_acq_rel ||
11150         C->getClauseKind() == OMPC_acquire ||
11151         C->getClauseKind() == OMPC_release ||
11152         C->getClauseKind() == OMPC_seq_cst /*OpenMP 5.1*/) {
11153       if (MemOrderKind != OMPC_unknown) {
11154         Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11155             << getOpenMPDirectiveName(OMPD_flush, OMPVersion) << 1
11156             << SourceRange(C->getBeginLoc(), C->getEndLoc());
11157         Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11158             << getOpenMPClauseNameForDiag(MemOrderKind);
11159       } else {
11160         MemOrderKind = C->getClauseKind();
11161         MemOrderLoc = C->getBeginLoc();
11162       }
11163     }
11164   }
11165   if (FC && OrderClause) {
11166     Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11167         << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11168     Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11169         << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11170     return StmtError();
11171   }
11172   return OMPFlushDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11173 }
11174 
ActOnOpenMPDepobjDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc)11175 StmtResult SemaOpenMP::ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses,
11176                                                   SourceLocation StartLoc,
11177                                                   SourceLocation EndLoc) {
11178   if (Clauses.empty()) {
11179     Diag(StartLoc, diag::err_omp_depobj_expected);
11180     return StmtError();
11181   } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11182     Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11183     return StmtError();
11184   }
11185   // Only depobj expression and another single clause is allowed.
11186   if (Clauses.size() > 2) {
11187     Diag(Clauses[2]->getBeginLoc(),
11188          diag::err_omp_depobj_single_clause_expected);
11189     return StmtError();
11190   } else if (Clauses.size() < 1) {
11191     Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11192     return StmtError();
11193   }
11194   return OMPDepobjDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11195 }
11196 
ActOnOpenMPScanDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc)11197 StmtResult SemaOpenMP::ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses,
11198                                                 SourceLocation StartLoc,
11199                                                 SourceLocation EndLoc) {
11200   // Check that exactly one clause is specified.
11201   if (Clauses.size() != 1) {
11202     Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11203          diag::err_omp_scan_single_clause_expected);
11204     return StmtError();
11205   }
11206   // Check that scan directive is used in the scope of the OpenMP loop body.
11207   if (Scope *S = DSAStack->getCurScope()) {
11208     Scope *ParentS = S->getParent();
11209     if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11210         !ParentS->getBreakParent()->isOpenMPLoopScope()) {
11211       unsigned OMPVersion = getLangOpts().OpenMP;
11212       return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11213                        << getOpenMPDirectiveName(OMPD_scan, OMPVersion) << 5);
11214     }
11215   }
11216   // Check that only one instance of scan directives is used in the same outer
11217   // region.
11218   if (DSAStack->doesParentHasScanDirective()) {
11219     Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11220     Diag(DSAStack->getParentScanDirectiveLoc(),
11221          diag::note_omp_previous_directive)
11222         << "scan";
11223     return StmtError();
11224   }
11225   DSAStack->setParentHasScanDirective(StartLoc);
11226   return OMPScanDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11227 }
11228 
11229 StmtResult
ActOnOpenMPOrderedDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)11230 SemaOpenMP::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
11231                                         Stmt *AStmt, SourceLocation StartLoc,
11232                                         SourceLocation EndLoc) {
11233   const OMPClause *DependFound = nullptr;
11234   const OMPClause *DependSourceClause = nullptr;
11235   const OMPClause *DependSinkClause = nullptr;
11236   const OMPClause *DoacrossFound = nullptr;
11237   const OMPClause *DoacrossSourceClause = nullptr;
11238   const OMPClause *DoacrossSinkClause = nullptr;
11239   bool ErrorFound = false;
11240   const OMPThreadsClause *TC = nullptr;
11241   const OMPSIMDClause *SC = nullptr;
11242   for (const OMPClause *C : Clauses) {
11243     auto DOC = dyn_cast<OMPDoacrossClause>(C);
11244     auto DC = dyn_cast<OMPDependClause>(C);
11245     if (DC || DOC) {
11246       DependFound = DC ? C : nullptr;
11247       DoacrossFound = DOC ? C : nullptr;
11248       OMPDoacrossKind ODK;
11249       if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11250           (DOC && (ODK.isSource(DOC)))) {
11251         if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11252           unsigned OMPVersion = getLangOpts().OpenMP;
11253           Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11254               << getOpenMPDirectiveName(OMPD_ordered, OMPVersion)
11255               << getOpenMPClauseNameForDiag(DC ? OMPC_depend : OMPC_doacross)
11256               << 2;
11257           ErrorFound = true;
11258         } else {
11259           if (DC)
11260             DependSourceClause = C;
11261           else
11262             DoacrossSourceClause = C;
11263         }
11264         if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11265           Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11266               << (DC ? "depend" : "doacross") << 0;
11267           ErrorFound = true;
11268         }
11269       } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11270                  (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11271         if (DependSourceClause || DoacrossSourceClause) {
11272           Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11273               << (DC ? "depend" : "doacross") << 1;
11274           ErrorFound = true;
11275         }
11276         if (DC)
11277           DependSinkClause = C;
11278         else
11279           DoacrossSinkClause = C;
11280       }
11281     } else if (C->getClauseKind() == OMPC_threads) {
11282       TC = cast<OMPThreadsClause>(C);
11283     } else if (C->getClauseKind() == OMPC_simd) {
11284       SC = cast<OMPSIMDClause>(C);
11285     }
11286   }
11287   if (!ErrorFound && !SC &&
11288       isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11289     // OpenMP [2.8.1,simd Construct, Restrictions]
11290     // An ordered construct with the simd clause is the only OpenMP construct
11291     // that can appear in the simd region.
11292     Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11293         << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11294     ErrorFound = true;
11295   } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11296     SourceLocation Loc =
11297         DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11298     Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11299         << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend : OMPC_doacross)
11300         << getOpenMPClauseNameForDiag(TC ? TC->getClauseKind()
11301                                          : SC->getClauseKind());
11302     ErrorFound = true;
11303   } else if ((DependFound || DoacrossFound) &&
11304              !DSAStack->getParentOrderedRegionParam().first) {
11305     SourceLocation Loc =
11306         DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11307     Diag(Loc, diag::err_omp_ordered_directive_without_param)
11308         << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend
11309                                                   : OMPC_doacross);
11310     ErrorFound = true;
11311   } else if (TC || Clauses.empty()) {
11312     if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11313       SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11314       Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11315           << (TC != nullptr);
11316       Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11317       ErrorFound = true;
11318     }
11319   }
11320   if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11321     return StmtError();
11322 
11323   // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11324   // During execution of an iteration of a worksharing-loop or a loop nest
11325   // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11326   // must not execute more than one ordered region corresponding to an ordered
11327   // construct without a depend clause.
11328   if (!DependFound && !DoacrossFound) {
11329     if (DSAStack->doesParentHasOrderedDirective()) {
11330       Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11331       Diag(DSAStack->getParentOrderedDirectiveLoc(),
11332            diag::note_omp_previous_directive)
11333           << "ordered";
11334       return StmtError();
11335     }
11336     DSAStack->setParentHasOrderedDirective(StartLoc);
11337   }
11338 
11339   if (AStmt) {
11340     assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11341 
11342     SemaRef.setFunctionHasBranchProtectedScope();
11343   }
11344 
11345   return OMPOrderedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11346                                      AStmt);
11347 }
11348 
11349 namespace {
11350 /// Helper class for checking expression in 'omp atomic [update]'
11351 /// construct.
11352 class OpenMPAtomicUpdateChecker {
11353   /// Error results for atomic update expressions.
11354   enum ExprAnalysisErrorCode {
11355     /// A statement is not an expression statement.
11356     NotAnExpression,
11357     /// Expression is not builtin binary or unary operation.
11358     NotABinaryOrUnaryExpression,
11359     /// Unary operation is not post-/pre- increment/decrement operation.
11360     NotAnUnaryIncDecExpression,
11361     /// An expression is not of scalar type.
11362     NotAScalarType,
11363     /// A binary operation is not an assignment operation.
11364     NotAnAssignmentOp,
11365     /// RHS part of the binary operation is not a binary expression.
11366     NotABinaryExpression,
11367     /// RHS part is not additive/multiplicative/shift/bitwise binary
11368     /// expression.
11369     NotABinaryOperator,
11370     /// RHS binary operation does not have reference to the updated LHS
11371     /// part.
11372     NotAnUpdateExpression,
11373     /// An expression contains semantical error not related to
11374     /// 'omp atomic [update]'
11375     NotAValidExpression,
11376     /// No errors is found.
11377     NoError
11378   };
11379   /// Reference to Sema.
11380   Sema &SemaRef;
11381   /// A location for note diagnostics (when error is found).
11382   SourceLocation NoteLoc;
11383   /// 'x' lvalue part of the source atomic expression.
11384   Expr *X;
11385   /// 'expr' rvalue part of the source atomic expression.
11386   Expr *E;
11387   /// Helper expression of the form
11388   /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11389   /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11390   Expr *UpdateExpr;
11391   /// Is 'x' a LHS in a RHS part of full update expression. It is
11392   /// important for non-associative operations.
11393   bool IsXLHSInRHSPart;
11394   BinaryOperatorKind Op;
11395   SourceLocation OpLoc;
11396   /// true if the source expression is a postfix unary operation, false
11397   /// if it is a prefix unary operation.
11398   bool IsPostfixUpdate;
11399 
11400 public:
OpenMPAtomicUpdateChecker(Sema & SemaRef)11401   OpenMPAtomicUpdateChecker(Sema &SemaRef)
11402       : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11403         IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11404   /// Check specified statement that it is suitable for 'atomic update'
11405   /// constructs and extract 'x', 'expr' and Operation from the original
11406   /// expression. If DiagId and NoteId == 0, then only check is performed
11407   /// without error notification.
11408   /// \param DiagId Diagnostic which should be emitted if error is found.
11409   /// \param NoteId Diagnostic note for the main error message.
11410   /// \return true if statement is not an update expression, false otherwise.
11411   bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11412   /// Return the 'x' lvalue part of the source atomic expression.
getX() const11413   Expr *getX() const { return X; }
11414   /// Return the 'expr' rvalue part of the source atomic expression.
getExpr() const11415   Expr *getExpr() const { return E; }
11416   /// Return the update expression used in calculation of the updated
11417   /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11418   /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
getUpdateExpr() const11419   Expr *getUpdateExpr() const { return UpdateExpr; }
11420   /// Return true if 'x' is LHS in RHS part of full update expression,
11421   /// false otherwise.
isXLHSInRHSPart() const11422   bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11423 
11424   /// true if the source expression is a postfix unary operation, false
11425   /// if it is a prefix unary operation.
isPostfixUpdate() const11426   bool isPostfixUpdate() const { return IsPostfixUpdate; }
11427 
11428 private:
11429   bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11430                             unsigned NoteId = 0);
11431 };
11432 
checkBinaryOperation(BinaryOperator * AtomicBinOp,unsigned DiagId,unsigned NoteId)11433 bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11434     BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11435   ExprAnalysisErrorCode ErrorFound = NoError;
11436   SourceLocation ErrorLoc, NoteLoc;
11437   SourceRange ErrorRange, NoteRange;
11438   // Allowed constructs are:
11439   //  x = x binop expr;
11440   //  x = expr binop x;
11441   if (AtomicBinOp->getOpcode() == BO_Assign) {
11442     X = AtomicBinOp->getLHS();
11443     if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11444             AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11445       if (AtomicInnerBinOp->isMultiplicativeOp() ||
11446           AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11447           AtomicInnerBinOp->isBitwiseOp()) {
11448         Op = AtomicInnerBinOp->getOpcode();
11449         OpLoc = AtomicInnerBinOp->getOperatorLoc();
11450         Expr *LHS = AtomicInnerBinOp->getLHS();
11451         Expr *RHS = AtomicInnerBinOp->getRHS();
11452         llvm::FoldingSetNodeID XId, LHSId, RHSId;
11453         X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11454                                           /*Canonical=*/true);
11455         LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11456                                             /*Canonical=*/true);
11457         RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11458                                             /*Canonical=*/true);
11459         if (XId == LHSId) {
11460           E = RHS;
11461           IsXLHSInRHSPart = true;
11462         } else if (XId == RHSId) {
11463           E = LHS;
11464           IsXLHSInRHSPart = false;
11465         } else {
11466           ErrorLoc = AtomicInnerBinOp->getExprLoc();
11467           ErrorRange = AtomicInnerBinOp->getSourceRange();
11468           NoteLoc = X->getExprLoc();
11469           NoteRange = X->getSourceRange();
11470           ErrorFound = NotAnUpdateExpression;
11471         }
11472       } else {
11473         ErrorLoc = AtomicInnerBinOp->getExprLoc();
11474         ErrorRange = AtomicInnerBinOp->getSourceRange();
11475         NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11476         NoteRange = SourceRange(NoteLoc, NoteLoc);
11477         ErrorFound = NotABinaryOperator;
11478       }
11479     } else {
11480       NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11481       NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11482       ErrorFound = NotABinaryExpression;
11483     }
11484   } else {
11485     ErrorLoc = AtomicBinOp->getExprLoc();
11486     ErrorRange = AtomicBinOp->getSourceRange();
11487     NoteLoc = AtomicBinOp->getOperatorLoc();
11488     NoteRange = SourceRange(NoteLoc, NoteLoc);
11489     ErrorFound = NotAnAssignmentOp;
11490   }
11491   if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11492     SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11493     SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11494     return true;
11495   }
11496   if (SemaRef.CurContext->isDependentContext())
11497     E = X = UpdateExpr = nullptr;
11498   return ErrorFound != NoError;
11499 }
11500 
checkStatement(Stmt * S,unsigned DiagId,unsigned NoteId)11501 bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11502                                                unsigned NoteId) {
11503   ExprAnalysisErrorCode ErrorFound = NoError;
11504   SourceLocation ErrorLoc, NoteLoc;
11505   SourceRange ErrorRange, NoteRange;
11506   // Allowed constructs are:
11507   //  x++;
11508   //  x--;
11509   //  ++x;
11510   //  --x;
11511   //  x binop= expr;
11512   //  x = x binop expr;
11513   //  x = expr binop x;
11514   if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11515     AtomicBody = AtomicBody->IgnoreParenImpCasts();
11516     if (AtomicBody->getType()->isScalarType() ||
11517         AtomicBody->isInstantiationDependent()) {
11518       if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11519               AtomicBody->IgnoreParenImpCasts())) {
11520         // Check for Compound Assignment Operation
11521         Op = BinaryOperator::getOpForCompoundAssignment(
11522             AtomicCompAssignOp->getOpcode());
11523         OpLoc = AtomicCompAssignOp->getOperatorLoc();
11524         E = AtomicCompAssignOp->getRHS();
11525         X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11526         IsXLHSInRHSPart = true;
11527       } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11528                      AtomicBody->IgnoreParenImpCasts())) {
11529         // Check for Binary Operation
11530         if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11531           return true;
11532       } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11533                      AtomicBody->IgnoreParenImpCasts())) {
11534         // Check for Unary Operation
11535         if (AtomicUnaryOp->isIncrementDecrementOp()) {
11536           IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11537           Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11538           OpLoc = AtomicUnaryOp->getOperatorLoc();
11539           X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11540           E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11541           IsXLHSInRHSPart = true;
11542         } else {
11543           ErrorFound = NotAnUnaryIncDecExpression;
11544           ErrorLoc = AtomicUnaryOp->getExprLoc();
11545           ErrorRange = AtomicUnaryOp->getSourceRange();
11546           NoteLoc = AtomicUnaryOp->getOperatorLoc();
11547           NoteRange = SourceRange(NoteLoc, NoteLoc);
11548         }
11549       } else if (!AtomicBody->isInstantiationDependent()) {
11550         ErrorFound = NotABinaryOrUnaryExpression;
11551         NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11552         NoteRange = ErrorRange = AtomicBody->getSourceRange();
11553       } else if (AtomicBody->containsErrors()) {
11554         ErrorFound = NotAValidExpression;
11555         NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11556         NoteRange = ErrorRange = AtomicBody->getSourceRange();
11557       }
11558     } else {
11559       ErrorFound = NotAScalarType;
11560       NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11561       NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11562     }
11563   } else {
11564     ErrorFound = NotAnExpression;
11565     NoteLoc = ErrorLoc = S->getBeginLoc();
11566     NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11567   }
11568   if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11569     SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11570     SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11571     return true;
11572   }
11573   if (SemaRef.CurContext->isDependentContext())
11574     E = X = UpdateExpr = nullptr;
11575   if (ErrorFound == NoError && E && X) {
11576     // Build an update expression of form 'OpaqueValueExpr(x) binop
11577     // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11578     // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11579     auto *OVEX = new (SemaRef.getASTContext())
11580         OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11581     auto *OVEExpr = new (SemaRef.getASTContext())
11582         OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_PRValue);
11583     ExprResult Update =
11584         SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11585                                    IsXLHSInRHSPart ? OVEExpr : OVEX);
11586     if (Update.isInvalid())
11587       return true;
11588     Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11589                                                AssignmentAction::Casting);
11590     if (Update.isInvalid())
11591       return true;
11592     UpdateExpr = Update.get();
11593   }
11594   return ErrorFound != NoError;
11595 }
11596 
11597 /// Get the node id of the fixed point of an expression \a S.
getNodeId(ASTContext & Context,const Expr * S)11598 llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11599   llvm::FoldingSetNodeID Id;
11600   S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11601   return Id;
11602 }
11603 
11604 /// Check if two expressions are same.
checkIfTwoExprsAreSame(ASTContext & Context,const Expr * LHS,const Expr * RHS)11605 bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11606                             const Expr *RHS) {
11607   return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11608 }
11609 
11610 class OpenMPAtomicCompareChecker {
11611 public:
11612   /// All kinds of errors that can occur in `atomic compare`
11613   enum ErrorTy {
11614     /// Empty compound statement.
11615     NoStmt = 0,
11616     /// More than one statement in a compound statement.
11617     MoreThanOneStmt,
11618     /// Not an assignment binary operator.
11619     NotAnAssignment,
11620     /// Not a conditional operator.
11621     NotCondOp,
11622     /// Wrong false expr. According to the spec, 'x' should be at the false
11623     /// expression of a conditional expression.
11624     WrongFalseExpr,
11625     /// The condition of a conditional expression is not a binary operator.
11626     NotABinaryOp,
11627     /// Invalid binary operator (not <, >, or ==).
11628     InvalidBinaryOp,
11629     /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11630     InvalidComparison,
11631     /// X is not a lvalue.
11632     XNotLValue,
11633     /// Not a scalar.
11634     NotScalar,
11635     /// Not an integer.
11636     NotInteger,
11637     /// 'else' statement is not expected.
11638     UnexpectedElse,
11639     /// Not an equality operator.
11640     NotEQ,
11641     /// Invalid assignment (not v == x).
11642     InvalidAssignment,
11643     /// Not if statement
11644     NotIfStmt,
11645     /// More than two statements in a compound statement.
11646     MoreThanTwoStmts,
11647     /// Not a compound statement.
11648     NotCompoundStmt,
11649     /// No else statement.
11650     NoElse,
11651     /// Not 'if (r)'.
11652     InvalidCondition,
11653     /// No error.
11654     NoError,
11655   };
11656 
11657   struct ErrorInfoTy {
11658     ErrorTy Error;
11659     SourceLocation ErrorLoc;
11660     SourceRange ErrorRange;
11661     SourceLocation NoteLoc;
11662     SourceRange NoteRange;
11663   };
11664 
OpenMPAtomicCompareChecker(Sema & S)11665   OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11666 
11667   /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11668   bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11669 
getX() const11670   Expr *getX() const { return X; }
getE() const11671   Expr *getE() const { return E; }
getD() const11672   Expr *getD() const { return D; }
getCond() const11673   Expr *getCond() const { return C; }
isXBinopExpr() const11674   bool isXBinopExpr() const { return IsXBinopExpr; }
11675 
11676 protected:
11677   /// Reference to ASTContext
11678   ASTContext &ContextRef;
11679   /// 'x' lvalue part of the source atomic expression.
11680   Expr *X = nullptr;
11681   /// 'expr' or 'e' rvalue part of the source atomic expression.
11682   Expr *E = nullptr;
11683   /// 'd' rvalue part of the source atomic expression.
11684   Expr *D = nullptr;
11685   /// 'cond' part of the source atomic expression. It is in one of the following
11686   /// forms:
11687   /// expr ordop x
11688   /// x ordop expr
11689   /// x == e
11690   /// e == x
11691   Expr *C = nullptr;
11692   /// True if the cond expr is in the form of 'x ordop expr'.
11693   bool IsXBinopExpr = true;
11694 
11695   /// Check if it is a valid conditional update statement (cond-update-stmt).
11696   bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11697 
11698   /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11699   bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11700 
11701   /// Check if all captured values have right type.
11702   bool checkType(ErrorInfoTy &ErrorInfo) const;
11703 
CheckValue(const Expr * E,ErrorInfoTy & ErrorInfo,bool ShouldBeLValue,bool ShouldBeInteger=false)11704   static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11705                          bool ShouldBeLValue, bool ShouldBeInteger = false) {
11706     if (E->isInstantiationDependent())
11707       return true;
11708 
11709     if (ShouldBeLValue && !E->isLValue()) {
11710       ErrorInfo.Error = ErrorTy::XNotLValue;
11711       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11712       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11713       return false;
11714     }
11715 
11716     QualType QTy = E->getType();
11717     if (!QTy->isScalarType()) {
11718       ErrorInfo.Error = ErrorTy::NotScalar;
11719       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11720       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11721       return false;
11722     }
11723     if (ShouldBeInteger && !QTy->isIntegerType()) {
11724       ErrorInfo.Error = ErrorTy::NotInteger;
11725       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11726       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11727       return false;
11728     }
11729 
11730     return true;
11731   }
11732 };
11733 
checkCondUpdateStmt(IfStmt * S,ErrorInfoTy & ErrorInfo)11734 bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11735                                                      ErrorInfoTy &ErrorInfo) {
11736   auto *Then = S->getThen();
11737   if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11738     if (CS->body_empty()) {
11739       ErrorInfo.Error = ErrorTy::NoStmt;
11740       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11741       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11742       return false;
11743     }
11744     if (CS->size() > 1) {
11745       ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11746       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11747       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11748       return false;
11749     }
11750     Then = CS->body_front();
11751   }
11752 
11753   auto *BO = dyn_cast<BinaryOperator>(Then);
11754   if (!BO) {
11755     ErrorInfo.Error = ErrorTy::NotAnAssignment;
11756     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11757     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11758     return false;
11759   }
11760   if (BO->getOpcode() != BO_Assign) {
11761     ErrorInfo.Error = ErrorTy::NotAnAssignment;
11762     ErrorInfo.ErrorLoc = BO->getExprLoc();
11763     ErrorInfo.NoteLoc = BO->getOperatorLoc();
11764     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11765     return false;
11766   }
11767 
11768   X = BO->getLHS();
11769 
11770   auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11771   auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
11772   Expr *LHS = nullptr;
11773   Expr *RHS = nullptr;
11774   if (Cond) {
11775     LHS = Cond->getLHS();
11776     RHS = Cond->getRHS();
11777   } else if (Call) {
11778     LHS = Call->getArg(0);
11779     RHS = Call->getArg(1);
11780   } else {
11781     ErrorInfo.Error = ErrorTy::NotABinaryOp;
11782     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11783     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11784     return false;
11785   }
11786 
11787   if ((Cond && Cond->getOpcode() == BO_EQ) ||
11788       (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
11789     C = S->getCond();
11790     D = BO->getRHS();
11791     if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
11792       E = RHS;
11793     } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
11794       E = LHS;
11795     } else {
11796       ErrorInfo.Error = ErrorTy::InvalidComparison;
11797       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11798       ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11799           S->getCond()->getSourceRange();
11800       return false;
11801     }
11802   } else if ((Cond &&
11803               (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
11804              (Call &&
11805               (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
11806                Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
11807     E = BO->getRHS();
11808     if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
11809         checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
11810       C = S->getCond();
11811     } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
11812                checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
11813       C = S->getCond();
11814       IsXBinopExpr = false;
11815     } else {
11816       ErrorInfo.Error = ErrorTy::InvalidComparison;
11817       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11818       ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11819           S->getCond()->getSourceRange();
11820       return false;
11821     }
11822   } else {
11823     ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11824     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11825     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11826     return false;
11827   }
11828 
11829   if (S->getElse()) {
11830     ErrorInfo.Error = ErrorTy::UnexpectedElse;
11831     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
11832     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
11833     return false;
11834   }
11835 
11836   return true;
11837 }
11838 
checkCondExprStmt(Stmt * S,ErrorInfoTy & ErrorInfo)11839 bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
11840                                                    ErrorInfoTy &ErrorInfo) {
11841   auto *BO = dyn_cast<BinaryOperator>(S);
11842   if (!BO) {
11843     ErrorInfo.Error = ErrorTy::NotAnAssignment;
11844     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11845     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11846     return false;
11847   }
11848   if (BO->getOpcode() != BO_Assign) {
11849     ErrorInfo.Error = ErrorTy::NotAnAssignment;
11850     ErrorInfo.ErrorLoc = BO->getExprLoc();
11851     ErrorInfo.NoteLoc = BO->getOperatorLoc();
11852     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11853     return false;
11854   }
11855 
11856   X = BO->getLHS();
11857 
11858   auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
11859   if (!CO) {
11860     ErrorInfo.Error = ErrorTy::NotCondOp;
11861     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
11862     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
11863     return false;
11864   }
11865 
11866   if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
11867     ErrorInfo.Error = ErrorTy::WrongFalseExpr;
11868     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
11869     ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11870         CO->getFalseExpr()->getSourceRange();
11871     return false;
11872   }
11873 
11874   auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
11875   auto *Call = dyn_cast<CXXOperatorCallExpr>(CO->getCond());
11876   Expr *LHS = nullptr;
11877   Expr *RHS = nullptr;
11878   if (Cond) {
11879     LHS = Cond->getLHS();
11880     RHS = Cond->getRHS();
11881   } else if (Call) {
11882     LHS = Call->getArg(0);
11883     RHS = Call->getArg(1);
11884   } else {
11885     ErrorInfo.Error = ErrorTy::NotABinaryOp;
11886     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11887     ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11888         CO->getCond()->getSourceRange();
11889     return false;
11890   }
11891 
11892   if ((Cond && Cond->getOpcode() == BO_EQ) ||
11893       (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
11894     C = CO->getCond();
11895     D = CO->getTrueExpr();
11896     if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
11897       E = RHS;
11898     } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
11899       E = LHS;
11900     } else {
11901       ErrorInfo.Error = ErrorTy::InvalidComparison;
11902       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11903       ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11904           CO->getCond()->getSourceRange();
11905       return false;
11906     }
11907   } else if ((Cond &&
11908               (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
11909              (Call &&
11910               (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
11911                Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
11912 
11913     E = CO->getTrueExpr();
11914     if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
11915         checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
11916       C = CO->getCond();
11917     } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
11918                checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
11919       C = CO->getCond();
11920       IsXBinopExpr = false;
11921     } else {
11922       ErrorInfo.Error = ErrorTy::InvalidComparison;
11923       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11924       ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11925           CO->getCond()->getSourceRange();
11926       return false;
11927     }
11928   } else {
11929     ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11930     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11931     ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11932         CO->getCond()->getSourceRange();
11933     return false;
11934   }
11935 
11936   return true;
11937 }
11938 
checkType(ErrorInfoTy & ErrorInfo) const11939 bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
11940   // 'x' and 'e' cannot be nullptr
11941   assert(X && E && "X and E cannot be nullptr");
11942 
11943   if (!CheckValue(X, ErrorInfo, true))
11944     return false;
11945 
11946   if (!CheckValue(E, ErrorInfo, false))
11947     return false;
11948 
11949   if (D && !CheckValue(D, ErrorInfo, false))
11950     return false;
11951 
11952   return true;
11953 }
11954 
checkStmt(Stmt * S,OpenMPAtomicCompareChecker::ErrorInfoTy & ErrorInfo)11955 bool OpenMPAtomicCompareChecker::checkStmt(
11956     Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
11957   auto *CS = dyn_cast<CompoundStmt>(S);
11958   if (CS) {
11959     if (CS->body_empty()) {
11960       ErrorInfo.Error = ErrorTy::NoStmt;
11961       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11962       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11963       return false;
11964     }
11965 
11966     if (CS->size() != 1) {
11967       ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11968       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11969       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11970       return false;
11971     }
11972     S = CS->body_front();
11973   }
11974 
11975   auto Res = false;
11976 
11977   if (auto *IS = dyn_cast<IfStmt>(S)) {
11978     // Check if the statement is in one of the following forms
11979     // (cond-update-stmt):
11980     // if (expr ordop x) { x = expr; }
11981     // if (x ordop expr) { x = expr; }
11982     // if (x == e) { x = d; }
11983     Res = checkCondUpdateStmt(IS, ErrorInfo);
11984   } else {
11985     // Check if the statement is in one of the following forms (cond-expr-stmt):
11986     // x = expr ordop x ? expr : x;
11987     // x = x ordop expr ? expr : x;
11988     // x = x == e ? d : x;
11989     Res = checkCondExprStmt(S, ErrorInfo);
11990   }
11991 
11992   if (!Res)
11993     return false;
11994 
11995   return checkType(ErrorInfo);
11996 }
11997 
11998 class OpenMPAtomicCompareCaptureChecker final
11999     : public OpenMPAtomicCompareChecker {
12000 public:
OpenMPAtomicCompareCaptureChecker(Sema & S)12001   OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12002 
getV() const12003   Expr *getV() const { return V; }
getR() const12004   Expr *getR() const { return R; }
isFailOnly() const12005   bool isFailOnly() const { return IsFailOnly; }
isPostfixUpdate() const12006   bool isPostfixUpdate() const { return IsPostfixUpdate; }
12007 
12008   /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12009   bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12010 
12011 private:
12012   bool checkType(ErrorInfoTy &ErrorInfo);
12013 
12014   // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12015   // form of 'conditional-update-capture-atomic' structured block on the v5.2
12016   // spec p.p. 82:
12017   // (1) { v = x; cond-update-stmt }
12018   // (2) { cond-update-stmt v = x; }
12019   // (3) if(x == e) { x = d; } else { v = x; }
12020   // (4) { r = x == e; if(r) { x = d; } }
12021   // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12022 
12023   /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12024   bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12025 
12026   /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12027   /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12028   bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12029 
12030   /// 'v' lvalue part of the source atomic expression.
12031   Expr *V = nullptr;
12032   /// 'r' lvalue part of the source atomic expression.
12033   Expr *R = nullptr;
12034   /// If 'v' is only updated when the comparison fails.
12035   bool IsFailOnly = false;
12036   /// If original value of 'x' must be stored in 'v', not an updated one.
12037   bool IsPostfixUpdate = false;
12038 };
12039 
checkType(ErrorInfoTy & ErrorInfo)12040 bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12041   if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12042     return false;
12043 
12044   if (V && !CheckValue(V, ErrorInfo, true))
12045     return false;
12046 
12047   if (R && !CheckValue(R, ErrorInfo, true, true))
12048     return false;
12049 
12050   return true;
12051 }
12052 
checkForm3(IfStmt * S,ErrorInfoTy & ErrorInfo)12053 bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12054                                                    ErrorInfoTy &ErrorInfo) {
12055   IsFailOnly = true;
12056 
12057   auto *Then = S->getThen();
12058   if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12059     if (CS->body_empty()) {
12060       ErrorInfo.Error = ErrorTy::NoStmt;
12061       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12062       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12063       return false;
12064     }
12065     if (CS->size() > 1) {
12066       ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12067       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12068       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12069       return false;
12070     }
12071     Then = CS->body_front();
12072   }
12073 
12074   auto *BO = dyn_cast<BinaryOperator>(Then);
12075   if (!BO) {
12076     ErrorInfo.Error = ErrorTy::NotAnAssignment;
12077     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12078     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12079     return false;
12080   }
12081   if (BO->getOpcode() != BO_Assign) {
12082     ErrorInfo.Error = ErrorTy::NotAnAssignment;
12083     ErrorInfo.ErrorLoc = BO->getExprLoc();
12084     ErrorInfo.NoteLoc = BO->getOperatorLoc();
12085     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12086     return false;
12087   }
12088 
12089   X = BO->getLHS();
12090   D = BO->getRHS();
12091 
12092   auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12093   auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
12094   Expr *LHS = nullptr;
12095   Expr *RHS = nullptr;
12096   if (Cond) {
12097     LHS = Cond->getLHS();
12098     RHS = Cond->getRHS();
12099   } else if (Call) {
12100     LHS = Call->getArg(0);
12101     RHS = Call->getArg(1);
12102   } else {
12103     ErrorInfo.Error = ErrorTy::NotABinaryOp;
12104     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12105     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12106     return false;
12107   }
12108   if ((Cond && Cond->getOpcode() != BO_EQ) ||
12109       (Call && Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12110     ErrorInfo.Error = ErrorTy::NotEQ;
12111     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12112     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12113     return false;
12114   }
12115 
12116   if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12117     E = RHS;
12118   } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12119     E = LHS;
12120   } else {
12121     ErrorInfo.Error = ErrorTy::InvalidComparison;
12122     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12123     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12124     return false;
12125   }
12126 
12127   C = S->getCond();
12128 
12129   if (!S->getElse()) {
12130     ErrorInfo.Error = ErrorTy::NoElse;
12131     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12132     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12133     return false;
12134   }
12135 
12136   auto *Else = S->getElse();
12137   if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12138     if (CS->body_empty()) {
12139       ErrorInfo.Error = ErrorTy::NoStmt;
12140       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12141       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12142       return false;
12143     }
12144     if (CS->size() > 1) {
12145       ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12146       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12147       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12148       return false;
12149     }
12150     Else = CS->body_front();
12151   }
12152 
12153   auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12154   if (!ElseBO) {
12155     ErrorInfo.Error = ErrorTy::NotAnAssignment;
12156     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12157     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12158     return false;
12159   }
12160   if (ElseBO->getOpcode() != BO_Assign) {
12161     ErrorInfo.Error = ErrorTy::NotAnAssignment;
12162     ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12163     ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12164     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12165     return false;
12166   }
12167 
12168   if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12169     ErrorInfo.Error = ErrorTy::InvalidAssignment;
12170     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12171     ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12172         ElseBO->getRHS()->getSourceRange();
12173     return false;
12174   }
12175 
12176   V = ElseBO->getLHS();
12177 
12178   return checkType(ErrorInfo);
12179 }
12180 
checkForm45(Stmt * S,ErrorInfoTy & ErrorInfo)12181 bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12182                                                     ErrorInfoTy &ErrorInfo) {
12183   // We don't check here as they should be already done before call this
12184   // function.
12185   auto *CS = cast<CompoundStmt>(S);
12186   assert(CS->size() == 2 && "CompoundStmt size is not expected");
12187   auto *S1 = cast<BinaryOperator>(CS->body_front());
12188   auto *S2 = cast<IfStmt>(CS->body_back());
12189   assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12190 
12191   if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12192     ErrorInfo.Error = ErrorTy::InvalidCondition;
12193     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12194     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12195     return false;
12196   }
12197 
12198   R = S1->getLHS();
12199 
12200   auto *Then = S2->getThen();
12201   if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12202     if (ThenCS->body_empty()) {
12203       ErrorInfo.Error = ErrorTy::NoStmt;
12204       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12205       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12206       return false;
12207     }
12208     if (ThenCS->size() > 1) {
12209       ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12210       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12211       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12212       return false;
12213     }
12214     Then = ThenCS->body_front();
12215   }
12216 
12217   auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12218   if (!ThenBO) {
12219     ErrorInfo.Error = ErrorTy::NotAnAssignment;
12220     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12221     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12222     return false;
12223   }
12224   if (ThenBO->getOpcode() != BO_Assign) {
12225     ErrorInfo.Error = ErrorTy::NotAnAssignment;
12226     ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12227     ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12228     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12229     return false;
12230   }
12231 
12232   X = ThenBO->getLHS();
12233   D = ThenBO->getRHS();
12234 
12235   auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12236   if (BO->getOpcode() != BO_EQ) {
12237     ErrorInfo.Error = ErrorTy::NotEQ;
12238     ErrorInfo.ErrorLoc = BO->getExprLoc();
12239     ErrorInfo.NoteLoc = BO->getOperatorLoc();
12240     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12241     return false;
12242   }
12243 
12244   C = BO;
12245 
12246   if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12247     E = BO->getRHS();
12248   } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12249     E = BO->getLHS();
12250   } else {
12251     ErrorInfo.Error = ErrorTy::InvalidComparison;
12252     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12253     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12254     return false;
12255   }
12256 
12257   if (S2->getElse()) {
12258     IsFailOnly = true;
12259 
12260     auto *Else = S2->getElse();
12261     if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12262       if (ElseCS->body_empty()) {
12263         ErrorInfo.Error = ErrorTy::NoStmt;
12264         ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12265         ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12266         return false;
12267       }
12268       if (ElseCS->size() > 1) {
12269         ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12270         ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12271         ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12272         return false;
12273       }
12274       Else = ElseCS->body_front();
12275     }
12276 
12277     auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12278     if (!ElseBO) {
12279       ErrorInfo.Error = ErrorTy::NotAnAssignment;
12280       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12281       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12282       return false;
12283     }
12284     if (ElseBO->getOpcode() != BO_Assign) {
12285       ErrorInfo.Error = ErrorTy::NotAnAssignment;
12286       ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12287       ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12288       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12289       return false;
12290     }
12291     if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12292       ErrorInfo.Error = ErrorTy::InvalidAssignment;
12293       ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12294       ErrorInfo.NoteLoc = X->getExprLoc();
12295       ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12296       ErrorInfo.NoteRange = X->getSourceRange();
12297       return false;
12298     }
12299 
12300     V = ElseBO->getLHS();
12301   }
12302 
12303   return checkType(ErrorInfo);
12304 }
12305 
checkStmt(Stmt * S,ErrorInfoTy & ErrorInfo)12306 bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12307                                                   ErrorInfoTy &ErrorInfo) {
12308   // if(x == e) { x = d; } else { v = x; }
12309   if (auto *IS = dyn_cast<IfStmt>(S))
12310     return checkForm3(IS, ErrorInfo);
12311 
12312   auto *CS = dyn_cast<CompoundStmt>(S);
12313   if (!CS) {
12314     ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12315     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12316     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12317     return false;
12318   }
12319   if (CS->body_empty()) {
12320     ErrorInfo.Error = ErrorTy::NoStmt;
12321     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12322     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12323     return false;
12324   }
12325 
12326   // { if(x == e) { x = d; } else { v = x; } }
12327   if (CS->size() == 1) {
12328     auto *IS = dyn_cast<IfStmt>(CS->body_front());
12329     if (!IS) {
12330       ErrorInfo.Error = ErrorTy::NotIfStmt;
12331       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12332       ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12333           CS->body_front()->getSourceRange();
12334       return false;
12335     }
12336 
12337     return checkForm3(IS, ErrorInfo);
12338   } else if (CS->size() == 2) {
12339     auto *S1 = CS->body_front();
12340     auto *S2 = CS->body_back();
12341 
12342     Stmt *UpdateStmt = nullptr;
12343     Stmt *CondUpdateStmt = nullptr;
12344     Stmt *CondExprStmt = nullptr;
12345 
12346     if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12347       // It could be one of the following cases:
12348       // { v = x; cond-update-stmt }
12349       // { v = x; cond-expr-stmt }
12350       // { cond-expr-stmt; v = x; }
12351       // form 45
12352       if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12353           isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12354         // check if form 45
12355         if (isa<IfStmt>(S2))
12356           return checkForm45(CS, ErrorInfo);
12357         // { cond-expr-stmt; v = x; }
12358         CondExprStmt = S1;
12359         UpdateStmt = S2;
12360       } else {
12361         IsPostfixUpdate = true;
12362         UpdateStmt = S1;
12363         if (isa<IfStmt>(S2)) {
12364           // { v = x; cond-update-stmt }
12365           CondUpdateStmt = S2;
12366         } else {
12367           // { v = x; cond-expr-stmt }
12368           CondExprStmt = S2;
12369         }
12370       }
12371     } else {
12372       // { cond-update-stmt v = x; }
12373       UpdateStmt = S2;
12374       CondUpdateStmt = S1;
12375     }
12376 
12377     auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12378       auto *IS = dyn_cast<IfStmt>(CUS);
12379       if (!IS) {
12380         ErrorInfo.Error = ErrorTy::NotIfStmt;
12381         ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12382         ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12383         return false;
12384       }
12385 
12386       return checkCondUpdateStmt(IS, ErrorInfo);
12387     };
12388 
12389     // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12390     auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12391       auto *BO = dyn_cast<BinaryOperator>(US);
12392       if (!BO) {
12393         ErrorInfo.Error = ErrorTy::NotAnAssignment;
12394         ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12395         ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12396         return false;
12397       }
12398       if (BO->getOpcode() != BO_Assign) {
12399         ErrorInfo.Error = ErrorTy::NotAnAssignment;
12400         ErrorInfo.ErrorLoc = BO->getExprLoc();
12401         ErrorInfo.NoteLoc = BO->getOperatorLoc();
12402         ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12403         return false;
12404       }
12405       if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12406         ErrorInfo.Error = ErrorTy::InvalidAssignment;
12407         ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12408         ErrorInfo.NoteLoc = this->X->getExprLoc();
12409         ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12410         ErrorInfo.NoteRange = this->X->getSourceRange();
12411         return false;
12412       }
12413 
12414       this->V = BO->getLHS();
12415 
12416       return true;
12417     };
12418 
12419     if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12420       return false;
12421     if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12422       return false;
12423     if (!CheckUpdateStmt(UpdateStmt))
12424       return false;
12425   } else {
12426     ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12427     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12428     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12429     return false;
12430   }
12431 
12432   return checkType(ErrorInfo);
12433 }
12434 } // namespace
12435 
ActOnOpenMPAtomicDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)12436 StmtResult SemaOpenMP::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
12437                                                   Stmt *AStmt,
12438                                                   SourceLocation StartLoc,
12439                                                   SourceLocation EndLoc) {
12440   ASTContext &Context = getASTContext();
12441   unsigned OMPVersion = getLangOpts().OpenMP;
12442   // Register location of the first atomic directive.
12443   DSAStack->addAtomicDirectiveLoc(StartLoc);
12444   if (!AStmt)
12445     return StmtError();
12446 
12447   // 1.2.2 OpenMP Language Terminology
12448   // Structured block - An executable statement with a single entry at the
12449   // top and a single exit at the bottom.
12450   // The point of exit cannot be a branch out of the structured block.
12451   // longjmp() and throw() must not violate the entry/exit criteria.
12452   OpenMPClauseKind AtomicKind = OMPC_unknown;
12453   SourceLocation AtomicKindLoc;
12454   OpenMPClauseKind MemOrderKind = OMPC_unknown;
12455   SourceLocation MemOrderLoc;
12456   bool MutexClauseEncountered = false;
12457   llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12458   for (const OMPClause *C : Clauses) {
12459     switch (C->getClauseKind()) {
12460     case OMPC_read:
12461     case OMPC_write:
12462     case OMPC_update:
12463       MutexClauseEncountered = true;
12464       [[fallthrough]];
12465     case OMPC_capture:
12466     case OMPC_compare: {
12467       if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12468         Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12469             << SourceRange(C->getBeginLoc(), C->getEndLoc());
12470         Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12471             << getOpenMPClauseNameForDiag(AtomicKind);
12472       } else {
12473         AtomicKind = C->getClauseKind();
12474         AtomicKindLoc = C->getBeginLoc();
12475         if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12476           Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12477               << SourceRange(C->getBeginLoc(), C->getEndLoc());
12478           Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12479               << getOpenMPClauseNameForDiag(AtomicKind);
12480         }
12481       }
12482       break;
12483     }
12484     case OMPC_weak:
12485     case OMPC_fail: {
12486       if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12487         Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12488             << getOpenMPClauseNameForDiag(C->getClauseKind())
12489             << SourceRange(C->getBeginLoc(), C->getEndLoc());
12490         return StmtError();
12491       }
12492       break;
12493     }
12494     case OMPC_seq_cst:
12495     case OMPC_acq_rel:
12496     case OMPC_acquire:
12497     case OMPC_release:
12498     case OMPC_relaxed: {
12499       if (MemOrderKind != OMPC_unknown) {
12500         Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12501             << getOpenMPDirectiveName(OMPD_atomic, OMPVersion) << 0
12502             << SourceRange(C->getBeginLoc(), C->getEndLoc());
12503         Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12504             << getOpenMPClauseNameForDiag(MemOrderKind);
12505       } else {
12506         MemOrderKind = C->getClauseKind();
12507         MemOrderLoc = C->getBeginLoc();
12508       }
12509       break;
12510     }
12511     // The following clauses are allowed, but we don't need to do anything here.
12512     case OMPC_hint:
12513       break;
12514     default:
12515       llvm_unreachable("unknown clause is encountered");
12516     }
12517   }
12518   bool IsCompareCapture = false;
12519   if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12520       EncounteredAtomicKinds.contains(OMPC_capture)) {
12521     IsCompareCapture = true;
12522     AtomicKind = OMPC_compare;
12523   }
12524   // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12525   // If atomic-clause is read then memory-order-clause must not be acq_rel or
12526   // release.
12527   // If atomic-clause is write then memory-order-clause must not be acq_rel or
12528   // acquire.
12529   // If atomic-clause is update or not present then memory-order-clause must not
12530   // be acq_rel or acquire.
12531   if ((AtomicKind == OMPC_read &&
12532        (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12533       ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12534         AtomicKind == OMPC_unknown) &&
12535        (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12536     SourceLocation Loc = AtomicKindLoc;
12537     if (AtomicKind == OMPC_unknown)
12538       Loc = StartLoc;
12539     Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12540         << getOpenMPClauseNameForDiag(AtomicKind)
12541         << (AtomicKind == OMPC_unknown ? 1 : 0)
12542         << getOpenMPClauseNameForDiag(MemOrderKind);
12543     Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12544         << getOpenMPClauseNameForDiag(MemOrderKind);
12545   }
12546 
12547   Stmt *Body = AStmt;
12548   if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12549     Body = EWC->getSubExpr();
12550 
12551   Expr *X = nullptr;
12552   Expr *V = nullptr;
12553   Expr *E = nullptr;
12554   Expr *UE = nullptr;
12555   Expr *D = nullptr;
12556   Expr *CE = nullptr;
12557   Expr *R = nullptr;
12558   bool IsXLHSInRHSPart = false;
12559   bool IsPostfixUpdate = false;
12560   bool IsFailOnly = false;
12561   // OpenMP [2.12.6, atomic Construct]
12562   // In the next expressions:
12563   // * x and v (as applicable) are both l-value expressions with scalar type.
12564   // * During the execution of an atomic region, multiple syntactic
12565   // occurrences of x must designate the same storage location.
12566   // * Neither of v and expr (as applicable) may access the storage location
12567   // designated by x.
12568   // * Neither of x and expr (as applicable) may access the storage location
12569   // designated by v.
12570   // * expr is an expression with scalar type.
12571   // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12572   // * binop, binop=, ++, and -- are not overloaded operators.
12573   // * The expression x binop expr must be numerically equivalent to x binop
12574   // (expr). This requirement is satisfied if the operators in expr have
12575   // precedence greater than binop, or by using parentheses around expr or
12576   // subexpressions of expr.
12577   // * The expression expr binop x must be numerically equivalent to (expr)
12578   // binop x. This requirement is satisfied if the operators in expr have
12579   // precedence equal to or greater than binop, or by using parentheses around
12580   // expr or subexpressions of expr.
12581   // * For forms that allow multiple occurrences of x, the number of times
12582   // that x is evaluated is unspecified.
12583   if (AtomicKind == OMPC_read) {
12584     enum {
12585       NotAnExpression,
12586       NotAnAssignmentOp,
12587       NotAScalarType,
12588       NotAnLValue,
12589       NoError
12590     } ErrorFound = NoError;
12591     SourceLocation ErrorLoc, NoteLoc;
12592     SourceRange ErrorRange, NoteRange;
12593     // If clause is read:
12594     //  v = x;
12595     if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12596       const auto *AtomicBinOp =
12597           dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12598       if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12599         X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12600         V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12601         if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12602             (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12603           if (!X->isLValue() || !V->isLValue()) {
12604             const Expr *NotLValueExpr = X->isLValue() ? V : X;
12605             ErrorFound = NotAnLValue;
12606             ErrorLoc = AtomicBinOp->getExprLoc();
12607             ErrorRange = AtomicBinOp->getSourceRange();
12608             NoteLoc = NotLValueExpr->getExprLoc();
12609             NoteRange = NotLValueExpr->getSourceRange();
12610           }
12611         } else if (!X->isInstantiationDependent() ||
12612                    !V->isInstantiationDependent()) {
12613           const Expr *NotScalarExpr =
12614               (X->isInstantiationDependent() || X->getType()->isScalarType())
12615                   ? V
12616                   : X;
12617           ErrorFound = NotAScalarType;
12618           ErrorLoc = AtomicBinOp->getExprLoc();
12619           ErrorRange = AtomicBinOp->getSourceRange();
12620           NoteLoc = NotScalarExpr->getExprLoc();
12621           NoteRange = NotScalarExpr->getSourceRange();
12622         }
12623       } else if (!AtomicBody->isInstantiationDependent()) {
12624         ErrorFound = NotAnAssignmentOp;
12625         ErrorLoc = AtomicBody->getExprLoc();
12626         ErrorRange = AtomicBody->getSourceRange();
12627         NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12628                               : AtomicBody->getExprLoc();
12629         NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12630                                 : AtomicBody->getSourceRange();
12631       }
12632     } else {
12633       ErrorFound = NotAnExpression;
12634       NoteLoc = ErrorLoc = Body->getBeginLoc();
12635       NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12636     }
12637     if (ErrorFound != NoError) {
12638       Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12639           << ErrorRange;
12640       Diag(NoteLoc, diag::note_omp_atomic_read_write)
12641           << ErrorFound << NoteRange;
12642       return StmtError();
12643     }
12644     if (SemaRef.CurContext->isDependentContext())
12645       V = X = nullptr;
12646   } else if (AtomicKind == OMPC_write) {
12647     enum {
12648       NotAnExpression,
12649       NotAnAssignmentOp,
12650       NotAScalarType,
12651       NotAnLValue,
12652       NoError
12653     } ErrorFound = NoError;
12654     SourceLocation ErrorLoc, NoteLoc;
12655     SourceRange ErrorRange, NoteRange;
12656     // If clause is write:
12657     //  x = expr;
12658     if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12659       const auto *AtomicBinOp =
12660           dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12661       if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12662         X = AtomicBinOp->getLHS();
12663         E = AtomicBinOp->getRHS();
12664         if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12665             (E->isInstantiationDependent() || E->getType()->isScalarType())) {
12666           if (!X->isLValue()) {
12667             ErrorFound = NotAnLValue;
12668             ErrorLoc = AtomicBinOp->getExprLoc();
12669             ErrorRange = AtomicBinOp->getSourceRange();
12670             NoteLoc = X->getExprLoc();
12671             NoteRange = X->getSourceRange();
12672           }
12673         } else if (!X->isInstantiationDependent() ||
12674                    !E->isInstantiationDependent()) {
12675           const Expr *NotScalarExpr =
12676               (X->isInstantiationDependent() || X->getType()->isScalarType())
12677                   ? E
12678                   : X;
12679           ErrorFound = NotAScalarType;
12680           ErrorLoc = AtomicBinOp->getExprLoc();
12681           ErrorRange = AtomicBinOp->getSourceRange();
12682           NoteLoc = NotScalarExpr->getExprLoc();
12683           NoteRange = NotScalarExpr->getSourceRange();
12684         }
12685       } else if (!AtomicBody->isInstantiationDependent()) {
12686         ErrorFound = NotAnAssignmentOp;
12687         ErrorLoc = AtomicBody->getExprLoc();
12688         ErrorRange = AtomicBody->getSourceRange();
12689         NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12690                               : AtomicBody->getExprLoc();
12691         NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12692                                 : AtomicBody->getSourceRange();
12693       }
12694     } else {
12695       ErrorFound = NotAnExpression;
12696       NoteLoc = ErrorLoc = Body->getBeginLoc();
12697       NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12698     }
12699     if (ErrorFound != NoError) {
12700       Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12701           << ErrorRange;
12702       Diag(NoteLoc, diag::note_omp_atomic_read_write)
12703           << ErrorFound << NoteRange;
12704       return StmtError();
12705     }
12706     if (SemaRef.CurContext->isDependentContext())
12707       E = X = nullptr;
12708   } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12709     // If clause is update:
12710     //  x++;
12711     //  x--;
12712     //  ++x;
12713     //  --x;
12714     //  x binop= expr;
12715     //  x = x binop expr;
12716     //  x = expr binop x;
12717     OpenMPAtomicUpdateChecker Checker(SemaRef);
12718     if (Checker.checkStatement(
12719             Body,
12720             (AtomicKind == OMPC_update)
12721                 ? diag::err_omp_atomic_update_not_expression_statement
12722                 : diag::err_omp_atomic_not_expression_statement,
12723             diag::note_omp_atomic_update))
12724       return StmtError();
12725     if (!SemaRef.CurContext->isDependentContext()) {
12726       E = Checker.getExpr();
12727       X = Checker.getX();
12728       UE = Checker.getUpdateExpr();
12729       IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12730     }
12731   } else if (AtomicKind == OMPC_capture) {
12732     enum {
12733       NotAnAssignmentOp,
12734       NotACompoundStatement,
12735       NotTwoSubstatements,
12736       NotASpecificExpression,
12737       NoError
12738     } ErrorFound = NoError;
12739     SourceLocation ErrorLoc, NoteLoc;
12740     SourceRange ErrorRange, NoteRange;
12741     if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12742       // If clause is a capture:
12743       //  v = x++;
12744       //  v = x--;
12745       //  v = ++x;
12746       //  v = --x;
12747       //  v = x binop= expr;
12748       //  v = x = x binop expr;
12749       //  v = x = expr binop x;
12750       const auto *AtomicBinOp =
12751           dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12752       if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12753         V = AtomicBinOp->getLHS();
12754         Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12755         OpenMPAtomicUpdateChecker Checker(SemaRef);
12756         if (Checker.checkStatement(
12757                 Body, diag::err_omp_atomic_capture_not_expression_statement,
12758                 diag::note_omp_atomic_update))
12759           return StmtError();
12760         E = Checker.getExpr();
12761         X = Checker.getX();
12762         UE = Checker.getUpdateExpr();
12763         IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12764         IsPostfixUpdate = Checker.isPostfixUpdate();
12765       } else if (!AtomicBody->isInstantiationDependent()) {
12766         ErrorLoc = AtomicBody->getExprLoc();
12767         ErrorRange = AtomicBody->getSourceRange();
12768         NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12769                               : AtomicBody->getExprLoc();
12770         NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12771                                 : AtomicBody->getSourceRange();
12772         ErrorFound = NotAnAssignmentOp;
12773       }
12774       if (ErrorFound != NoError) {
12775         Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12776             << ErrorRange;
12777         Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12778         return StmtError();
12779       }
12780       if (SemaRef.CurContext->isDependentContext())
12781         UE = V = E = X = nullptr;
12782     } else {
12783       // If clause is a capture:
12784       //  { v = x; x = expr; }
12785       //  { v = x; x++; }
12786       //  { v = x; x--; }
12787       //  { v = x; ++x; }
12788       //  { v = x; --x; }
12789       //  { v = x; x binop= expr; }
12790       //  { v = x; x = x binop expr; }
12791       //  { v = x; x = expr binop x; }
12792       //  { x++; v = x; }
12793       //  { x--; v = x; }
12794       //  { ++x; v = x; }
12795       //  { --x; v = x; }
12796       //  { x binop= expr; v = x; }
12797       //  { x = x binop expr; v = x; }
12798       //  { x = expr binop x; v = x; }
12799       if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
12800         // Check that this is { expr1; expr2; }
12801         if (CS->size() == 2) {
12802           Stmt *First = CS->body_front();
12803           Stmt *Second = CS->body_back();
12804           if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
12805             First = EWC->getSubExpr()->IgnoreParenImpCasts();
12806           if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
12807             Second = EWC->getSubExpr()->IgnoreParenImpCasts();
12808           // Need to find what subexpression is 'v' and what is 'x'.
12809           OpenMPAtomicUpdateChecker Checker(SemaRef);
12810           bool IsUpdateExprFound = !Checker.checkStatement(Second);
12811           BinaryOperator *BinOp = nullptr;
12812           if (IsUpdateExprFound) {
12813             BinOp = dyn_cast<BinaryOperator>(First);
12814             IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12815           }
12816           if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
12817             //  { v = x; x++; }
12818             //  { v = x; x--; }
12819             //  { v = x; ++x; }
12820             //  { v = x; --x; }
12821             //  { v = x; x binop= expr; }
12822             //  { v = x; x = x binop expr; }
12823             //  { v = x; x = expr binop x; }
12824             // Check that the first expression has form v = x.
12825             Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12826             llvm::FoldingSetNodeID XId, PossibleXId;
12827             Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12828             PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12829             IsUpdateExprFound = XId == PossibleXId;
12830             if (IsUpdateExprFound) {
12831               V = BinOp->getLHS();
12832               X = Checker.getX();
12833               E = Checker.getExpr();
12834               UE = Checker.getUpdateExpr();
12835               IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12836               IsPostfixUpdate = true;
12837             }
12838           }
12839           if (!IsUpdateExprFound) {
12840             IsUpdateExprFound = !Checker.checkStatement(First);
12841             BinOp = nullptr;
12842             if (IsUpdateExprFound) {
12843               BinOp = dyn_cast<BinaryOperator>(Second);
12844               IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12845             }
12846             if (IsUpdateExprFound &&
12847                 !SemaRef.CurContext->isDependentContext()) {
12848               //  { x++; v = x; }
12849               //  { x--; v = x; }
12850               //  { ++x; v = x; }
12851               //  { --x; v = x; }
12852               //  { x binop= expr; v = x; }
12853               //  { x = x binop expr; v = x; }
12854               //  { x = expr binop x; v = x; }
12855               // Check that the second expression has form v = x.
12856               Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12857               llvm::FoldingSetNodeID XId, PossibleXId;
12858               Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12859               PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12860               IsUpdateExprFound = XId == PossibleXId;
12861               if (IsUpdateExprFound) {
12862                 V = BinOp->getLHS();
12863                 X = Checker.getX();
12864                 E = Checker.getExpr();
12865                 UE = Checker.getUpdateExpr();
12866                 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12867                 IsPostfixUpdate = false;
12868               }
12869             }
12870           }
12871           if (!IsUpdateExprFound) {
12872             //  { v = x; x = expr; }
12873             auto *FirstExpr = dyn_cast<Expr>(First);
12874             auto *SecondExpr = dyn_cast<Expr>(Second);
12875             if (!FirstExpr || !SecondExpr ||
12876                 !(FirstExpr->isInstantiationDependent() ||
12877                   SecondExpr->isInstantiationDependent())) {
12878               auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
12879               if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
12880                 ErrorFound = NotAnAssignmentOp;
12881                 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
12882                                                 : First->getBeginLoc();
12883                 NoteRange = ErrorRange = FirstBinOp
12884                                              ? FirstBinOp->getSourceRange()
12885                                              : SourceRange(ErrorLoc, ErrorLoc);
12886               } else {
12887                 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
12888                 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
12889                   ErrorFound = NotAnAssignmentOp;
12890                   NoteLoc = ErrorLoc = SecondBinOp
12891                                            ? SecondBinOp->getOperatorLoc()
12892                                            : Second->getBeginLoc();
12893                   NoteRange = ErrorRange =
12894                       SecondBinOp ? SecondBinOp->getSourceRange()
12895                                   : SourceRange(ErrorLoc, ErrorLoc);
12896                 } else {
12897                   Expr *PossibleXRHSInFirst =
12898                       FirstBinOp->getRHS()->IgnoreParenImpCasts();
12899                   Expr *PossibleXLHSInSecond =
12900                       SecondBinOp->getLHS()->IgnoreParenImpCasts();
12901                   llvm::FoldingSetNodeID X1Id, X2Id;
12902                   PossibleXRHSInFirst->Profile(X1Id, Context,
12903                                                /*Canonical=*/true);
12904                   PossibleXLHSInSecond->Profile(X2Id, Context,
12905                                                 /*Canonical=*/true);
12906                   IsUpdateExprFound = X1Id == X2Id;
12907                   if (IsUpdateExprFound) {
12908                     V = FirstBinOp->getLHS();
12909                     X = SecondBinOp->getLHS();
12910                     E = SecondBinOp->getRHS();
12911                     UE = nullptr;
12912                     IsXLHSInRHSPart = false;
12913                     IsPostfixUpdate = true;
12914                   } else {
12915                     ErrorFound = NotASpecificExpression;
12916                     ErrorLoc = FirstBinOp->getExprLoc();
12917                     ErrorRange = FirstBinOp->getSourceRange();
12918                     NoteLoc = SecondBinOp->getLHS()->getExprLoc();
12919                     NoteRange = SecondBinOp->getRHS()->getSourceRange();
12920                   }
12921                 }
12922               }
12923             }
12924           }
12925         } else {
12926           NoteLoc = ErrorLoc = Body->getBeginLoc();
12927           NoteRange = ErrorRange =
12928               SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12929           ErrorFound = NotTwoSubstatements;
12930         }
12931       } else {
12932         NoteLoc = ErrorLoc = Body->getBeginLoc();
12933         NoteRange = ErrorRange =
12934             SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12935         ErrorFound = NotACompoundStatement;
12936       }
12937     }
12938     if (ErrorFound != NoError) {
12939       Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
12940           << ErrorRange;
12941       Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12942       return StmtError();
12943     }
12944     if (SemaRef.CurContext->isDependentContext())
12945       UE = V = E = X = nullptr;
12946   } else if (AtomicKind == OMPC_compare) {
12947     if (IsCompareCapture) {
12948       OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
12949       OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
12950       if (!Checker.checkStmt(Body, ErrorInfo)) {
12951         Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
12952             << ErrorInfo.ErrorRange;
12953         Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12954             << ErrorInfo.Error << ErrorInfo.NoteRange;
12955         return StmtError();
12956       }
12957       X = Checker.getX();
12958       E = Checker.getE();
12959       D = Checker.getD();
12960       CE = Checker.getCond();
12961       V = Checker.getV();
12962       R = Checker.getR();
12963       // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12964       IsXLHSInRHSPart = Checker.isXBinopExpr();
12965       IsFailOnly = Checker.isFailOnly();
12966       IsPostfixUpdate = Checker.isPostfixUpdate();
12967     } else {
12968       OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
12969       OpenMPAtomicCompareChecker Checker(SemaRef);
12970       if (!Checker.checkStmt(Body, ErrorInfo)) {
12971         Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
12972             << ErrorInfo.ErrorRange;
12973         Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12974             << ErrorInfo.Error << ErrorInfo.NoteRange;
12975         return StmtError();
12976       }
12977       X = Checker.getX();
12978       E = Checker.getE();
12979       D = Checker.getD();
12980       CE = Checker.getCond();
12981       // The weak clause may only appear if the resulting atomic operation is
12982       // an atomic conditional update for which the comparison tests for
12983       // equality. It was not possible to do this check in
12984       // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
12985       // could not be performed (Clauses are not available).
12986       auto *It = find_if(Clauses, [](OMPClause *C) {
12987         return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
12988       });
12989       if (It != Clauses.end()) {
12990         auto *Cond = dyn_cast<BinaryOperator>(CE);
12991         if (Cond->getOpcode() != BO_EQ) {
12992           ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
12993           ErrorInfo.ErrorLoc = Cond->getExprLoc();
12994           ErrorInfo.NoteLoc = Cond->getOperatorLoc();
12995           ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12996 
12997           Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
12998               << ErrorInfo.ErrorRange;
12999           return StmtError();
13000         }
13001       }
13002       // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13003       IsXLHSInRHSPart = Checker.isXBinopExpr();
13004     }
13005   }
13006 
13007   SemaRef.setFunctionHasBranchProtectedScope();
13008 
13009   return OMPAtomicDirective::Create(
13010       Context, StartLoc, EndLoc, Clauses, AStmt,
13011       {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
13012 }
13013 
ActOnOpenMPTargetDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)13014 StmtResult SemaOpenMP::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
13015                                                   Stmt *AStmt,
13016                                                   SourceLocation StartLoc,
13017                                                   SourceLocation EndLoc) {
13018   if (!AStmt)
13019     return StmtError();
13020 
13021   CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target, AStmt);
13022 
13023   // OpenMP [2.16, Nesting of Regions]
13024   // If specified, a teams construct must be contained within a target
13025   // construct. That target construct must contain no statements or directives
13026   // outside of the teams construct.
13027   if (DSAStack->hasInnerTeamsRegion()) {
13028     const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13029     bool OMPTeamsFound = true;
13030     if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
13031       auto I = CS->body_begin();
13032       while (I != CS->body_end()) {
13033         const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13034         bool IsTeams = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13035         if (!IsTeams || I != CS->body_begin()) {
13036           OMPTeamsFound = false;
13037           if (IsTeams && I != CS->body_begin()) {
13038             // This is the two teams case. Since the InnerTeamsRegionLoc will
13039             // point to this second one reset the iterator to the other teams.
13040             --I;
13041           }
13042           break;
13043         }
13044         ++I;
13045       }
13046       assert(I != CS->body_end() && "Not found statement");
13047       S = *I;
13048     } else {
13049       const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13050       OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13051     }
13052     if (!OMPTeamsFound) {
13053       Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13054       Diag(DSAStack->getInnerTeamsRegionLoc(),
13055            diag::note_omp_nested_teams_construct_here);
13056       Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
13057           << isa<OMPExecutableDirective>(S);
13058       return StmtError();
13059     }
13060   }
13061 
13062   return OMPTargetDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13063                                     AStmt);
13064 }
13065 
ActOnOpenMPTargetParallelDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)13066 StmtResult SemaOpenMP::ActOnOpenMPTargetParallelDirective(
13067     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13068     SourceLocation EndLoc) {
13069   if (!AStmt)
13070     return StmtError();
13071 
13072   setBranchProtectedScope(SemaRef, OMPD_target_parallel, AStmt);
13073 
13074   return OMPTargetParallelDirective::Create(
13075       getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
13076       DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13077 }
13078 
ActOnOpenMPTargetParallelForDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13079 StmtResult SemaOpenMP::ActOnOpenMPTargetParallelForDirective(
13080     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13081     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13082   if (!AStmt)
13083     return StmtError();
13084 
13085   CapturedStmt *CS =
13086       setBranchProtectedScope(SemaRef, OMPD_target_parallel_for, AStmt);
13087 
13088   OMPLoopBasedDirective::HelperExprs B;
13089   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13090   // define the nested loops number.
13091   unsigned NestedLoopCount =
13092       checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13093                       getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13094                       VarsWithImplicitDSA, B);
13095   if (NestedLoopCount == 0)
13096     return StmtError();
13097 
13098   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13099     return StmtError();
13100 
13101   return OMPTargetParallelForDirective::Create(
13102       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13103       DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13104 }
13105 
13106 /// Check for existence of a map clause in the list of clauses.
hasClauses(ArrayRef<OMPClause * > Clauses,const OpenMPClauseKind K)13107 static bool hasClauses(ArrayRef<OMPClause *> Clauses,
13108                        const OpenMPClauseKind K) {
13109   return llvm::any_of(
13110       Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13111 }
13112 
13113 template <typename... Params>
hasClauses(ArrayRef<OMPClause * > Clauses,const OpenMPClauseKind K,const Params...ClauseTypes)13114 static bool hasClauses(ArrayRef<OMPClause *> Clauses, const OpenMPClauseKind K,
13115                        const Params... ClauseTypes) {
13116   return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13117 }
13118 
13119 /// Check if the variables in the mapping clause are externally visible.
isClauseMappable(ArrayRef<OMPClause * > Clauses)13120 static bool isClauseMappable(ArrayRef<OMPClause *> Clauses) {
13121   for (const OMPClause *C : Clauses) {
13122     if (auto *TC = dyn_cast<OMPToClause>(C))
13123       return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13124         return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13125                (VD->isExternallyVisible() &&
13126                 VD->getVisibility() != HiddenVisibility);
13127       });
13128     else if (auto *FC = dyn_cast<OMPFromClause>(C))
13129       return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13130         return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13131                (VD->isExternallyVisible() &&
13132                 VD->getVisibility() != HiddenVisibility);
13133       });
13134   }
13135 
13136   return true;
13137 }
13138 
13139 StmtResult
ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)13140 SemaOpenMP::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
13141                                            Stmt *AStmt, SourceLocation StartLoc,
13142                                            SourceLocation EndLoc) {
13143   if (!AStmt)
13144     return StmtError();
13145 
13146   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13147 
13148   // OpenMP [2.12.2, target data Construct, Restrictions]
13149   // At least one map, use_device_addr or use_device_ptr clause must appear on
13150   // the directive.
13151   if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13152       (getLangOpts().OpenMP < 50 ||
13153        !hasClauses(Clauses, OMPC_use_device_addr))) {
13154     StringRef Expected;
13155     if (getLangOpts().OpenMP < 50)
13156       Expected = "'map' or 'use_device_ptr'";
13157     else
13158       Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13159     unsigned OMPVersion = getLangOpts().OpenMP;
13160     Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13161         << Expected << getOpenMPDirectiveName(OMPD_target_data, OMPVersion);
13162     return StmtError();
13163   }
13164 
13165   SemaRef.setFunctionHasBranchProtectedScope();
13166 
13167   return OMPTargetDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13168                                         Clauses, AStmt);
13169 }
13170 
ActOnOpenMPTargetEnterDataDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc,Stmt * AStmt)13171 StmtResult SemaOpenMP::ActOnOpenMPTargetEnterDataDirective(
13172     ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13173     SourceLocation EndLoc, Stmt *AStmt) {
13174   if (!AStmt)
13175     return StmtError();
13176 
13177   setBranchProtectedScope(SemaRef, OMPD_target_enter_data, AStmt);
13178 
13179   // OpenMP [2.10.2, Restrictions, p. 99]
13180   // At least one map clause must appear on the directive.
13181   if (!hasClauses(Clauses, OMPC_map)) {
13182     unsigned OMPVersion = getLangOpts().OpenMP;
13183     Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13184         << "'map'"
13185         << getOpenMPDirectiveName(OMPD_target_enter_data, OMPVersion);
13186     return StmtError();
13187   }
13188 
13189   return OMPTargetEnterDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13190                                              Clauses, AStmt);
13191 }
13192 
ActOnOpenMPTargetExitDataDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc,Stmt * AStmt)13193 StmtResult SemaOpenMP::ActOnOpenMPTargetExitDataDirective(
13194     ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13195     SourceLocation EndLoc, Stmt *AStmt) {
13196   if (!AStmt)
13197     return StmtError();
13198 
13199   setBranchProtectedScope(SemaRef, OMPD_target_exit_data, AStmt);
13200 
13201   // OpenMP [2.10.3, Restrictions, p. 102]
13202   // At least one map clause must appear on the directive.
13203   if (!hasClauses(Clauses, OMPC_map)) {
13204     unsigned OMPVersion = getLangOpts().OpenMP;
13205     Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13206         << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data, OMPVersion);
13207     return StmtError();
13208   }
13209 
13210   return OMPTargetExitDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13211                                             Clauses, AStmt);
13212 }
13213 
ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc,Stmt * AStmt)13214 StmtResult SemaOpenMP::ActOnOpenMPTargetUpdateDirective(
13215     ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13216     SourceLocation EndLoc, Stmt *AStmt) {
13217   if (!AStmt)
13218     return StmtError();
13219 
13220   setBranchProtectedScope(SemaRef, OMPD_target_update, AStmt);
13221 
13222   if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13223     Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13224     return StmtError();
13225   }
13226 
13227   if (!isClauseMappable(Clauses)) {
13228     Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13229     return StmtError();
13230   }
13231 
13232   return OMPTargetUpdateDirective::Create(getASTContext(), StartLoc, EndLoc,
13233                                           Clauses, AStmt);
13234 }
13235 
13236 /// This checks whether a \p ClauseType clause \p C has at most \p Max
13237 /// expression. If not, a diag of number \p Diag will be emitted.
13238 template <typename ClauseType>
checkNumExprsInClause(SemaBase & SemaRef,ArrayRef<OMPClause * > Clauses,unsigned MaxNum,unsigned Diag)13239 static bool checkNumExprsInClause(SemaBase &SemaRef,
13240                                   ArrayRef<OMPClause *> Clauses,
13241                                   unsigned MaxNum, unsigned Diag) {
13242   auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13243   if (ClauseItr == Clauses.end())
13244     return true;
13245   const auto *C = cast<ClauseType>(*ClauseItr);
13246   auto VarList = C->getVarRefs();
13247   if (VarList.size() > MaxNum) {
13248     SemaRef.Diag(VarList[MaxNum]->getBeginLoc(), Diag)
13249         << getOpenMPClauseNameForDiag(C->getClauseKind());
13250     return false;
13251   }
13252   return true;
13253 }
13254 
ActOnOpenMPTeamsDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)13255 StmtResult SemaOpenMP::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
13256                                                  Stmt *AStmt,
13257                                                  SourceLocation StartLoc,
13258                                                  SourceLocation EndLoc) {
13259   if (!AStmt)
13260     return StmtError();
13261 
13262   if (!checkNumExprsInClause<OMPNumTeamsClause>(
13263           *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
13264       !checkNumExprsInClause<OMPThreadLimitClause>(
13265           *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
13266     return StmtError();
13267 
13268   // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13269   if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13270     Diag(StartLoc, diag::warn_hip_omp_target_directives);
13271 
13272   setBranchProtectedScope(SemaRef, OMPD_teams, AStmt);
13273 
13274   DSAStack->setParentTeamsRegionLoc(StartLoc);
13275 
13276   return OMPTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13277                                    AStmt);
13278 }
13279 
ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc,SourceLocation EndLoc,OpenMPDirectiveKind CancelRegion)13280 StmtResult SemaOpenMP::ActOnOpenMPCancellationPointDirective(
13281     SourceLocation StartLoc, SourceLocation EndLoc,
13282     OpenMPDirectiveKind CancelRegion) {
13283   if (DSAStack->isParentNowaitRegion()) {
13284     Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13285     return StmtError();
13286   }
13287   if (DSAStack->isParentOrderedRegion()) {
13288     Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13289     return StmtError();
13290   }
13291   return OMPCancellationPointDirective::Create(getASTContext(), StartLoc,
13292                                                EndLoc, CancelRegion);
13293 }
13294 
ActOnOpenMPCancelDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc,OpenMPDirectiveKind CancelRegion)13295 StmtResult SemaOpenMP::ActOnOpenMPCancelDirective(
13296     ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13297     SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13298   if (DSAStack->isParentNowaitRegion()) {
13299     Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13300     return StmtError();
13301   }
13302   if (DSAStack->isParentOrderedRegion()) {
13303     Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13304     return StmtError();
13305   }
13306   DSAStack->setParentCancelRegion(/*Cancel=*/true);
13307   return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13308                                     CancelRegion);
13309 }
13310 
checkReductionClauseWithNogroup(Sema & S,ArrayRef<OMPClause * > Clauses)13311 static bool checkReductionClauseWithNogroup(Sema &S,
13312                                             ArrayRef<OMPClause *> Clauses) {
13313   const OMPClause *ReductionClause = nullptr;
13314   const OMPClause *NogroupClause = nullptr;
13315   for (const OMPClause *C : Clauses) {
13316     if (C->getClauseKind() == OMPC_reduction) {
13317       ReductionClause = C;
13318       if (NogroupClause)
13319         break;
13320       continue;
13321     }
13322     if (C->getClauseKind() == OMPC_nogroup) {
13323       NogroupClause = C;
13324       if (ReductionClause)
13325         break;
13326       continue;
13327     }
13328   }
13329   if (ReductionClause && NogroupClause) {
13330     S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13331         << SourceRange(NogroupClause->getBeginLoc(),
13332                        NogroupClause->getEndLoc());
13333     return true;
13334   }
13335   return false;
13336 }
13337 
ActOnOpenMPTaskLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13338 StmtResult SemaOpenMP::ActOnOpenMPTaskLoopDirective(
13339     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13340     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13341   if (!AStmt)
13342     return StmtError();
13343 
13344   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13345   OMPLoopBasedDirective::HelperExprs B;
13346   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13347   // define the nested loops number.
13348   unsigned NestedLoopCount =
13349       checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13350                       /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13351                       *DSAStack, VarsWithImplicitDSA, B);
13352   if (NestedLoopCount == 0)
13353     return StmtError();
13354 
13355   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13356          "omp for loop exprs were not built");
13357 
13358   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13359   // The grainsize clause and num_tasks clause are mutually exclusive and may
13360   // not appear on the same taskloop directive.
13361   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13362                                     {OMPC_grainsize, OMPC_num_tasks}))
13363     return StmtError();
13364   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13365   // If a reduction clause is present on the taskloop directive, the nogroup
13366   // clause must not be specified.
13367   if (checkReductionClauseWithNogroup(SemaRef, Clauses))
13368     return StmtError();
13369 
13370   SemaRef.setFunctionHasBranchProtectedScope();
13371   return OMPTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13372                                       NestedLoopCount, Clauses, AStmt, B,
13373                                       DSAStack->isCancelRegion());
13374 }
13375 
ActOnOpenMPTaskLoopSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13376 StmtResult SemaOpenMP::ActOnOpenMPTaskLoopSimdDirective(
13377     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13378     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13379   if (!AStmt)
13380     return StmtError();
13381 
13382   CapturedStmt *CS =
13383       setBranchProtectedScope(SemaRef, OMPD_taskloop_simd, AStmt);
13384 
13385   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13386   OMPLoopBasedDirective::HelperExprs B;
13387   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13388   // define the nested loops number.
13389   unsigned NestedLoopCount =
13390       checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13391                       /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13392                       VarsWithImplicitDSA, B);
13393   if (NestedLoopCount == 0)
13394     return StmtError();
13395 
13396   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13397     return StmtError();
13398 
13399   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13400   // The grainsize clause and num_tasks clause are mutually exclusive and may
13401   // not appear on the same taskloop directive.
13402   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13403                                     {OMPC_grainsize, OMPC_num_tasks}))
13404     return StmtError();
13405   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13406   // If a reduction clause is present on the taskloop directive, the nogroup
13407   // clause must not be specified.
13408   if (checkReductionClauseWithNogroup(SemaRef, Clauses))
13409     return StmtError();
13410   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13411     return StmtError();
13412 
13413   return OMPTaskLoopSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13414                                           NestedLoopCount, Clauses, AStmt, B);
13415 }
13416 
ActOnOpenMPMasterTaskLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13417 StmtResult SemaOpenMP::ActOnOpenMPMasterTaskLoopDirective(
13418     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13419     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13420   if (!AStmt)
13421     return StmtError();
13422 
13423   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13424   OMPLoopBasedDirective::HelperExprs B;
13425   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13426   // define the nested loops number.
13427   unsigned NestedLoopCount =
13428       checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13429                       /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13430                       *DSAStack, VarsWithImplicitDSA, B);
13431   if (NestedLoopCount == 0)
13432     return StmtError();
13433 
13434   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13435          "omp for loop exprs were not built");
13436 
13437   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13438   // The grainsize clause and num_tasks clause are mutually exclusive and may
13439   // not appear on the same taskloop directive.
13440   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13441                                     {OMPC_grainsize, OMPC_num_tasks}))
13442     return StmtError();
13443   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13444   // If a reduction clause is present on the taskloop directive, the nogroup
13445   // clause must not be specified.
13446   if (checkReductionClauseWithNogroup(SemaRef, Clauses))
13447     return StmtError();
13448 
13449   SemaRef.setFunctionHasBranchProtectedScope();
13450   return OMPMasterTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13451                                             NestedLoopCount, Clauses, AStmt, B,
13452                                             DSAStack->isCancelRegion());
13453 }
13454 
ActOnOpenMPMaskedTaskLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13455 StmtResult SemaOpenMP::ActOnOpenMPMaskedTaskLoopDirective(
13456     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13457     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13458   if (!AStmt)
13459     return StmtError();
13460 
13461   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13462   OMPLoopBasedDirective::HelperExprs B;
13463   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13464   // define the nested loops number.
13465   unsigned NestedLoopCount =
13466       checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13467                       /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13468                       *DSAStack, VarsWithImplicitDSA, B);
13469   if (NestedLoopCount == 0)
13470     return StmtError();
13471 
13472   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13473          "omp for loop exprs were not built");
13474 
13475   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13476   // The grainsize clause and num_tasks clause are mutually exclusive and may
13477   // not appear on the same taskloop directive.
13478   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13479                                     {OMPC_grainsize, OMPC_num_tasks}))
13480     return StmtError();
13481   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13482   // If a reduction clause is present on the taskloop directive, the nogroup
13483   // clause must not be specified.
13484   if (checkReductionClauseWithNogroup(SemaRef, Clauses))
13485     return StmtError();
13486 
13487   SemaRef.setFunctionHasBranchProtectedScope();
13488   return OMPMaskedTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13489                                             NestedLoopCount, Clauses, AStmt, B,
13490                                             DSAStack->isCancelRegion());
13491 }
13492 
ActOnOpenMPMasterTaskLoopSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13493 StmtResult SemaOpenMP::ActOnOpenMPMasterTaskLoopSimdDirective(
13494     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13495     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13496   if (!AStmt)
13497     return StmtError();
13498 
13499   CapturedStmt *CS =
13500       setBranchProtectedScope(SemaRef, OMPD_master_taskloop_simd, AStmt);
13501 
13502   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13503   OMPLoopBasedDirective::HelperExprs B;
13504   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13505   // define the nested loops number.
13506   unsigned NestedLoopCount =
13507       checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13508                       /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13509                       VarsWithImplicitDSA, B);
13510   if (NestedLoopCount == 0)
13511     return StmtError();
13512 
13513   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13514     return StmtError();
13515 
13516   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13517   // The grainsize clause and num_tasks clause are mutually exclusive and may
13518   // not appear on the same taskloop directive.
13519   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13520                                     {OMPC_grainsize, OMPC_num_tasks}))
13521     return StmtError();
13522   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13523   // If a reduction clause is present on the taskloop directive, the nogroup
13524   // clause must not be specified.
13525   if (checkReductionClauseWithNogroup(SemaRef, Clauses))
13526     return StmtError();
13527   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13528     return StmtError();
13529 
13530   return OMPMasterTaskLoopSimdDirective::Create(
13531       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13532 }
13533 
ActOnOpenMPMaskedTaskLoopSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13534 StmtResult SemaOpenMP::ActOnOpenMPMaskedTaskLoopSimdDirective(
13535     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13536     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13537   if (!AStmt)
13538     return StmtError();
13539 
13540   CapturedStmt *CS =
13541       setBranchProtectedScope(SemaRef, OMPD_masked_taskloop_simd, AStmt);
13542 
13543   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13544   OMPLoopBasedDirective::HelperExprs B;
13545   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13546   // define the nested loops number.
13547   unsigned NestedLoopCount =
13548       checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13549                       /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13550                       VarsWithImplicitDSA, B);
13551   if (NestedLoopCount == 0)
13552     return StmtError();
13553 
13554   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13555     return StmtError();
13556 
13557   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13558   // The grainsize clause and num_tasks clause are mutually exclusive and may
13559   // not appear on the same taskloop directive.
13560   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13561                                     {OMPC_grainsize, OMPC_num_tasks}))
13562     return StmtError();
13563   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13564   // If a reduction clause is present on the taskloop directive, the nogroup
13565   // clause must not be specified.
13566   if (checkReductionClauseWithNogroup(SemaRef, Clauses))
13567     return StmtError();
13568   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13569     return StmtError();
13570 
13571   return OMPMaskedTaskLoopSimdDirective::Create(
13572       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13573 }
13574 
ActOnOpenMPParallelMasterTaskLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13575 StmtResult SemaOpenMP::ActOnOpenMPParallelMasterTaskLoopDirective(
13576     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13577     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13578   if (!AStmt)
13579     return StmtError();
13580 
13581   CapturedStmt *CS =
13582       setBranchProtectedScope(SemaRef, OMPD_parallel_master_taskloop, AStmt);
13583 
13584   OMPLoopBasedDirective::HelperExprs B;
13585   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13586   // define the nested loops number.
13587   unsigned NestedLoopCount = checkOpenMPLoop(
13588       OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13589       /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13590       VarsWithImplicitDSA, B);
13591   if (NestedLoopCount == 0)
13592     return StmtError();
13593 
13594   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13595          "omp for loop exprs were not built");
13596 
13597   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13598   // The grainsize clause and num_tasks clause are mutually exclusive and may
13599   // not appear on the same taskloop directive.
13600   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13601                                     {OMPC_grainsize, OMPC_num_tasks}))
13602     return StmtError();
13603   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13604   // If a reduction clause is present on the taskloop directive, the nogroup
13605   // clause must not be specified.
13606   if (checkReductionClauseWithNogroup(SemaRef, Clauses))
13607     return StmtError();
13608 
13609   return OMPParallelMasterTaskLoopDirective::Create(
13610       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13611       DSAStack->isCancelRegion());
13612 }
13613 
ActOnOpenMPParallelMaskedTaskLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13614 StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedTaskLoopDirective(
13615     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13616     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13617   if (!AStmt)
13618     return StmtError();
13619 
13620   CapturedStmt *CS =
13621       setBranchProtectedScope(SemaRef, OMPD_parallel_masked_taskloop, AStmt);
13622 
13623   OMPLoopBasedDirective::HelperExprs B;
13624   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13625   // define the nested loops number.
13626   unsigned NestedLoopCount = checkOpenMPLoop(
13627       OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13628       /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13629       VarsWithImplicitDSA, B);
13630   if (NestedLoopCount == 0)
13631     return StmtError();
13632 
13633   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13634          "omp for loop exprs were not built");
13635 
13636   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13637   // The grainsize clause and num_tasks clause are mutually exclusive and may
13638   // not appear on the same taskloop directive.
13639   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13640                                     {OMPC_grainsize, OMPC_num_tasks}))
13641     return StmtError();
13642   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13643   // If a reduction clause is present on the taskloop directive, the nogroup
13644   // clause must not be specified.
13645   if (checkReductionClauseWithNogroup(SemaRef, Clauses))
13646     return StmtError();
13647 
13648   return OMPParallelMaskedTaskLoopDirective::Create(
13649       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13650       DSAStack->isCancelRegion());
13651 }
13652 
ActOnOpenMPParallelMasterTaskLoopSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13653 StmtResult SemaOpenMP::ActOnOpenMPParallelMasterTaskLoopSimdDirective(
13654     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13655     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13656   if (!AStmt)
13657     return StmtError();
13658 
13659   CapturedStmt *CS = setBranchProtectedScope(
13660       SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13661 
13662   OMPLoopBasedDirective::HelperExprs B;
13663   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13664   // define the nested loops number.
13665   unsigned NestedLoopCount = checkOpenMPLoop(
13666       OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13667       /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13668       VarsWithImplicitDSA, B);
13669   if (NestedLoopCount == 0)
13670     return StmtError();
13671 
13672   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13673     return StmtError();
13674 
13675   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13676   // The grainsize clause and num_tasks clause are mutually exclusive and may
13677   // not appear on the same taskloop directive.
13678   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13679                                     {OMPC_grainsize, OMPC_num_tasks}))
13680     return StmtError();
13681   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13682   // If a reduction clause is present on the taskloop directive, the nogroup
13683   // clause must not be specified.
13684   if (checkReductionClauseWithNogroup(SemaRef, Clauses))
13685     return StmtError();
13686   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13687     return StmtError();
13688 
13689   return OMPParallelMasterTaskLoopSimdDirective::Create(
13690       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13691 }
13692 
ActOnOpenMPParallelMaskedTaskLoopSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13693 StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
13694     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13695     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13696   if (!AStmt)
13697     return StmtError();
13698 
13699   CapturedStmt *CS = setBranchProtectedScope(
13700       SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13701 
13702   OMPLoopBasedDirective::HelperExprs B;
13703   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13704   // define the nested loops number.
13705   unsigned NestedLoopCount = checkOpenMPLoop(
13706       OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13707       /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13708       VarsWithImplicitDSA, B);
13709   if (NestedLoopCount == 0)
13710     return StmtError();
13711 
13712   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13713     return StmtError();
13714 
13715   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13716   // The grainsize clause and num_tasks clause are mutually exclusive and may
13717   // not appear on the same taskloop directive.
13718   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13719                                     {OMPC_grainsize, OMPC_num_tasks}))
13720     return StmtError();
13721   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13722   // If a reduction clause is present on the taskloop directive, the nogroup
13723   // clause must not be specified.
13724   if (checkReductionClauseWithNogroup(SemaRef, Clauses))
13725     return StmtError();
13726   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13727     return StmtError();
13728 
13729   return OMPParallelMaskedTaskLoopSimdDirective::Create(
13730       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13731 }
13732 
ActOnOpenMPDistributeDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13733 StmtResult SemaOpenMP::ActOnOpenMPDistributeDirective(
13734     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13735     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13736   if (!AStmt)
13737     return StmtError();
13738 
13739   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13740   OMPLoopBasedDirective::HelperExprs B;
13741   // In presence of clause 'collapse' with number of loops, it will
13742   // define the nested loops number.
13743   unsigned NestedLoopCount =
13744       checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
13745                       nullptr /*ordered not a clause on distribute*/, AStmt,
13746                       SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13747   if (NestedLoopCount == 0)
13748     return StmtError();
13749 
13750   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13751          "omp for loop exprs were not built");
13752 
13753   SemaRef.setFunctionHasBranchProtectedScope();
13754   auto *DistributeDirective = OMPDistributeDirective::Create(
13755       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13756   return DistributeDirective;
13757 }
13758 
ActOnOpenMPDistributeParallelForDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13759 StmtResult SemaOpenMP::ActOnOpenMPDistributeParallelForDirective(
13760     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13761     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13762   if (!AStmt)
13763     return StmtError();
13764 
13765   CapturedStmt *CS =
13766       setBranchProtectedScope(SemaRef, OMPD_distribute_parallel_for, AStmt);
13767 
13768   OMPLoopBasedDirective::HelperExprs B;
13769   // In presence of clause 'collapse' with number of loops, it will
13770   // define the nested loops number.
13771   unsigned NestedLoopCount = checkOpenMPLoop(
13772       OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13773       nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13774       VarsWithImplicitDSA, B);
13775   if (NestedLoopCount == 0)
13776     return StmtError();
13777 
13778   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13779          "omp for loop exprs were not built");
13780 
13781   return OMPDistributeParallelForDirective::Create(
13782       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13783       DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13784 }
13785 
ActOnOpenMPDistributeParallelForSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13786 StmtResult SemaOpenMP::ActOnOpenMPDistributeParallelForSimdDirective(
13787     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13788     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13789   if (!AStmt)
13790     return StmtError();
13791 
13792   CapturedStmt *CS = setBranchProtectedScope(
13793       SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
13794 
13795   OMPLoopBasedDirective::HelperExprs B;
13796   // In presence of clause 'collapse' with number of loops, it will
13797   // define the nested loops number.
13798   unsigned NestedLoopCount = checkOpenMPLoop(
13799       OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13800       nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13801       VarsWithImplicitDSA, B);
13802   if (NestedLoopCount == 0)
13803     return StmtError();
13804 
13805   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13806     return StmtError();
13807 
13808   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13809     return StmtError();
13810 
13811   return OMPDistributeParallelForSimdDirective::Create(
13812       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13813 }
13814 
ActOnOpenMPDistributeSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13815 StmtResult SemaOpenMP::ActOnOpenMPDistributeSimdDirective(
13816     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13817     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13818   if (!AStmt)
13819     return StmtError();
13820 
13821   CapturedStmt *CS =
13822       setBranchProtectedScope(SemaRef, OMPD_distribute_simd, AStmt);
13823 
13824   OMPLoopBasedDirective::HelperExprs B;
13825   // In presence of clause 'collapse' with number of loops, it will
13826   // define the nested loops number.
13827   unsigned NestedLoopCount =
13828       checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
13829                       nullptr /*ordered not a clause on distribute*/, CS,
13830                       SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13831   if (NestedLoopCount == 0)
13832     return StmtError();
13833 
13834   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13835     return StmtError();
13836 
13837   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13838     return StmtError();
13839 
13840   return OMPDistributeSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13841                                             NestedLoopCount, Clauses, AStmt, B);
13842 }
13843 
ActOnOpenMPTargetParallelForSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13844 StmtResult SemaOpenMP::ActOnOpenMPTargetParallelForSimdDirective(
13845     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13846     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13847   if (!AStmt)
13848     return StmtError();
13849 
13850   CapturedStmt *CS =
13851       setBranchProtectedScope(SemaRef, OMPD_target_parallel_for_simd, AStmt);
13852 
13853   OMPLoopBasedDirective::HelperExprs B;
13854   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13855   // define the nested loops number.
13856   unsigned NestedLoopCount = checkOpenMPLoop(
13857       OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
13858       getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13859       VarsWithImplicitDSA, B);
13860   if (NestedLoopCount == 0)
13861     return StmtError();
13862 
13863   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13864     return StmtError();
13865 
13866   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13867     return StmtError();
13868 
13869   return OMPTargetParallelForSimdDirective::Create(
13870       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13871 }
13872 
ActOnOpenMPTargetSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13873 StmtResult SemaOpenMP::ActOnOpenMPTargetSimdDirective(
13874     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13875     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13876   if (!AStmt)
13877     return StmtError();
13878 
13879   CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target_simd, AStmt);
13880 
13881   OMPLoopBasedDirective::HelperExprs B;
13882   // In presence of clause 'collapse' with number of loops, it will define the
13883   // nested loops number.
13884   unsigned NestedLoopCount =
13885       checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
13886                       getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13887                       VarsWithImplicitDSA, B);
13888   if (NestedLoopCount == 0)
13889     return StmtError();
13890 
13891   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13892     return StmtError();
13893 
13894   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13895     return StmtError();
13896 
13897   return OMPTargetSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13898                                         NestedLoopCount, Clauses, AStmt, B);
13899 }
13900 
ActOnOpenMPTeamsDistributeDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13901 StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeDirective(
13902     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13903     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13904   if (!AStmt)
13905     return StmtError();
13906 
13907   CapturedStmt *CS =
13908       setBranchProtectedScope(SemaRef, OMPD_teams_distribute, AStmt);
13909 
13910   OMPLoopBasedDirective::HelperExprs B;
13911   // In presence of clause 'collapse' with number of loops, it will
13912   // define the nested loops number.
13913   unsigned NestedLoopCount =
13914       checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
13915                       nullptr /*ordered not a clause on distribute*/, CS,
13916                       SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13917   if (NestedLoopCount == 0)
13918     return StmtError();
13919 
13920   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13921          "omp teams distribute loop exprs were not built");
13922 
13923   DSAStack->setParentTeamsRegionLoc(StartLoc);
13924 
13925   return OMPTeamsDistributeDirective::Create(
13926       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13927 }
13928 
ActOnOpenMPTeamsDistributeSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13929 StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeSimdDirective(
13930     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13931     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13932   if (!AStmt)
13933     return StmtError();
13934 
13935   CapturedStmt *CS =
13936       setBranchProtectedScope(SemaRef, OMPD_teams_distribute_simd, AStmt);
13937 
13938   OMPLoopBasedDirective::HelperExprs B;
13939   // In presence of clause 'collapse' with number of loops, it will
13940   // define the nested loops number.
13941   unsigned NestedLoopCount = checkOpenMPLoop(
13942       OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
13943       nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13944       VarsWithImplicitDSA, B);
13945   if (NestedLoopCount == 0)
13946     return StmtError();
13947 
13948   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13949     return StmtError();
13950 
13951   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13952     return StmtError();
13953 
13954   DSAStack->setParentTeamsRegionLoc(StartLoc);
13955 
13956   return OMPTeamsDistributeSimdDirective::Create(
13957       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13958 }
13959 
ActOnOpenMPTeamsDistributeParallelForSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13960 StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
13961     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13962     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13963   if (!AStmt)
13964     return StmtError();
13965 
13966   CapturedStmt *CS = setBranchProtectedScope(
13967       SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
13968 
13969   OMPLoopBasedDirective::HelperExprs B;
13970   // In presence of clause 'collapse' with number of loops, it will
13971   // define the nested loops number.
13972   unsigned NestedLoopCount = checkOpenMPLoop(
13973       OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13974       nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13975       VarsWithImplicitDSA, B);
13976   if (NestedLoopCount == 0)
13977     return StmtError();
13978 
13979   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13980     return StmtError();
13981 
13982   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13983     return StmtError();
13984 
13985   DSAStack->setParentTeamsRegionLoc(StartLoc);
13986 
13987   return OMPTeamsDistributeParallelForSimdDirective::Create(
13988       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13989 }
13990 
ActOnOpenMPTeamsDistributeParallelForDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13991 StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeParallelForDirective(
13992     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13993     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13994   if (!AStmt)
13995     return StmtError();
13996 
13997   CapturedStmt *CS = setBranchProtectedScope(
13998       SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
13999 
14000   OMPLoopBasedDirective::HelperExprs B;
14001   // In presence of clause 'collapse' with number of loops, it will
14002   // define the nested loops number.
14003   unsigned NestedLoopCount = checkOpenMPLoop(
14004       OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14005       nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14006       VarsWithImplicitDSA, B);
14007 
14008   if (NestedLoopCount == 0)
14009     return StmtError();
14010 
14011   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14012          "omp for loop exprs were not built");
14013 
14014   DSAStack->setParentTeamsRegionLoc(StartLoc);
14015 
14016   return OMPTeamsDistributeParallelForDirective::Create(
14017       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14018       DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14019 }
14020 
ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)14021 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDirective(
14022     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14023     SourceLocation EndLoc) {
14024   if (!AStmt)
14025     return StmtError();
14026 
14027   setBranchProtectedScope(SemaRef, OMPD_target_teams, AStmt);
14028 
14029   const OMPClause *BareClause = nullptr;
14030   bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) &&
14031                                          hasClauses(Clauses, OMPC_thread_limit);
14032   bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) {
14033     BareClause = C;
14034     return C->getClauseKind() == OMPC_ompx_bare;
14035   });
14036 
14037   if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14038     Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
14039     return StmtError();
14040   }
14041 
14042   unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
14043   unsigned DiagNo = HasBareClause
14044                         ? diag::err_ompx_more_than_three_expr_not_allowed
14045                         : diag::err_omp_multi_expr_not_allowed;
14046   if (!checkNumExprsInClause<OMPNumTeamsClause>(*this, Clauses,
14047                                                 ClauseMaxNumExprs, DiagNo) ||
14048       !checkNumExprsInClause<OMPThreadLimitClause>(*this, Clauses,
14049                                                    ClauseMaxNumExprs, DiagNo))
14050     return StmtError();
14051 
14052   return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc,
14053                                          Clauses, AStmt);
14054 }
14055 
ActOnOpenMPTargetTeamsDistributeDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)14056 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeDirective(
14057     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14058     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14059   if (!AStmt)
14060     return StmtError();
14061 
14062   if (!checkNumExprsInClause<OMPNumTeamsClause>(
14063           *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14064       !checkNumExprsInClause<OMPThreadLimitClause>(
14065           *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14066     return StmtError();
14067 
14068   CapturedStmt *CS =
14069       setBranchProtectedScope(SemaRef, OMPD_target_teams_distribute, AStmt);
14070 
14071   OMPLoopBasedDirective::HelperExprs B;
14072   // In presence of clause 'collapse' with number of loops, it will
14073   // define the nested loops number.
14074   unsigned NestedLoopCount = checkOpenMPLoop(
14075       OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14076       nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14077       VarsWithImplicitDSA, B);
14078   if (NestedLoopCount == 0)
14079     return StmtError();
14080 
14081   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14082          "omp target teams distribute loop exprs were not built");
14083 
14084   return OMPTargetTeamsDistributeDirective::Create(
14085       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14086 }
14087 
ActOnOpenMPTargetTeamsDistributeParallelForDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)14088 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
14089     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14090     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14091   if (!AStmt)
14092     return StmtError();
14093 
14094   if (!checkNumExprsInClause<OMPNumTeamsClause>(
14095           *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14096       !checkNumExprsInClause<OMPThreadLimitClause>(
14097           *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14098     return StmtError();
14099 
14100   CapturedStmt *CS = setBranchProtectedScope(
14101       SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14102 
14103   OMPLoopBasedDirective::HelperExprs B;
14104   // In presence of clause 'collapse' with number of loops, it will
14105   // define the nested loops number.
14106   unsigned NestedLoopCount = checkOpenMPLoop(
14107       OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14108       nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14109       VarsWithImplicitDSA, B);
14110   if (NestedLoopCount == 0)
14111     return StmtError();
14112 
14113   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14114     return StmtError();
14115 
14116   return OMPTargetTeamsDistributeParallelForDirective::Create(
14117       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14118       DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14119 }
14120 
ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)14121 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
14122     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14123     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14124   if (!AStmt)
14125     return StmtError();
14126 
14127   if (!checkNumExprsInClause<OMPNumTeamsClause>(
14128           *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14129       !checkNumExprsInClause<OMPThreadLimitClause>(
14130           *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14131     return StmtError();
14132 
14133   CapturedStmt *CS = setBranchProtectedScope(
14134       SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14135 
14136   OMPLoopBasedDirective::HelperExprs B;
14137   // In presence of clause 'collapse' with number of loops, it will
14138   // define the nested loops number.
14139   unsigned NestedLoopCount =
14140       checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14141                       getCollapseNumberExpr(Clauses),
14142                       nullptr /*ordered not a clause on distribute*/, CS,
14143                       SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14144   if (NestedLoopCount == 0)
14145     return StmtError();
14146 
14147   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14148     return StmtError();
14149 
14150   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
14151     return StmtError();
14152 
14153   return OMPTargetTeamsDistributeParallelForSimdDirective::Create(
14154       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14155 }
14156 
ActOnOpenMPTargetTeamsDistributeSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)14157 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeSimdDirective(
14158     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14159     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14160   if (!AStmt)
14161     return StmtError();
14162 
14163   if (!checkNumExprsInClause<OMPNumTeamsClause>(
14164           *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14165       !checkNumExprsInClause<OMPThreadLimitClause>(
14166           *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14167     return StmtError();
14168 
14169   CapturedStmt *CS = setBranchProtectedScope(
14170       SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14171 
14172   OMPLoopBasedDirective::HelperExprs B;
14173   // In presence of clause 'collapse' with number of loops, it will
14174   // define the nested loops number.
14175   unsigned NestedLoopCount = checkOpenMPLoop(
14176       OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14177       nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14178       VarsWithImplicitDSA, B);
14179   if (NestedLoopCount == 0)
14180     return StmtError();
14181 
14182   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14183     return StmtError();
14184 
14185   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
14186     return StmtError();
14187 
14188   return OMPTargetTeamsDistributeSimdDirective::Create(
14189       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14190 }
14191 
checkTransformableLoopNest(OpenMPDirectiveKind Kind,Stmt * AStmt,int NumLoops,SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> & LoopHelpers,Stmt * & Body,SmallVectorImpl<SmallVector<Stmt *,0>> & OriginalInits)14192 bool SemaOpenMP::checkTransformableLoopNest(
14193     OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14194     SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers,
14195     Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *, 0>> &OriginalInits) {
14196   OriginalInits.emplace_back();
14197   bool Result = OMPLoopBasedDirective::doForAllLoops(
14198       AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14199       [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14200                                                         Stmt *CurStmt) {
14201         VarsWithInheritedDSAType TmpDSA;
14202         unsigned SingleNumLoops =
14203             checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14204                             TmpDSA, LoopHelpers[Cnt]);
14205         if (SingleNumLoops == 0)
14206           return true;
14207         assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14208         if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14209           OriginalInits.back().push_back(For->getInit());
14210           Body = For->getBody();
14211         } else {
14212           assert(isa<CXXForRangeStmt>(CurStmt) &&
14213                  "Expected canonical for or range-based for loops.");
14214           auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14215           OriginalInits.back().push_back(CXXFor->getBeginStmt());
14216           Body = CXXFor->getBody();
14217         }
14218         OriginalInits.emplace_back();
14219         return false;
14220       },
14221       [&OriginalInits](OMPLoopBasedDirective *Transform) {
14222         Stmt *DependentPreInits;
14223         if (auto *Dir = dyn_cast<OMPTileDirective>(Transform))
14224           DependentPreInits = Dir->getPreInits();
14225         else if (auto *Dir = dyn_cast<OMPStripeDirective>(Transform))
14226           DependentPreInits = Dir->getPreInits();
14227         else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
14228           DependentPreInits = Dir->getPreInits();
14229         else if (auto *Dir = dyn_cast<OMPReverseDirective>(Transform))
14230           DependentPreInits = Dir->getPreInits();
14231         else if (auto *Dir = dyn_cast<OMPInterchangeDirective>(Transform))
14232           DependentPreInits = Dir->getPreInits();
14233         else
14234           llvm_unreachable("Unhandled loop transformation");
14235 
14236         appendFlattenedStmtList(OriginalInits.back(), DependentPreInits);
14237       });
14238   assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14239   OriginalInits.pop_back();
14240   return Result;
14241 }
14242 
14243 /// Add preinit statements that need to be propageted from the selected loop.
addLoopPreInits(ASTContext & Context,OMPLoopBasedDirective::HelperExprs & LoopHelper,Stmt * LoopStmt,ArrayRef<Stmt * > OriginalInit,SmallVectorImpl<Stmt * > & PreInits)14244 static void addLoopPreInits(ASTContext &Context,
14245                             OMPLoopBasedDirective::HelperExprs &LoopHelper,
14246                             Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
14247                             SmallVectorImpl<Stmt *> &PreInits) {
14248 
14249   // For range-based for-statements, ensure that their syntactic sugar is
14250   // executed by adding them as pre-init statements.
14251   if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14252     Stmt *RangeInit = CXXRangeFor->getInit();
14253     if (RangeInit)
14254       PreInits.push_back(RangeInit);
14255 
14256     DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14257     PreInits.push_back(new (Context) DeclStmt(RangeStmt->getDeclGroup(),
14258                                               RangeStmt->getBeginLoc(),
14259                                               RangeStmt->getEndLoc()));
14260 
14261     DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14262     PreInits.push_back(new (Context) DeclStmt(RangeEnd->getDeclGroup(),
14263                                               RangeEnd->getBeginLoc(),
14264                                               RangeEnd->getEndLoc()));
14265   }
14266 
14267   llvm::append_range(PreInits, OriginalInit);
14268 
14269   // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
14270   if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
14271     PreInits.push_back(new (Context) DeclStmt(
14272         PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14273   }
14274 
14275   // Gather declarations for the data members used as counters.
14276   for (Expr *CounterRef : LoopHelper.Counters) {
14277     auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14278     if (isa<OMPCapturedExprDecl>(CounterDecl))
14279       PreInits.push_back(new (Context) DeclStmt(
14280           DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
14281   }
14282 }
14283 
14284 /// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
14285 /// loop of a construct.
collectLoopStmts(Stmt * AStmt,MutableArrayRef<Stmt * > LoopStmts)14286 static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) {
14287   size_t NumLoops = LoopStmts.size();
14288   OMPLoopBasedDirective::doForAllLoops(
14289       AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
14290       [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
14291         assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
14292         LoopStmts[Cnt] = CurStmt;
14293         return false;
14294       });
14295   assert(!is_contained(LoopStmts, nullptr) &&
14296          "Expecting a loop statement for each affected loop");
14297 }
14298 
14299 /// Build and return a DeclRefExpr for the floor induction variable using the
14300 /// SemaRef and the provided parameters.
makeFloorIVRef(Sema & SemaRef,ArrayRef<VarDecl * > FloorIndVars,int I,QualType IVTy,DeclRefExpr * OrigCntVar)14301 static Expr *makeFloorIVRef(Sema &SemaRef, ArrayRef<VarDecl *> FloorIndVars,
14302                             int I, QualType IVTy, DeclRefExpr *OrigCntVar) {
14303   return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14304                           OrigCntVar->getExprLoc());
14305 }
14306 
ActOnOpenMPTileDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)14307 StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
14308                                                 Stmt *AStmt,
14309                                                 SourceLocation StartLoc,
14310                                                 SourceLocation EndLoc) {
14311   ASTContext &Context = getASTContext();
14312   Scope *CurScope = SemaRef.getCurScope();
14313 
14314   const auto *SizesClause =
14315       OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14316   if (!SizesClause ||
14317       llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; }))
14318     return StmtError();
14319   unsigned NumLoops = SizesClause->getNumSizes();
14320 
14321   // Empty statement should only be possible if there already was an error.
14322   if (!AStmt)
14323     return StmtError();
14324 
14325   // Verify and diagnose loop nest.
14326   SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
14327   Stmt *Body = nullptr;
14328   SmallVector<SmallVector<Stmt *, 0>, 4> OriginalInits;
14329   if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14330                                   OriginalInits))
14331     return StmtError();
14332 
14333   // Delay tiling to when template is completely instantiated.
14334   if (SemaRef.CurContext->isDependentContext())
14335     return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14336                                     NumLoops, AStmt, nullptr, nullptr);
14337 
14338   assert(LoopHelpers.size() == NumLoops &&
14339          "Expecting loop iteration space dimensionality to match number of "
14340          "affected loops");
14341   assert(OriginalInits.size() == NumLoops &&
14342          "Expecting loop iteration space dimensionality to match number of "
14343          "affected loops");
14344 
14345   // Collect all affected loop statements.
14346   SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14347   collectLoopStmts(AStmt, LoopStmts);
14348 
14349   SmallVector<Stmt *, 4> PreInits;
14350   CaptureVars CopyTransformer(SemaRef);
14351 
14352   // Create iteration variables for the generated loops.
14353   SmallVector<VarDecl *, 4> FloorIndVars;
14354   SmallVector<VarDecl *, 4> TileIndVars;
14355   FloorIndVars.resize(NumLoops);
14356   TileIndVars.resize(NumLoops);
14357   for (unsigned I = 0; I < NumLoops; ++I) {
14358     OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14359 
14360     assert(LoopHelper.Counters.size() == 1 &&
14361            "Expect single-dimensional loop iteration space");
14362     auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14363     std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14364     DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14365     QualType CntTy = IterVarRef->getType();
14366 
14367     // Iteration variable for the floor (i.e. outer) loop.
14368     {
14369       std::string FloorCntName =
14370           (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14371       VarDecl *FloorCntDecl =
14372           buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14373       FloorIndVars[I] = FloorCntDecl;
14374     }
14375 
14376     // Iteration variable for the tile (i.e. inner) loop.
14377     {
14378       std::string TileCntName =
14379           (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14380 
14381       // Reuse the iteration variable created by checkOpenMPLoop. It is also
14382       // used by the expressions to derive the original iteration variable's
14383       // value from the logical iteration number.
14384       auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14385       TileCntDecl->setDeclName(
14386           &SemaRef.PP.getIdentifierTable().get(TileCntName));
14387       TileIndVars[I] = TileCntDecl;
14388     }
14389 
14390     addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
14391                     PreInits);
14392   }
14393 
14394   // Once the original iteration values are set, append the innermost body.
14395   Stmt *Inner = Body;
14396 
14397   auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
14398                           SizesClause, CurScope](int I) -> Expr * {
14399     Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14400 
14401     if (DimTileSizeExpr->containsErrors())
14402       return nullptr;
14403 
14404     if (isa<ConstantExpr>(DimTileSizeExpr))
14405       return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14406 
14407     // When the tile size is not a constant but a variable, it is possible to
14408     // pass non-positive numbers. For instance:
14409     // \code{c}
14410     //   int a = 0;
14411     //   #pragma omp tile sizes(a)
14412     //   for (int i = 0; i < 42; ++i)
14413     //     body(i);
14414     // \endcode
14415     // Although there is no meaningful interpretation of the tile size, the body
14416     // should still be executed 42 times to avoid surprises. To preserve the
14417     // invariant that every loop iteration is executed exactly once and not
14418     // cause an infinite loop, apply a minimum tile size of one.
14419     // Build expr:
14420     // \code{c}
14421     //   (TS <= 0) ? 1 : TS
14422     // \endcode
14423     QualType DimTy = DimTileSizeExpr->getType();
14424     uint64_t DimWidth = Context.getTypeSize(DimTy);
14425     IntegerLiteral *Zero = IntegerLiteral::Create(
14426         Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14427     IntegerLiteral *One =
14428         IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
14429     Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
14430         CurScope, {}, BO_LE,
14431         AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
14432     Expr *MinOne = new (Context) ConditionalOperator(
14433         Cond, {}, One, {},
14434         AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14435         VK_PRValue, OK_Ordinary);
14436     return MinOne;
14437   };
14438 
14439   // Create tile loops from the inside to the outside.
14440   for (int I = NumLoops - 1; I >= 0; --I) {
14441     OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14442     Expr *NumIterations = LoopHelper.NumIterations;
14443     auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14444     QualType IVTy = NumIterations->getType();
14445     Stmt *LoopStmt = LoopStmts[I];
14446 
14447     // Commonly used variables. One of the constraints of an AST is that every
14448     // node object must appear at most once, hence we define a lambda that
14449     // creates a new AST node at every use.
14450     auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
14451                           OrigCntVar]() {
14452       return buildDeclRefExpr(SemaRef, TileIndVars[I], IVTy,
14453                               OrigCntVar->getExprLoc());
14454     };
14455 
14456     // For init-statement: auto .tile.iv = .floor.iv
14457     SemaRef.AddInitializerToDecl(
14458         TileIndVars[I],
14459         SemaRef
14460             .DefaultLvalueConversion(
14461                 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
14462             .get(),
14463         /*DirectInit=*/false);
14464     Decl *CounterDecl = TileIndVars[I];
14465     StmtResult InitStmt = new (Context)
14466         DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14467                  OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14468     if (!InitStmt.isUsable())
14469       return StmtError();
14470 
14471     // For cond-expression:
14472     //   .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
14473     Expr *DimTileSize = MakeDimTileSize(I);
14474     if (!DimTileSize)
14475       return StmtError();
14476     ExprResult EndOfTile = SemaRef.BuildBinOp(
14477         CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14478         makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14479         DimTileSize);
14480     if (!EndOfTile.isUsable())
14481       return StmtError();
14482     ExprResult IsPartialTile =
14483         SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14484                            NumIterations, EndOfTile.get());
14485     if (!IsPartialTile.isUsable())
14486       return StmtError();
14487     ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
14488         LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14489         IsPartialTile.get(), NumIterations, EndOfTile.get());
14490     if (!MinTileAndIterSpace.isUsable())
14491       return StmtError();
14492     ExprResult CondExpr =
14493         SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14494                            MakeTileIVRef(), MinTileAndIterSpace.get());
14495     if (!CondExpr.isUsable())
14496       return StmtError();
14497 
14498     // For incr-statement: ++.tile.iv
14499     ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14500         CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
14501     if (!IncrStmt.isUsable())
14502       return StmtError();
14503 
14504     // Statements to set the original iteration variable's value from the
14505     // logical iteration number.
14506     // Generated for loop is:
14507     // \code
14508     // Original_for_init;
14509     // for (auto .tile.iv = .floor.iv;
14510     //      .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
14511     //      ++.tile.iv) {
14512     //   Original_Body;
14513     //   Original_counter_update;
14514     // }
14515     // \endcode
14516     // FIXME: If the innermost body is an loop itself, inserting these
14517     // statements stops it being recognized  as a perfectly nested loop (e.g.
14518     // for applying tiling again). If this is the case, sink the expressions
14519     // further into the inner loop.
14520     SmallVector<Stmt *, 4> BodyParts;
14521     BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14522     if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14523       BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14524     BodyParts.push_back(Inner);
14525     Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
14526                                  Inner->getBeginLoc(), Inner->getEndLoc());
14527     Inner = new (Context)
14528         ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14529                 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14530                 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14531   }
14532 
14533   // Create floor loops from the inside to the outside.
14534   for (int I = NumLoops - 1; I >= 0; --I) {
14535     auto &LoopHelper = LoopHelpers[I];
14536     Expr *NumIterations = LoopHelper.NumIterations;
14537     DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14538     QualType IVTy = NumIterations->getType();
14539 
14540     // For init-statement: auto .floor.iv = 0
14541     SemaRef.AddInitializerToDecl(
14542         FloorIndVars[I],
14543         SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14544         /*DirectInit=*/false);
14545     Decl *CounterDecl = FloorIndVars[I];
14546     StmtResult InitStmt = new (Context)
14547         DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14548                  OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14549     if (!InitStmt.isUsable())
14550       return StmtError();
14551 
14552     // For cond-expression: .floor.iv < NumIterations
14553     ExprResult CondExpr = SemaRef.BuildBinOp(
14554         CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14555         makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14556         NumIterations);
14557     if (!CondExpr.isUsable())
14558       return StmtError();
14559 
14560     // For incr-statement: .floor.iv += DimTileSize
14561     Expr *DimTileSize = MakeDimTileSize(I);
14562     if (!DimTileSize)
14563       return StmtError();
14564     ExprResult IncrStmt = SemaRef.BuildBinOp(
14565         CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
14566         makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14567         DimTileSize);
14568     if (!IncrStmt.isUsable())
14569       return StmtError();
14570 
14571     Inner = new (Context)
14572         ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14573                 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14574                 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14575   }
14576 
14577   return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
14578                                   AStmt, Inner,
14579                                   buildPreInits(Context, PreInits));
14580 }
14581 
ActOnOpenMPStripeDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)14582 StmtResult SemaOpenMP::ActOnOpenMPStripeDirective(ArrayRef<OMPClause *> Clauses,
14583                                                   Stmt *AStmt,
14584                                                   SourceLocation StartLoc,
14585                                                   SourceLocation EndLoc) {
14586   ASTContext &Context = getASTContext();
14587   Scope *CurScope = SemaRef.getCurScope();
14588 
14589   const auto *SizesClause =
14590       OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14591   if (!SizesClause ||
14592       llvm::any_of(SizesClause->getSizesRefs(), [](const Expr *SizeExpr) {
14593         return !SizeExpr || SizeExpr->containsErrors();
14594       }))
14595     return StmtError();
14596   unsigned NumLoops = SizesClause->getNumSizes();
14597 
14598   // Empty statement should only be possible if there already was an error.
14599   if (!AStmt)
14600     return StmtError();
14601 
14602   // Verify and diagnose loop nest.
14603   SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
14604   Stmt *Body = nullptr;
14605   SmallVector<SmallVector<Stmt *, 0>, 4> OriginalInits;
14606   if (!checkTransformableLoopNest(OMPD_stripe, AStmt, NumLoops, LoopHelpers,
14607                                   Body, OriginalInits))
14608     return StmtError();
14609 
14610   // Delay striping to when template is completely instantiated.
14611   if (SemaRef.CurContext->isDependentContext())
14612     return OMPStripeDirective::Create(Context, StartLoc, EndLoc, Clauses,
14613                                       NumLoops, AStmt, nullptr, nullptr);
14614 
14615   assert(LoopHelpers.size() == NumLoops &&
14616          "Expecting loop iteration space dimensionality to match number of "
14617          "affected loops");
14618   assert(OriginalInits.size() == NumLoops &&
14619          "Expecting loop iteration space dimensionality to match number of "
14620          "affected loops");
14621 
14622   // Collect all affected loop statements.
14623   SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14624   collectLoopStmts(AStmt, LoopStmts);
14625 
14626   SmallVector<Stmt *, 4> PreInits;
14627   CaptureVars CopyTransformer(SemaRef);
14628 
14629   // Create iteration variables for the generated loops.
14630   SmallVector<VarDecl *, 4> FloorIndVars;
14631   SmallVector<VarDecl *, 4> StripeIndVars;
14632   FloorIndVars.resize(NumLoops);
14633   StripeIndVars.resize(NumLoops);
14634   for (unsigned I : llvm::seq<unsigned>(NumLoops)) {
14635     OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14636 
14637     assert(LoopHelper.Counters.size() == 1 &&
14638            "Expect single-dimensional loop iteration space");
14639     auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14640     std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14641     DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14642     QualType CntTy = IterVarRef->getType();
14643 
14644     // Iteration variable for the stripe (i.e. outer) loop.
14645     {
14646       std::string FloorCntName =
14647           (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14648       VarDecl *FloorCntDecl =
14649           buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14650       FloorIndVars[I] = FloorCntDecl;
14651     }
14652 
14653     // Iteration variable for the stripe (i.e. inner) loop.
14654     {
14655       std::string StripeCntName =
14656           (Twine(".stripe_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14657 
14658       // Reuse the iteration variable created by checkOpenMPLoop. It is also
14659       // used by the expressions to derive the original iteration variable's
14660       // value from the logical iteration number.
14661       auto *StripeCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14662       StripeCntDecl->setDeclName(
14663           &SemaRef.PP.getIdentifierTable().get(StripeCntName));
14664       StripeIndVars[I] = StripeCntDecl;
14665     }
14666 
14667     addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
14668                     PreInits);
14669   }
14670 
14671   // Once the original iteration values are set, append the innermost body.
14672   Stmt *Inner = Body;
14673 
14674   auto MakeDimStripeSize = [&](int I) -> Expr * {
14675     Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
14676     if (isa<ConstantExpr>(DimStripeSizeExpr))
14677       return AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr));
14678 
14679     // When the stripe size is not a constant but a variable, it is possible to
14680     // pass non-positive numbers. For instance:
14681     // \code{c}
14682     //   int a = 0;
14683     //   #pragma omp stripe sizes(a)
14684     //   for (int i = 0; i < 42; ++i)
14685     //     body(i);
14686     // \endcode
14687     // Although there is no meaningful interpretation of the stripe size, the
14688     // body should still be executed 42 times to avoid surprises. To preserve
14689     // the invariant that every loop iteration is executed exactly once and not
14690     // cause an infinite loop, apply a minimum stripe size of one.
14691     // Build expr:
14692     // \code{c}
14693     //   (TS <= 0) ? 1 : TS
14694     // \endcode
14695     QualType DimTy = DimStripeSizeExpr->getType();
14696     uint64_t DimWidth = Context.getTypeSize(DimTy);
14697     IntegerLiteral *Zero = IntegerLiteral::Create(
14698         Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14699     IntegerLiteral *One =
14700         IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
14701     Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
14702         CurScope, {}, BO_LE,
14703         AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), Zero));
14704     Expr *MinOne = new (Context) ConditionalOperator(
14705         Cond, {}, One, {},
14706         AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), DimTy,
14707         VK_PRValue, OK_Ordinary);
14708     return MinOne;
14709   };
14710 
14711   // Create stripe loops from the inside to the outside.
14712   for (int I = NumLoops - 1; I >= 0; --I) {
14713     OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14714     Expr *NumIterations = LoopHelper.NumIterations;
14715     auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14716     QualType IVTy = NumIterations->getType();
14717     Stmt *LoopStmt = LoopStmts[I];
14718 
14719     // For init-statement: auto .stripe.iv = .floor.iv
14720     SemaRef.AddInitializerToDecl(
14721         StripeIndVars[I],
14722         SemaRef
14723             .DefaultLvalueConversion(
14724                 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
14725             .get(),
14726         /*DirectInit=*/false);
14727     Decl *CounterDecl = StripeIndVars[I];
14728     StmtResult InitStmt = new (Context)
14729         DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14730                  OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14731     if (!InitStmt.isUsable())
14732       return StmtError();
14733 
14734     // For cond-expression:
14735     //   .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations)
14736     ExprResult EndOfStripe = SemaRef.BuildBinOp(
14737         CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14738         makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14739         MakeDimStripeSize(I));
14740     if (!EndOfStripe.isUsable())
14741       return StmtError();
14742     ExprResult IsPartialStripe =
14743         SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14744                            NumIterations, EndOfStripe.get());
14745     if (!IsPartialStripe.isUsable())
14746       return StmtError();
14747     ExprResult MinStripeAndIterSpace = SemaRef.ActOnConditionalOp(
14748         LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14749         IsPartialStripe.get(), NumIterations, EndOfStripe.get());
14750     if (!MinStripeAndIterSpace.isUsable())
14751       return StmtError();
14752     ExprResult CondExpr = SemaRef.BuildBinOp(
14753         CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14754         makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar),
14755         MinStripeAndIterSpace.get());
14756     if (!CondExpr.isUsable())
14757       return StmtError();
14758 
14759     // For incr-statement: ++.stripe.iv
14760     ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14761         CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc,
14762         makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar));
14763     if (!IncrStmt.isUsable())
14764       return StmtError();
14765 
14766     // Statements to set the original iteration variable's value from the
14767     // logical iteration number.
14768     // Generated for loop is:
14769     // \code
14770     // Original_for_init;
14771     // for (auto .stripe.iv = .floor.iv;
14772     //      .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations);
14773     //      ++.stripe.iv) {
14774     //   Original_Body;
14775     //   Original_counter_update;
14776     // }
14777     // \endcode
14778     // FIXME: If the innermost body is a loop itself, inserting these
14779     // statements stops it being recognized  as a perfectly nested loop (e.g.
14780     // for applying another loop transformation). If this is the case, sink the
14781     // expressions further into the inner loop.
14782     SmallVector<Stmt *, 4> BodyParts;
14783     BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14784     if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14785       BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14786     BodyParts.push_back(Inner);
14787     Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
14788                                  Inner->getBeginLoc(), Inner->getEndLoc());
14789     Inner = new (Context)
14790         ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14791                 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14792                 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14793   }
14794 
14795   // Create grid loops from the inside to the outside.
14796   for (int I = NumLoops - 1; I >= 0; --I) {
14797     auto &LoopHelper = LoopHelpers[I];
14798     Expr *NumIterations = LoopHelper.NumIterations;
14799     DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14800     QualType IVTy = NumIterations->getType();
14801 
14802     // For init-statement: auto .grid.iv = 0
14803     SemaRef.AddInitializerToDecl(
14804         FloorIndVars[I],
14805         SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14806         /*DirectInit=*/false);
14807     Decl *CounterDecl = FloorIndVars[I];
14808     StmtResult InitStmt = new (Context)
14809         DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14810                  OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14811     if (!InitStmt.isUsable())
14812       return StmtError();
14813 
14814     // For cond-expression: .floor.iv < NumIterations
14815     ExprResult CondExpr = SemaRef.BuildBinOp(
14816         CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14817         makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14818         NumIterations);
14819     if (!CondExpr.isUsable())
14820       return StmtError();
14821 
14822     // For incr-statement: .floor.iv += DimStripeSize
14823     ExprResult IncrStmt = SemaRef.BuildBinOp(
14824         CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
14825         makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14826         MakeDimStripeSize(I));
14827     if (!IncrStmt.isUsable())
14828       return StmtError();
14829 
14830     Inner = new (Context)
14831         ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14832                 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14833                 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14834   }
14835 
14836   return OMPStripeDirective::Create(Context, StartLoc, EndLoc, Clauses,
14837                                     NumLoops, AStmt, Inner,
14838                                     buildPreInits(Context, PreInits));
14839 }
14840 
ActOnOpenMPUnrollDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)14841 StmtResult SemaOpenMP::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses,
14842                                                   Stmt *AStmt,
14843                                                   SourceLocation StartLoc,
14844                                                   SourceLocation EndLoc) {
14845   ASTContext &Context = getASTContext();
14846   Scope *CurScope = SemaRef.getCurScope();
14847   // Empty statement should only be possible if there already was an error.
14848   if (!AStmt)
14849     return StmtError();
14850 
14851   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
14852                                     {OMPC_partial, OMPC_full}))
14853     return StmtError();
14854 
14855   const OMPFullClause *FullClause =
14856       OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
14857   const OMPPartialClause *PartialClause =
14858       OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
14859   assert(!(FullClause && PartialClause) &&
14860          "mutual exclusivity must have been checked before");
14861 
14862   constexpr unsigned NumLoops = 1;
14863   Stmt *Body = nullptr;
14864   SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
14865       NumLoops);
14866   SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
14867   if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
14868                                   Body, OriginalInits))
14869     return StmtError();
14870 
14871   unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
14872 
14873   // Delay unrolling to when template is completely instantiated.
14874   if (SemaRef.CurContext->isDependentContext())
14875     return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14876                                       NumGeneratedLoops, nullptr, nullptr);
14877 
14878   assert(LoopHelpers.size() == NumLoops &&
14879          "Expecting a single-dimensional loop iteration space");
14880   assert(OriginalInits.size() == NumLoops &&
14881          "Expecting a single-dimensional loop iteration space");
14882   OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
14883 
14884   if (FullClause) {
14885     if (!VerifyPositiveIntegerConstantInClause(
14886              LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
14887              /*SuppressExprDiags=*/true)
14888              .isUsable()) {
14889       Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
14890       Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
14891           << "#pragma omp unroll full";
14892       return StmtError();
14893     }
14894   }
14895 
14896   // The generated loop may only be passed to other loop-associated directive
14897   // when a partial clause is specified. Without the requirement it is
14898   // sufficient to generate loop unroll metadata at code-generation.
14899   if (NumGeneratedLoops == 0)
14900     return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14901                                       NumGeneratedLoops, nullptr, nullptr);
14902 
14903   // Otherwise, we need to provide a de-sugared/transformed AST that can be
14904   // associated with another loop directive.
14905   //
14906   // The canonical loop analysis return by checkTransformableLoopNest assumes
14907   // the following structure to be the same loop without transformations or
14908   // directives applied: \code OriginalInits; LoopHelper.PreInits;
14909   // LoopHelper.Counters;
14910   // for (; IV < LoopHelper.NumIterations; ++IV) {
14911   //   LoopHelper.Updates;
14912   //   Body;
14913   // }
14914   // \endcode
14915   // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
14916   // and referenced by LoopHelper.IterationVarRef.
14917   //
14918   // The unrolling directive transforms this into the following loop:
14919   // \code
14920   // OriginalInits;         \
14921   // LoopHelper.PreInits;    > NewPreInits
14922   // LoopHelper.Counters;   /
14923   // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
14924   //   #pragma clang loop unroll_count(Factor)
14925   //   for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
14926   //   {
14927   //     LoopHelper.Updates;
14928   //     Body;
14929   //   }
14930   // }
14931   // \endcode
14932   // where UIV is a new logical iteration counter. IV must be the same VarDecl
14933   // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
14934   // references it. If the partially unrolled loop is associated with another
14935   // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
14936   // analyze this loop, i.e. the outer loop must fulfill the constraints of an
14937   // OpenMP canonical loop. The inner loop is not an associable canonical loop
14938   // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
14939   // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
14940   // property of the OMPLoopBasedDirective instead of statements in
14941   // CompoundStatement. This is to allow the loop to become a non-outermost loop
14942   // of a canonical loop nest where these PreInits are emitted before the
14943   // outermost directive.
14944 
14945   // Find the loop statement.
14946   Stmt *LoopStmt = nullptr;
14947   collectLoopStmts(AStmt, {LoopStmt});
14948 
14949   // Determine the PreInit declarations.
14950   SmallVector<Stmt *, 4> PreInits;
14951   addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14952 
14953   auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14954   QualType IVTy = IterationVarRef->getType();
14955   assert(LoopHelper.Counters.size() == 1 &&
14956          "Expecting a single-dimensional loop iteration space");
14957   auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14958 
14959   // Determine the unroll factor.
14960   uint64_t Factor;
14961   SourceLocation FactorLoc;
14962   if (Expr *FactorVal = PartialClause->getFactor();
14963       FactorVal && !FactorVal->containsErrors()) {
14964     Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
14965     FactorLoc = FactorVal->getExprLoc();
14966   } else {
14967     // TODO: Use a better profitability model.
14968     Factor = 2;
14969   }
14970   assert(Factor > 0 && "Expected positive unroll factor");
14971   auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
14972     return IntegerLiteral::Create(
14973         getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor),
14974         IVTy, FactorLoc);
14975   };
14976 
14977   // Iteration variable SourceLocations.
14978   SourceLocation OrigVarLoc = OrigVar->getExprLoc();
14979   SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
14980   SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
14981 
14982   // Internal variable names.
14983   std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14984   std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
14985   std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
14986 
14987   // Create the iteration variable for the unrolled loop.
14988   VarDecl *OuterIVDecl =
14989       buildVarDecl(SemaRef, {}, IVTy, OuterIVName, nullptr, OrigVar);
14990   auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
14991     return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc);
14992   };
14993 
14994   // Iteration variable for the inner loop: Reuse the iteration variable created
14995   // by checkOpenMPLoop.
14996   auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14997   InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(InnerIVName));
14998   auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
14999     return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc);
15000   };
15001 
15002   // Make a copy of the NumIterations expression for each use: By the AST
15003   // constraints, every expression object in a DeclContext must be unique.
15004   CaptureVars CopyTransformer(SemaRef);
15005   auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15006     return AssertSuccess(
15007         CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15008   };
15009 
15010   // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15011   ExprResult LValueConv = SemaRef.DefaultLvalueConversion(MakeOuterRef());
15012   SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(),
15013                                /*DirectInit=*/false);
15014   StmtResult InnerInit = new (Context)
15015       DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15016   if (!InnerInit.isUsable())
15017     return StmtError();
15018 
15019   // Inner For cond-expression:
15020   // \code
15021   //   .unroll_inner.iv < .unrolled.iv + Factor &&
15022   //   .unroll_inner.iv < NumIterations
15023   // \endcode
15024   // This conjunction of two conditions allows ScalarEvolution to derive the
15025   // maximum trip count of the inner loop.
15026   ExprResult EndOfTile =
15027       SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15028                          MakeOuterRef(), MakeFactorExpr());
15029   if (!EndOfTile.isUsable())
15030     return StmtError();
15031   ExprResult InnerCond1 =
15032       SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15033                          MakeInnerRef(), EndOfTile.get());
15034   if (!InnerCond1.isUsable())
15035     return StmtError();
15036   ExprResult InnerCond2 =
15037       SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15038                          MakeInnerRef(), MakeNumIterations());
15039   if (!InnerCond2.isUsable())
15040     return StmtError();
15041   ExprResult InnerCond =
15042       SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15043                          InnerCond1.get(), InnerCond2.get());
15044   if (!InnerCond.isUsable())
15045     return StmtError();
15046 
15047   // Inner For incr-statement: ++.unroll_inner.iv
15048   ExprResult InnerIncr = SemaRef.BuildUnaryOp(
15049       CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
15050   if (!InnerIncr.isUsable())
15051     return StmtError();
15052 
15053   // Inner For statement.
15054   SmallVector<Stmt *> InnerBodyStmts;
15055   InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15056   if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15057     InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15058   InnerBodyStmts.push_back(Body);
15059   CompoundStmt *InnerBody =
15060       CompoundStmt::Create(getASTContext(), InnerBodyStmts, FPOptionsOverride(),
15061                            Body->getBeginLoc(), Body->getEndLoc());
15062   ForStmt *InnerFor = new (Context)
15063       ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15064               InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15065               LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15066 
15067   // Unroll metadata for the inner loop.
15068   // This needs to take into account the remainder portion of the unrolled loop,
15069   // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15070   // supports multiple loop exits. Instead, unroll using a factor equivalent to
15071   // the maximum trip count, which will also generate a remainder loop. Just
15072   // `unroll(enable)` (which could have been useful if the user has not
15073   // specified a concrete factor; even though the outer loop cannot be
15074   // influenced anymore, would avoid more code bloat than necessary) will refuse
15075   // the loop because "Won't unroll; remainder loop could not be generated when
15076   // assuming runtime trip count". Even if it did work, it must not choose a
15077   // larger unroll factor than the maximum loop length, or it would always just
15078   // execute the remainder loop.
15079   LoopHintAttr *UnrollHintAttr =
15080       LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15081                                    LoopHintAttr::Numeric, MakeFactorExpr());
15082   AttributedStmt *InnerUnrolled = AttributedStmt::Create(
15083       getASTContext(), StartLoc, {UnrollHintAttr}, InnerFor);
15084 
15085   // Outer For init-statement: auto .unrolled.iv = 0
15086   SemaRef.AddInitializerToDecl(
15087       OuterIVDecl,
15088       SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15089       /*DirectInit=*/false);
15090   StmtResult OuterInit = new (Context)
15091       DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15092   if (!OuterInit.isUsable())
15093     return StmtError();
15094 
15095   // Outer For cond-expression: .unrolled.iv < NumIterations
15096   ExprResult OuterConde =
15097       SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15098                          MakeOuterRef(), MakeNumIterations());
15099   if (!OuterConde.isUsable())
15100     return StmtError();
15101 
15102   // Outer For incr-statement: .unrolled.iv += Factor
15103   ExprResult OuterIncr =
15104       SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15105                          MakeOuterRef(), MakeFactorExpr());
15106   if (!OuterIncr.isUsable())
15107     return StmtError();
15108 
15109   // Outer For statement.
15110   ForStmt *OuterFor = new (Context)
15111       ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15112               OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15113               LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15114 
15115   return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15116                                     NumGeneratedLoops, OuterFor,
15117                                     buildPreInits(Context, PreInits));
15118 }
15119 
ActOnOpenMPReverseDirective(Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)15120 StmtResult SemaOpenMP::ActOnOpenMPReverseDirective(Stmt *AStmt,
15121                                                    SourceLocation StartLoc,
15122                                                    SourceLocation EndLoc) {
15123   ASTContext &Context = getASTContext();
15124   Scope *CurScope = SemaRef.getCurScope();
15125 
15126   // Empty statement should only be possible if there already was an error.
15127   if (!AStmt)
15128     return StmtError();
15129 
15130   constexpr unsigned NumLoops = 1;
15131   Stmt *Body = nullptr;
15132   SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
15133       NumLoops);
15134   SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
15135   if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
15136                                   Body, OriginalInits))
15137     return StmtError();
15138 
15139   // Delay applying the transformation to when template is completely
15140   // instantiated.
15141   if (SemaRef.CurContext->isDependentContext())
15142     return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
15143                                        NumLoops, nullptr, nullptr);
15144 
15145   assert(LoopHelpers.size() == NumLoops &&
15146          "Expecting a single-dimensional loop iteration space");
15147   assert(OriginalInits.size() == NumLoops &&
15148          "Expecting a single-dimensional loop iteration space");
15149   OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15150 
15151   // Find the loop statement.
15152   Stmt *LoopStmt = nullptr;
15153   collectLoopStmts(AStmt, {LoopStmt});
15154 
15155   // Determine the PreInit declarations.
15156   SmallVector<Stmt *> PreInits;
15157   addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15158 
15159   auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15160   QualType IVTy = IterationVarRef->getType();
15161   uint64_t IVWidth = Context.getTypeSize(IVTy);
15162   auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15163 
15164   // Iteration variable SourceLocations.
15165   SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15166   SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15167   SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15168 
15169   // Locations pointing to the transformation.
15170   SourceLocation TransformLoc = StartLoc;
15171   SourceLocation TransformLocBegin = StartLoc;
15172   SourceLocation TransformLocEnd = EndLoc;
15173 
15174   // Internal variable names.
15175   std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15176   SmallString<64> ForwardIVName(".forward.iv.");
15177   ForwardIVName += OrigVarName;
15178   SmallString<64> ReversedIVName(".reversed.iv.");
15179   ReversedIVName += OrigVarName;
15180 
15181   // LoopHelper.Updates will read the logical iteration number from
15182   // LoopHelper.IterationVarRef, compute the value of the user loop counter of
15183   // that logical iteration from it, then assign it to the user loop counter
15184   // variable. We cannot directly use LoopHelper.IterationVarRef as the
15185   // induction variable of the generated loop because it may cause an underflow:
15186   // \code{.c}
15187   //   for (unsigned i = 0; i < n; ++i)
15188   //     body(i);
15189   // \endcode
15190   //
15191   // Naive reversal:
15192   // \code{.c}
15193   //   for (unsigned i = n-1; i >= 0; --i)
15194   //     body(i);
15195   // \endcode
15196   //
15197   // Instead, we introduce a new iteration variable representing the logical
15198   // iteration counter of the original loop, convert it to the logical iteration
15199   // number of the reversed loop, then let LoopHelper.Updates compute the user's
15200   // loop iteration variable from it.
15201   // \code{.cpp}
15202   //   for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
15203   //     auto .reversed.iv = n - .forward.iv - 1;
15204   //     i = (.reversed.iv + 0) * 1;                // LoopHelper.Updates
15205   //     body(i);                                   // Body
15206   //   }
15207   // \endcode
15208 
15209   // Subexpressions with more than one use. One of the constraints of an AST is
15210   // that every node object must appear at most once, hence we define a lambda
15211   // that creates a new AST node at every use.
15212   CaptureVars CopyTransformer(SemaRef);
15213   auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15214     return AssertSuccess(
15215         CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15216   };
15217 
15218   // Create the iteration variable for the forward loop (from 0 to n-1).
15219   VarDecl *ForwardIVDecl =
15220       buildVarDecl(SemaRef, {}, IVTy, ForwardIVName, nullptr, OrigVar);
15221   auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
15222                          OrigVarLoc]() {
15223     return buildDeclRefExpr(SemaRef, ForwardIVDecl, IVTy, OrigVarLoc);
15224   };
15225 
15226   // Iteration variable for the reversed induction variable (from n-1 downto 0):
15227   // Reuse the iteration variable created by checkOpenMPLoop.
15228   auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15229   ReversedIVDecl->setDeclName(
15230       &SemaRef.PP.getIdentifierTable().get(ReversedIVName));
15231 
15232   // For init-statement:
15233   // \code{.cpp}
15234   //   auto .forward.iv = 0;
15235   // \endcode
15236   auto *Zero = IntegerLiteral::Create(Context, llvm::APInt::getZero(IVWidth),
15237                                       ForwardIVDecl->getType(), OrigVarLoc);
15238   SemaRef.AddInitializerToDecl(ForwardIVDecl, Zero, /*DirectInit=*/false);
15239   StmtResult Init = new (Context)
15240       DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15241   if (!Init.isUsable())
15242     return StmtError();
15243 
15244   // Forward iv cond-expression:
15245   // \code{.cpp}
15246   //   .forward.iv < MakeNumIterations()
15247   // \endcode
15248   ExprResult Cond =
15249       SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15250                          MakeForwardRef(), MakeNumIterations());
15251   if (!Cond.isUsable())
15252     return StmtError();
15253 
15254   // Forward incr-statement:
15255   // \code{.c}
15256   //   ++.forward.iv
15257   // \endcode
15258   ExprResult Incr = SemaRef.BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
15259                                          UO_PreInc, MakeForwardRef());
15260   if (!Incr.isUsable())
15261     return StmtError();
15262 
15263   // Reverse the forward-iv:
15264   // \code{.cpp}
15265   //   auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
15266   // \endcode
15267   auto *One = IntegerLiteral::Create(Context, llvm::APInt(IVWidth, 1), IVTy,
15268                                      TransformLoc);
15269   ExprResult Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub,
15270                                         MakeNumIterations(), One);
15271   if (!Minus.isUsable())
15272     return StmtError();
15273   Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.get(),
15274                              MakeForwardRef());
15275   if (!Minus.isUsable())
15276     return StmtError();
15277   StmtResult InitReversed = new (Context) DeclStmt(
15278       DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
15279   if (!InitReversed.isUsable())
15280     return StmtError();
15281   SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.get(),
15282                                /*DirectInit=*/false);
15283 
15284   // The new loop body.
15285   SmallVector<Stmt *, 4> BodyStmts;
15286   BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
15287                     (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
15288   BodyStmts.push_back(InitReversed.get());
15289   llvm::append_range(BodyStmts, LoopHelper.Updates);
15290   if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15291     BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15292   BodyStmts.push_back(Body);
15293   auto *ReversedBody =
15294       CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
15295                            Body->getBeginLoc(), Body->getEndLoc());
15296 
15297   // Finally create the reversed For-statement.
15298   auto *ReversedFor = new (Context)
15299       ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
15300               ReversedBody, LoopHelper.Init->getBeginLoc(),
15301               LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15302   return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt, NumLoops,
15303                                      ReversedFor,
15304                                      buildPreInits(Context, PreInits));
15305 }
15306 
ActOnOpenMPInterchangeDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)15307 StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective(
15308     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15309     SourceLocation EndLoc) {
15310   ASTContext &Context = getASTContext();
15311   DeclContext *CurContext = SemaRef.CurContext;
15312   Scope *CurScope = SemaRef.getCurScope();
15313 
15314   // Empty statement should only be possible if there already was an error.
15315   if (!AStmt)
15316     return StmtError();
15317 
15318   // interchange without permutation clause swaps two loops.
15319   const OMPPermutationClause *PermutationClause =
15320       OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
15321   size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2;
15322 
15323   // Verify and diagnose loop nest.
15324   SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
15325   Stmt *Body = nullptr;
15326   SmallVector<SmallVector<Stmt *, 0>, 2> OriginalInits;
15327   if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
15328                                   LoopHelpers, Body, OriginalInits))
15329     return StmtError();
15330 
15331   // Delay interchange to when template is completely instantiated.
15332   if (CurContext->isDependentContext())
15333     return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15334                                            NumLoops, AStmt, nullptr, nullptr);
15335 
15336   // An invalid expression in the permutation clause is set to nullptr in
15337   // ActOnOpenMPPermutationClause.
15338   if (PermutationClause &&
15339       llvm::is_contained(PermutationClause->getArgsRefs(), nullptr))
15340     return StmtError();
15341 
15342   assert(LoopHelpers.size() == NumLoops &&
15343          "Expecting loop iteration space dimensionaly to match number of "
15344          "affected loops");
15345   assert(OriginalInits.size() == NumLoops &&
15346          "Expecting loop iteration space dimensionaly to match number of "
15347          "affected loops");
15348 
15349   // Decode the permutation clause.
15350   SmallVector<uint64_t, 2> Permutation;
15351   if (!PermutationClause) {
15352     Permutation = {1, 0};
15353   } else {
15354     ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs();
15355     llvm::BitVector Flags(PermArgs.size());
15356     for (Expr *PermArg : PermArgs) {
15357       std::optional<llvm::APSInt> PermCstExpr =
15358           PermArg->getIntegerConstantExpr(Context);
15359       if (!PermCstExpr)
15360         continue;
15361       uint64_t PermInt = PermCstExpr->getZExtValue();
15362       assert(1 <= PermInt && PermInt <= NumLoops &&
15363              "Must be a permutation; diagnostic emitted in "
15364              "ActOnOpenMPPermutationClause");
15365       if (Flags[PermInt - 1]) {
15366         SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
15367         Diag(PermArg->getExprLoc(),
15368              diag::err_omp_interchange_permutation_value_repeated)
15369             << PermInt << ExprRange;
15370         continue;
15371       }
15372       Flags[PermInt - 1] = true;
15373 
15374       Permutation.push_back(PermInt - 1);
15375     }
15376 
15377     if (Permutation.size() != NumLoops)
15378       return StmtError();
15379   }
15380 
15381   // Nothing to transform with trivial permutation.
15382   if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](auto P) {
15383         auto [Idx, Arg] = P;
15384         return Idx == Arg;
15385       }))
15386     return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15387                                            NumLoops, AStmt, AStmt, nullptr);
15388 
15389   // Find the affected loops.
15390   SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15391   collectLoopStmts(AStmt, LoopStmts);
15392 
15393   // Collect pre-init statements on the order before the permuation.
15394   SmallVector<Stmt *> PreInits;
15395   for (auto I : llvm::seq<int>(NumLoops)) {
15396     OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15397 
15398     assert(LoopHelper.Counters.size() == 1 &&
15399            "Single-dimensional loop iteration space expected");
15400 
15401     addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
15402                     PreInits);
15403   }
15404 
15405   SmallVector<VarDecl *> PermutedIndVars(NumLoops);
15406   CaptureVars CopyTransformer(SemaRef);
15407 
15408   // Create the permuted loops from the inside to the outside of the
15409   // interchanged loop nest. Body of the innermost new loop is the original
15410   // innermost body.
15411   Stmt *Inner = Body;
15412   for (auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
15413     // Get the original loop that belongs to this new position.
15414     uint64_t SourceIdx = Permutation[TargetIdx];
15415     OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
15416     Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15417     assert(SourceHelper.Counters.size() == 1 &&
15418            "Single-dimensional loop iteration space expected");
15419     auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.Counters.front());
15420 
15421     // Normalized loop counter variable: From 0 to n-1, always an integer type.
15422     DeclRefExpr *IterVarRef = cast<DeclRefExpr>(SourceHelper.IterationVarRef);
15423     QualType IVTy = IterVarRef->getType();
15424     assert(IVTy->isIntegerType() &&
15425            "Expected the logical iteration counter to be an integer");
15426 
15427     std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15428     SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
15429 
15430     // Make a copy of the NumIterations expression for each use: By the AST
15431     // constraints, every expression object in a DeclContext must be unique.
15432     auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
15433       return AssertSuccess(
15434           CopyTransformer.TransformExpr(SourceHelper.NumIterations));
15435     };
15436 
15437     // Iteration variable for the permuted loop. Reuse the one from
15438     // checkOpenMPLoop which will also be used to update the original loop
15439     // variable.
15440     SmallString<64> PermutedCntName(".permuted_");
15441     PermutedCntName.append({llvm::utostr(TargetIdx), ".iv.", OrigVarName});
15442     auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15443     PermutedCntDecl->setDeclName(
15444         &SemaRef.PP.getIdentifierTable().get(PermutedCntName));
15445     PermutedIndVars[TargetIdx] = PermutedCntDecl;
15446     auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
15447       return buildDeclRefExpr(SemaRef, PermutedCntDecl, IVTy, OrigVarLoc);
15448     };
15449 
15450     // For init-statement:
15451     // \code
15452     //   auto .permuted_{target}.iv = 0
15453     // \endcode
15454     ExprResult Zero = SemaRef.ActOnIntegerConstant(OrigVarLoc, 0);
15455     if (!Zero.isUsable())
15456       return StmtError();
15457     SemaRef.AddInitializerToDecl(PermutedCntDecl, Zero.get(),
15458                                  /*DirectInit=*/false);
15459     StmtResult InitStmt = new (Context)
15460         DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
15461                  OrigCntVar->getEndLoc());
15462     if (!InitStmt.isUsable())
15463       return StmtError();
15464 
15465     // For cond-expression:
15466     // \code
15467     //   .permuted_{target}.iv < MakeNumIterations()
15468     // \endcode
15469     ExprResult CondExpr =
15470         SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
15471                            MakePermutedRef(), MakeNumIterations());
15472     if (!CondExpr.isUsable())
15473       return StmtError();
15474 
15475     // For incr-statement:
15476     // \code
15477     //   ++.tile.iv
15478     // \endcode
15479     ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15480         CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
15481     if (!IncrStmt.isUsable())
15482       return StmtError();
15483 
15484     SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
15485                                      SourceHelper.Updates.end());
15486     if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
15487       BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15488     BodyParts.push_back(Inner);
15489     Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15490                                  Inner->getBeginLoc(), Inner->getEndLoc());
15491     Inner = new (Context) ForStmt(
15492         Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
15493         SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
15494         SourceHelper.Inc->getEndLoc());
15495   }
15496 
15497   return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15498                                          NumLoops, AStmt, Inner,
15499                                          buildPreInits(Context, PreInits));
15500 }
15501 
ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,Expr * Expr,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)15502 OMPClause *SemaOpenMP::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
15503                                                    Expr *Expr,
15504                                                    SourceLocation StartLoc,
15505                                                    SourceLocation LParenLoc,
15506                                                    SourceLocation EndLoc) {
15507   OMPClause *Res = nullptr;
15508   switch (Kind) {
15509   case OMPC_final:
15510     Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
15511     break;
15512   case OMPC_safelen:
15513     Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
15514     break;
15515   case OMPC_simdlen:
15516     Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
15517     break;
15518   case OMPC_allocator:
15519     Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
15520     break;
15521   case OMPC_collapse:
15522     Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
15523     break;
15524   case OMPC_ordered:
15525     Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
15526     break;
15527   case OMPC_priority:
15528     Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
15529     break;
15530   case OMPC_hint:
15531     Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
15532     break;
15533   case OMPC_depobj:
15534     Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
15535     break;
15536   case OMPC_detach:
15537     Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
15538     break;
15539   case OMPC_novariants:
15540     Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
15541     break;
15542   case OMPC_nocontext:
15543     Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
15544     break;
15545   case OMPC_filter:
15546     Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
15547     break;
15548   case OMPC_partial:
15549     Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
15550     break;
15551   case OMPC_message:
15552     Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
15553     break;
15554   case OMPC_align:
15555     Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
15556     break;
15557   case OMPC_ompx_dyn_cgroup_mem:
15558     Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
15559     break;
15560   case OMPC_holds:
15561     Res = ActOnOpenMPHoldsClause(Expr, StartLoc, LParenLoc, EndLoc);
15562     break;
15563   case OMPC_grainsize:
15564   case OMPC_num_tasks:
15565   case OMPC_num_threads:
15566   case OMPC_device:
15567   case OMPC_if:
15568   case OMPC_default:
15569   case OMPC_proc_bind:
15570   case OMPC_schedule:
15571   case OMPC_private:
15572   case OMPC_firstprivate:
15573   case OMPC_lastprivate:
15574   case OMPC_shared:
15575   case OMPC_reduction:
15576   case OMPC_task_reduction:
15577   case OMPC_in_reduction:
15578   case OMPC_linear:
15579   case OMPC_aligned:
15580   case OMPC_copyin:
15581   case OMPC_copyprivate:
15582   case OMPC_nowait:
15583   case OMPC_untied:
15584   case OMPC_mergeable:
15585   case OMPC_threadprivate:
15586   case OMPC_sizes:
15587   case OMPC_allocate:
15588   case OMPC_flush:
15589   case OMPC_read:
15590   case OMPC_write:
15591   case OMPC_update:
15592   case OMPC_capture:
15593   case OMPC_compare:
15594   case OMPC_seq_cst:
15595   case OMPC_acq_rel:
15596   case OMPC_acquire:
15597   case OMPC_release:
15598   case OMPC_relaxed:
15599   case OMPC_depend:
15600   case OMPC_threads:
15601   case OMPC_simd:
15602   case OMPC_map:
15603   case OMPC_nogroup:
15604   case OMPC_dist_schedule:
15605   case OMPC_defaultmap:
15606   case OMPC_unknown:
15607   case OMPC_uniform:
15608   case OMPC_to:
15609   case OMPC_from:
15610   case OMPC_use_device_ptr:
15611   case OMPC_use_device_addr:
15612   case OMPC_is_device_ptr:
15613   case OMPC_unified_address:
15614   case OMPC_unified_shared_memory:
15615   case OMPC_reverse_offload:
15616   case OMPC_dynamic_allocators:
15617   case OMPC_atomic_default_mem_order:
15618   case OMPC_self_maps:
15619   case OMPC_device_type:
15620   case OMPC_match:
15621   case OMPC_nontemporal:
15622   case OMPC_order:
15623   case OMPC_at:
15624   case OMPC_severity:
15625   case OMPC_destroy:
15626   case OMPC_inclusive:
15627   case OMPC_exclusive:
15628   case OMPC_uses_allocators:
15629   case OMPC_affinity:
15630   case OMPC_when:
15631   case OMPC_bind:
15632   case OMPC_num_teams:
15633   case OMPC_thread_limit:
15634   default:
15635     llvm_unreachable("Clause is not allowed.");
15636   }
15637   return Res;
15638 }
15639 
15640 // An OpenMP directive such as 'target parallel' has two captured regions:
15641 // for the 'target' and 'parallel' respectively.  This function returns
15642 // the region in which to capture expressions associated with a clause.
15643 // A return value of OMPD_unknown signifies that the expression should not
15644 // be captured.
getOpenMPCaptureRegionForClause(OpenMPDirectiveKind DKind,OpenMPClauseKind CKind,unsigned OpenMPVersion,OpenMPDirectiveKind NameModifier=OMPD_unknown)15645 static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
15646     OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15647     OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15648   assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
15649          "Invalid directive with CKind-clause");
15650 
15651   // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
15652   if (NameModifier != OMPD_unknown &&
15653       !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
15654     return OMPD_unknown;
15655 
15656   ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(DKind);
15657 
15658   // [5.2:341:24-30]
15659   // If the clauses have expressions on them, such as for various clauses where
15660   // the argument of the clause is an expression, or lower-bound, length, or
15661   // stride expressions inside array sections (or subscript and stride
15662   // expressions in subscript-triplet for Fortran), or linear-step or alignment
15663   // expressions, the expressions are evaluated immediately before the construct
15664   // to which the clause has been split or duplicated per the above rules
15665   // (therefore inside of the outer leaf constructs). However, the expressions
15666   // inside the num_teams and thread_limit clauses are always evaluated before
15667   // the outermost leaf construct.
15668 
15669   // Process special cases first.
15670   switch (CKind) {
15671   case OMPC_if:
15672     switch (DKind) {
15673     case OMPD_teams_loop:
15674     case OMPD_target_teams_loop:
15675       // For [target] teams loop, assume capture region is 'teams' so it's
15676       // available for codegen later to use if/when necessary.
15677       return OMPD_teams;
15678     case OMPD_target_update:
15679     case OMPD_target_enter_data:
15680     case OMPD_target_exit_data:
15681       return OMPD_task;
15682     default:
15683       break;
15684     }
15685     break;
15686   case OMPC_num_teams:
15687   case OMPC_thread_limit:
15688   case OMPC_ompx_dyn_cgroup_mem:
15689     if (Leafs[0] == OMPD_target)
15690       return OMPD_target;
15691     break;
15692   case OMPC_device:
15693     if (Leafs[0] == OMPD_target ||
15694         llvm::is_contained({OMPD_dispatch, OMPD_target_update,
15695                             OMPD_target_enter_data, OMPD_target_exit_data},
15696                            DKind))
15697       return OMPD_task;
15698     break;
15699   case OMPC_novariants:
15700   case OMPC_nocontext:
15701     if (DKind == OMPD_dispatch)
15702       return OMPD_task;
15703     break;
15704   case OMPC_when:
15705     if (DKind == OMPD_metadirective)
15706       return OMPD_metadirective;
15707     break;
15708   case OMPC_filter:
15709     return OMPD_unknown;
15710   default:
15711     break;
15712   }
15713 
15714   // If none of the special cases above applied, and DKind is a capturing
15715   // directive, find the innermost enclosing leaf construct that allows the
15716   // clause, and returns the corresponding capture region.
15717 
15718   auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
15719     // Find the index in "Leafs" of the last leaf that allows the given
15720     // clause. The search will only include indexes [0, EndIdx).
15721     // EndIdx may be set to the index of the NameModifier, if present.
15722     int InnermostIdx = [&]() {
15723       for (int I = EndIdx - 1; I >= 0; --I) {
15724         if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
15725           return I;
15726       }
15727       return -1;
15728     }();
15729 
15730     // Find the nearest enclosing capture region.
15731     SmallVector<OpenMPDirectiveKind, 2> Regions;
15732     for (int I = InnermostIdx - 1; I >= 0; --I) {
15733       if (!isOpenMPCapturingDirective(Leafs[I]))
15734         continue;
15735       Regions.clear();
15736       getOpenMPCaptureRegions(Regions, Leafs[I]);
15737       if (Regions[0] != OMPD_unknown)
15738         return Regions.back();
15739     }
15740     return OMPD_unknown;
15741   };
15742 
15743   if (isOpenMPCapturingDirective(DKind)) {
15744     auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
15745       for (int I = 0, E = Leafs.size(); I != E; ++I) {
15746         if (Leafs[I] == Dir)
15747           return I + 1;
15748       }
15749       return 0;
15750     };
15751 
15752     int End = NameModifier == OMPD_unknown ? Leafs.size()
15753                                            : GetLeafIndex(NameModifier);
15754     return GetEnclosingRegion(End, CKind);
15755   }
15756 
15757   return OMPD_unknown;
15758 }
15759 
ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,Expr * Condition,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation NameModifierLoc,SourceLocation ColonLoc,SourceLocation EndLoc)15760 OMPClause *SemaOpenMP::ActOnOpenMPIfClause(
15761     OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
15762     SourceLocation LParenLoc, SourceLocation NameModifierLoc,
15763     SourceLocation ColonLoc, SourceLocation EndLoc) {
15764   Expr *ValExpr = Condition;
15765   Stmt *HelperValStmt = nullptr;
15766   OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15767   if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
15768       !Condition->isInstantiationDependent() &&
15769       !Condition->containsUnexpandedParameterPack()) {
15770     ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
15771     if (Val.isInvalid())
15772       return nullptr;
15773 
15774     ValExpr = Val.get();
15775 
15776     OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15777     CaptureRegion = getOpenMPCaptureRegionForClause(
15778         DKind, OMPC_if, getLangOpts().OpenMP, NameModifier);
15779     if (CaptureRegion != OMPD_unknown &&
15780         !SemaRef.CurContext->isDependentContext()) {
15781       ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15782       llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15783       ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15784       HelperValStmt = buildPreInits(getASTContext(), Captures);
15785     }
15786   }
15787 
15788   return new (getASTContext())
15789       OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
15790                   LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
15791 }
15792 
ActOnOpenMPFinalClause(Expr * Condition,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)15793 OMPClause *SemaOpenMP::ActOnOpenMPFinalClause(Expr *Condition,
15794                                               SourceLocation StartLoc,
15795                                               SourceLocation LParenLoc,
15796                                               SourceLocation EndLoc) {
15797   Expr *ValExpr = Condition;
15798   Stmt *HelperValStmt = nullptr;
15799   OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15800   if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
15801       !Condition->isInstantiationDependent() &&
15802       !Condition->containsUnexpandedParameterPack()) {
15803     ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
15804     if (Val.isInvalid())
15805       return nullptr;
15806 
15807     ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
15808 
15809     OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15810     CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final,
15811                                                     getLangOpts().OpenMP);
15812     if (CaptureRegion != OMPD_unknown &&
15813         !SemaRef.CurContext->isDependentContext()) {
15814       ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15815       llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15816       ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15817       HelperValStmt = buildPreInits(getASTContext(), Captures);
15818     }
15819   }
15820 
15821   return new (getASTContext()) OMPFinalClause(
15822       ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15823 }
15824 
15825 ExprResult
PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,Expr * Op)15826 SemaOpenMP::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
15827                                                    Expr *Op) {
15828   if (!Op)
15829     return ExprError();
15830 
15831   class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
15832   public:
15833     IntConvertDiagnoser()
15834         : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {}
15835     SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
15836                                          QualType T) override {
15837       return S.Diag(Loc, diag::err_omp_not_integral) << T;
15838     }
15839     SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
15840                                              QualType T) override {
15841       return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
15842     }
15843     SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
15844                                                QualType T,
15845                                                QualType ConvTy) override {
15846       return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
15847     }
15848     SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
15849                                            QualType ConvTy) override {
15850       return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
15851              << ConvTy->isEnumeralType() << ConvTy;
15852     }
15853     SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
15854                                             QualType T) override {
15855       return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
15856     }
15857     SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
15858                                         QualType ConvTy) override {
15859       return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
15860              << ConvTy->isEnumeralType() << ConvTy;
15861     }
15862     SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
15863                                              QualType) override {
15864       llvm_unreachable("conversion functions are permitted");
15865     }
15866   } ConvertDiagnoser;
15867   return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
15868 }
15869 
15870 static bool
isNonNegativeIntegerValue(Expr * & ValExpr,Sema & SemaRef,OpenMPClauseKind CKind,bool StrictlyPositive,bool BuildCapture=false,OpenMPDirectiveKind DKind=OMPD_unknown,OpenMPDirectiveKind * CaptureRegion=nullptr,Stmt ** HelperValStmt=nullptr)15871 isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind,
15872                           bool StrictlyPositive, bool BuildCapture = false,
15873                           OpenMPDirectiveKind DKind = OMPD_unknown,
15874                           OpenMPDirectiveKind *CaptureRegion = nullptr,
15875                           Stmt **HelperValStmt = nullptr) {
15876   if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
15877       !ValExpr->isInstantiationDependent()) {
15878     SourceLocation Loc = ValExpr->getExprLoc();
15879     ExprResult Value =
15880         SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
15881     if (Value.isInvalid())
15882       return false;
15883 
15884     ValExpr = Value.get();
15885     // The expression must evaluate to a non-negative integer value.
15886     if (std::optional<llvm::APSInt> Result =
15887             ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
15888       if (Result->isSigned() &&
15889           !((!StrictlyPositive && Result->isNonNegative()) ||
15890             (StrictlyPositive && Result->isStrictlyPositive()))) {
15891         SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
15892             << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
15893             << ValExpr->getSourceRange();
15894         return false;
15895       }
15896     }
15897     if (!BuildCapture)
15898       return true;
15899     *CaptureRegion =
15900         getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
15901     if (*CaptureRegion != OMPD_unknown &&
15902         !SemaRef.CurContext->isDependentContext()) {
15903       ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15904       llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15905       ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15906       *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
15907     }
15908   }
15909   return true;
15910 }
15911 
getListOfPossibleValues(OpenMPClauseKind K,unsigned First,unsigned Last,ArrayRef<unsigned> Exclude={})15912 static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First,
15913                                            unsigned Last,
15914                                            ArrayRef<unsigned> Exclude = {}) {
15915   SmallString<256> Buffer;
15916   llvm::raw_svector_ostream Out(Buffer);
15917   unsigned Skipped = Exclude.size();
15918   for (unsigned I = First; I < Last; ++I) {
15919     if (llvm::is_contained(Exclude, I)) {
15920       --Skipped;
15921       continue;
15922     }
15923     Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
15924     if (I + Skipped + 2 == Last)
15925       Out << " or ";
15926     else if (I + Skipped + 1 != Last)
15927       Out << ", ";
15928   }
15929   return std::string(Out.str());
15930 }
15931 
ActOnOpenMPNumThreadsClause(OpenMPNumThreadsClauseModifier Modifier,Expr * NumThreads,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ModifierLoc,SourceLocation EndLoc)15932 OMPClause *SemaOpenMP::ActOnOpenMPNumThreadsClause(
15933     OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads,
15934     SourceLocation StartLoc, SourceLocation LParenLoc,
15935     SourceLocation ModifierLoc, SourceLocation EndLoc) {
15936   assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 60) &&
15937          "Unexpected num_threads modifier in OpenMP < 60.");
15938 
15939   if (ModifierLoc.isValid() && Modifier == OMPC_NUMTHREADS_unknown) {
15940     std::string Values = getListOfPossibleValues(OMPC_num_threads, /*First=*/0,
15941                                                  OMPC_NUMTHREADS_unknown);
15942     Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
15943         << Values << getOpenMPClauseNameForDiag(OMPC_num_threads);
15944     return nullptr;
15945   }
15946 
15947   Expr *ValExpr = NumThreads;
15948   Stmt *HelperValStmt = nullptr;
15949 
15950   // OpenMP [2.5, Restrictions]
15951   //  The num_threads expression must evaluate to a positive integer value.
15952   if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads,
15953                                  /*StrictlyPositive=*/true))
15954     return nullptr;
15955 
15956   OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15957   OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
15958       DKind, OMPC_num_threads, getLangOpts().OpenMP);
15959   if (CaptureRegion != OMPD_unknown &&
15960       !SemaRef.CurContext->isDependentContext()) {
15961     ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15962     llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15963     ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15964     HelperValStmt = buildPreInits(getASTContext(), Captures);
15965   }
15966 
15967   return new (getASTContext())
15968       OMPNumThreadsClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
15969                           StartLoc, LParenLoc, ModifierLoc, EndLoc);
15970 }
15971 
VerifyPositiveIntegerConstantInClause(Expr * E,OpenMPClauseKind CKind,bool StrictlyPositive,bool SuppressExprDiags)15972 ExprResult SemaOpenMP::VerifyPositiveIntegerConstantInClause(
15973     Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
15974     bool SuppressExprDiags) {
15975   if (!E)
15976     return ExprError();
15977   if (E->isValueDependent() || E->isTypeDependent() ||
15978       E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
15979     return E;
15980 
15981   llvm::APSInt Result;
15982   ExprResult ICE;
15983   if (SuppressExprDiags) {
15984     // Use a custom diagnoser that suppresses 'note' diagnostics about the
15985     // expression.
15986     struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
15987       SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
15988       SemaBase::SemaDiagnosticBuilder
15989       diagnoseNotICE(Sema &S, SourceLocation Loc) override {
15990         llvm_unreachable("Diagnostic suppressed");
15991       }
15992     } Diagnoser;
15993     ICE = SemaRef.VerifyIntegerConstantExpression(E, &Result, Diagnoser,
15994                                                   AllowFoldKind::Allow);
15995   } else {
15996     ICE =
15997         SemaRef.VerifyIntegerConstantExpression(E, &Result,
15998                                                 /*FIXME*/ AllowFoldKind::Allow);
15999   }
16000   if (ICE.isInvalid())
16001     return ExprError();
16002 
16003   if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
16004       (!StrictlyPositive && !Result.isNonNegative())) {
16005     Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
16006         << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
16007         << E->getSourceRange();
16008     return ExprError();
16009   }
16010   if ((CKind == OMPC_aligned || CKind == OMPC_align ||
16011        CKind == OMPC_allocate) &&
16012       !Result.isPowerOf2()) {
16013     Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
16014         << E->getSourceRange();
16015     return ExprError();
16016   }
16017 
16018   if (!Result.isRepresentableByInt64()) {
16019     Diag(E->getExprLoc(), diag::err_omp_large_expression_in_clause)
16020         << getOpenMPClauseNameForDiag(CKind) << E->getSourceRange();
16021     return ExprError();
16022   }
16023 
16024   if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
16025     DSAStack->setAssociatedLoops(Result.getExtValue());
16026   else if (CKind == OMPC_ordered)
16027     DSAStack->setAssociatedLoops(Result.getExtValue());
16028   return ICE;
16029 }
16030 
setOpenMPDeviceNum(int Num)16031 void SemaOpenMP::setOpenMPDeviceNum(int Num) { DeviceNum = Num; }
16032 
setOpenMPDeviceNumID(StringRef ID)16033 void SemaOpenMP::setOpenMPDeviceNumID(StringRef ID) { DeviceNumID = ID; }
16034 
getOpenMPDeviceNum() const16035 int SemaOpenMP::getOpenMPDeviceNum() const { return DeviceNum; }
16036 
ActOnOpenMPDeviceNum(Expr * DeviceNumExpr)16037 void SemaOpenMP::ActOnOpenMPDeviceNum(Expr *DeviceNumExpr) {
16038   llvm::APSInt Result;
16039   Expr::EvalResult EvalResult;
16040   // Evaluate the expression to an integer value
16041   if (!DeviceNumExpr->isValueDependent() &&
16042       DeviceNumExpr->EvaluateAsInt(EvalResult, SemaRef.Context)) {
16043     // The device expression must evaluate to a non-negative integer value.
16044     Result = EvalResult.Val.getInt();
16045     if (Result.isNonNegative()) {
16046       setOpenMPDeviceNum(Result.getZExtValue());
16047     } else {
16048       Diag(DeviceNumExpr->getExprLoc(),
16049            diag::err_omp_negative_expression_in_clause)
16050           << "device_num" << 0 << DeviceNumExpr->getSourceRange();
16051     }
16052   } else if (auto *DeclRef = dyn_cast<DeclRefExpr>(DeviceNumExpr)) {
16053     // Check if the expression is an identifier
16054     IdentifierInfo *IdInfo = DeclRef->getDecl()->getIdentifier();
16055     if (IdInfo) {
16056       setOpenMPDeviceNumID(IdInfo->getName());
16057     }
16058   } else {
16059     Diag(DeviceNumExpr->getExprLoc(), diag::err_expected_expression);
16060   }
16061 }
16062 
ActOnOpenMPSafelenClause(Expr * Len,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16063 OMPClause *SemaOpenMP::ActOnOpenMPSafelenClause(Expr *Len,
16064                                                 SourceLocation StartLoc,
16065                                                 SourceLocation LParenLoc,
16066                                                 SourceLocation EndLoc) {
16067   // OpenMP [2.8.1, simd construct, Description]
16068   // The parameter of the safelen clause must be a constant
16069   // positive integer expression.
16070   ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
16071   if (Safelen.isInvalid())
16072     return nullptr;
16073   return new (getASTContext())
16074       OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
16075 }
16076 
ActOnOpenMPSimdlenClause(Expr * Len,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16077 OMPClause *SemaOpenMP::ActOnOpenMPSimdlenClause(Expr *Len,
16078                                                 SourceLocation StartLoc,
16079                                                 SourceLocation LParenLoc,
16080                                                 SourceLocation EndLoc) {
16081   // OpenMP [2.8.1, simd construct, Description]
16082   // The parameter of the simdlen clause must be a constant
16083   // positive integer expression.
16084   ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
16085   if (Simdlen.isInvalid())
16086     return nullptr;
16087   return new (getASTContext())
16088       OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
16089 }
16090 
16091 /// Tries to find omp_allocator_handle_t type.
findOMPAllocatorHandleT(Sema & S,SourceLocation Loc,DSAStackTy * Stack)16092 static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc,
16093                                     DSAStackTy *Stack) {
16094   if (!Stack->getOMPAllocatorHandleT().isNull())
16095     return true;
16096 
16097   // Set the allocator handle type.
16098   IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
16099   ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
16100   if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
16101     S.Diag(Loc, diag::err_omp_implied_type_not_found)
16102         << "omp_allocator_handle_t";
16103     return false;
16104   }
16105   QualType AllocatorHandleEnumTy = PT.get();
16106   AllocatorHandleEnumTy.addConst();
16107   Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
16108 
16109   // Fill the predefined allocator map.
16110   bool ErrorFound = false;
16111   for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
16112     auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
16113     StringRef Allocator =
16114         OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
16115     DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
16116     auto *VD = dyn_cast_or_null<ValueDecl>(
16117         S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
16118     if (!VD) {
16119       ErrorFound = true;
16120       break;
16121     }
16122     QualType AllocatorType =
16123         VD->getType().getNonLValueExprType(S.getASTContext());
16124     ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
16125     if (!Res.isUsable()) {
16126       ErrorFound = true;
16127       break;
16128     }
16129     Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
16130                                       AssignmentAction::Initializing,
16131                                       /*AllowExplicit=*/true);
16132     if (!Res.isUsable()) {
16133       ErrorFound = true;
16134       break;
16135     }
16136     Stack->setAllocator(AllocatorKind, Res.get());
16137   }
16138   if (ErrorFound) {
16139     S.Diag(Loc, diag::err_omp_implied_type_not_found)
16140         << "omp_allocator_handle_t";
16141     return false;
16142   }
16143 
16144   return true;
16145 }
16146 
ActOnOpenMPAllocatorClause(Expr * A,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16147 OMPClause *SemaOpenMP::ActOnOpenMPAllocatorClause(Expr *A,
16148                                                   SourceLocation StartLoc,
16149                                                   SourceLocation LParenLoc,
16150                                                   SourceLocation EndLoc) {
16151   // OpenMP [2.11.3, allocate Directive, Description]
16152   // allocator is an expression of omp_allocator_handle_t type.
16153   if (!findOMPAllocatorHandleT(SemaRef, A->getExprLoc(), DSAStack))
16154     return nullptr;
16155 
16156   ExprResult Allocator = SemaRef.DefaultLvalueConversion(A);
16157   if (Allocator.isInvalid())
16158     return nullptr;
16159   Allocator = SemaRef.PerformImplicitConversion(
16160       Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
16161       AssignmentAction::Initializing,
16162       /*AllowExplicit=*/true);
16163   if (Allocator.isInvalid())
16164     return nullptr;
16165   return new (getASTContext())
16166       OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
16167 }
16168 
ActOnOpenMPCollapseClause(Expr * NumForLoops,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16169 OMPClause *SemaOpenMP::ActOnOpenMPCollapseClause(Expr *NumForLoops,
16170                                                  SourceLocation StartLoc,
16171                                                  SourceLocation LParenLoc,
16172                                                  SourceLocation EndLoc) {
16173   // OpenMP [2.7.1, loop construct, Description]
16174   // OpenMP [2.8.1, simd construct, Description]
16175   // OpenMP [2.9.6, distribute construct, Description]
16176   // The parameter of the collapse clause must be a constant
16177   // positive integer expression.
16178   ExprResult NumForLoopsResult =
16179       VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
16180   if (NumForLoopsResult.isInvalid())
16181     return nullptr;
16182   return new (getASTContext())
16183       OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
16184 }
16185 
ActOnOpenMPOrderedClause(SourceLocation StartLoc,SourceLocation EndLoc,SourceLocation LParenLoc,Expr * NumForLoops)16186 OMPClause *SemaOpenMP::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
16187                                                 SourceLocation EndLoc,
16188                                                 SourceLocation LParenLoc,
16189                                                 Expr *NumForLoops) {
16190   // OpenMP [2.7.1, loop construct, Description]
16191   // OpenMP [2.8.1, simd construct, Description]
16192   // OpenMP [2.9.6, distribute construct, Description]
16193   // The parameter of the ordered clause must be a constant
16194   // positive integer expression if any.
16195   if (NumForLoops && LParenLoc.isValid()) {
16196     ExprResult NumForLoopsResult =
16197         VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
16198     if (NumForLoopsResult.isInvalid())
16199       return nullptr;
16200     NumForLoops = NumForLoopsResult.get();
16201   } else {
16202     NumForLoops = nullptr;
16203   }
16204   auto *Clause =
16205       OMPOrderedClause::Create(getASTContext(), NumForLoops,
16206                                NumForLoops ? DSAStack->getAssociatedLoops() : 0,
16207                                StartLoc, LParenLoc, EndLoc);
16208   DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
16209   return Clause;
16210 }
16211 
ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,unsigned Argument,SourceLocation ArgumentLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16212 OMPClause *SemaOpenMP::ActOnOpenMPSimpleClause(
16213     OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
16214     SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16215   OMPClause *Res = nullptr;
16216   switch (Kind) {
16217   case OMPC_default:
16218     Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument),
16219                                    ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16220     break;
16221   case OMPC_proc_bind:
16222     Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
16223                                     ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16224     break;
16225   case OMPC_atomic_default_mem_order:
16226     Res = ActOnOpenMPAtomicDefaultMemOrderClause(
16227         static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
16228         ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16229     break;
16230   case OMPC_fail:
16231     Res = ActOnOpenMPFailClause(static_cast<OpenMPClauseKind>(Argument),
16232                                 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16233     break;
16234   case OMPC_update:
16235     Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
16236                                   ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16237     break;
16238   case OMPC_bind:
16239     Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
16240                                 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16241     break;
16242   case OMPC_at:
16243     Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
16244                               ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16245     break;
16246   case OMPC_severity:
16247     Res = ActOnOpenMPSeverityClause(
16248         static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
16249         LParenLoc, EndLoc);
16250     break;
16251   case OMPC_if:
16252   case OMPC_final:
16253   case OMPC_num_threads:
16254   case OMPC_safelen:
16255   case OMPC_simdlen:
16256   case OMPC_sizes:
16257   case OMPC_allocator:
16258   case OMPC_collapse:
16259   case OMPC_schedule:
16260   case OMPC_private:
16261   case OMPC_firstprivate:
16262   case OMPC_lastprivate:
16263   case OMPC_shared:
16264   case OMPC_reduction:
16265   case OMPC_task_reduction:
16266   case OMPC_in_reduction:
16267   case OMPC_linear:
16268   case OMPC_aligned:
16269   case OMPC_copyin:
16270   case OMPC_copyprivate:
16271   case OMPC_ordered:
16272   case OMPC_nowait:
16273   case OMPC_untied:
16274   case OMPC_mergeable:
16275   case OMPC_threadprivate:
16276   case OMPC_allocate:
16277   case OMPC_flush:
16278   case OMPC_depobj:
16279   case OMPC_read:
16280   case OMPC_write:
16281   case OMPC_capture:
16282   case OMPC_compare:
16283   case OMPC_seq_cst:
16284   case OMPC_acq_rel:
16285   case OMPC_acquire:
16286   case OMPC_release:
16287   case OMPC_relaxed:
16288   case OMPC_depend:
16289   case OMPC_device:
16290   case OMPC_threads:
16291   case OMPC_simd:
16292   case OMPC_map:
16293   case OMPC_num_teams:
16294   case OMPC_thread_limit:
16295   case OMPC_priority:
16296   case OMPC_grainsize:
16297   case OMPC_nogroup:
16298   case OMPC_num_tasks:
16299   case OMPC_hint:
16300   case OMPC_dist_schedule:
16301   case OMPC_defaultmap:
16302   case OMPC_unknown:
16303   case OMPC_uniform:
16304   case OMPC_to:
16305   case OMPC_from:
16306   case OMPC_use_device_ptr:
16307   case OMPC_use_device_addr:
16308   case OMPC_is_device_ptr:
16309   case OMPC_has_device_addr:
16310   case OMPC_unified_address:
16311   case OMPC_unified_shared_memory:
16312   case OMPC_reverse_offload:
16313   case OMPC_dynamic_allocators:
16314   case OMPC_self_maps:
16315   case OMPC_device_type:
16316   case OMPC_match:
16317   case OMPC_nontemporal:
16318   case OMPC_destroy:
16319   case OMPC_novariants:
16320   case OMPC_nocontext:
16321   case OMPC_detach:
16322   case OMPC_inclusive:
16323   case OMPC_exclusive:
16324   case OMPC_uses_allocators:
16325   case OMPC_affinity:
16326   case OMPC_when:
16327   case OMPC_message:
16328   default:
16329     llvm_unreachable("Clause is not allowed.");
16330   }
16331   return Res;
16332 }
16333 
ActOnOpenMPDefaultClause(DefaultKind Kind,SourceLocation KindKwLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16334 OMPClause *SemaOpenMP::ActOnOpenMPDefaultClause(DefaultKind Kind,
16335                                                 SourceLocation KindKwLoc,
16336                                                 SourceLocation StartLoc,
16337                                                 SourceLocation LParenLoc,
16338                                                 SourceLocation EndLoc) {
16339   if (Kind == OMP_DEFAULT_unknown) {
16340     Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16341         << getListOfPossibleValues(OMPC_default, /*First=*/0,
16342                                    /*Last=*/unsigned(OMP_DEFAULT_unknown))
16343         << getOpenMPClauseNameForDiag(OMPC_default);
16344     return nullptr;
16345   }
16346 
16347   switch (Kind) {
16348   case OMP_DEFAULT_none:
16349     DSAStack->setDefaultDSANone(KindKwLoc);
16350     break;
16351   case OMP_DEFAULT_shared:
16352     DSAStack->setDefaultDSAShared(KindKwLoc);
16353     break;
16354   case OMP_DEFAULT_firstprivate:
16355     DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
16356     break;
16357   case OMP_DEFAULT_private:
16358     DSAStack->setDefaultDSAPrivate(KindKwLoc);
16359     break;
16360   default:
16361     llvm_unreachable("DSA unexpected in OpenMP default clause");
16362   }
16363 
16364   return new (getASTContext())
16365       OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16366 }
16367 
ActOnOpenMPProcBindClause(ProcBindKind Kind,SourceLocation KindKwLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16368 OMPClause *SemaOpenMP::ActOnOpenMPProcBindClause(ProcBindKind Kind,
16369                                                  SourceLocation KindKwLoc,
16370                                                  SourceLocation StartLoc,
16371                                                  SourceLocation LParenLoc,
16372                                                  SourceLocation EndLoc) {
16373   if (Kind == OMP_PROC_BIND_unknown) {
16374     Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16375         << getListOfPossibleValues(OMPC_proc_bind,
16376                                    /*First=*/unsigned(OMP_PROC_BIND_master),
16377                                    /*Last=*/
16378                                    unsigned(getLangOpts().OpenMP > 50
16379                                                 ? OMP_PROC_BIND_primary
16380                                                 : OMP_PROC_BIND_spread) +
16381                                        1)
16382         << getOpenMPClauseNameForDiag(OMPC_proc_bind);
16383     return nullptr;
16384   }
16385   if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
16386     Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16387         << getListOfPossibleValues(OMPC_proc_bind,
16388                                    /*First=*/unsigned(OMP_PROC_BIND_master),
16389                                    /*Last=*/
16390                                    unsigned(OMP_PROC_BIND_spread) + 1)
16391         << getOpenMPClauseNameForDiag(OMPC_proc_bind);
16392   return new (getASTContext())
16393       OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16394 }
16395 
ActOnOpenMPAtomicDefaultMemOrderClause(OpenMPAtomicDefaultMemOrderClauseKind Kind,SourceLocation KindKwLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16396 OMPClause *SemaOpenMP::ActOnOpenMPAtomicDefaultMemOrderClause(
16397     OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindKwLoc,
16398     SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16399   if (Kind == OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) {
16400     Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16401         << getListOfPossibleValues(
16402                OMPC_atomic_default_mem_order, /*First=*/0,
16403                /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown)
16404         << getOpenMPClauseNameForDiag(OMPC_atomic_default_mem_order);
16405     return nullptr;
16406   }
16407   return new (getASTContext()) OMPAtomicDefaultMemOrderClause(
16408       Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16409 }
16410 
ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,SourceLocation KindKwLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16411 OMPClause *SemaOpenMP::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
16412                                            SourceLocation KindKwLoc,
16413                                            SourceLocation StartLoc,
16414                                            SourceLocation LParenLoc,
16415                                            SourceLocation EndLoc) {
16416   if (Kind == OMPC_AT_unknown) {
16417     Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16418         << getListOfPossibleValues(OMPC_at, /*First=*/0,
16419                                    /*Last=*/OMPC_AT_unknown)
16420         << getOpenMPClauseNameForDiag(OMPC_at);
16421     return nullptr;
16422   }
16423   return new (getASTContext())
16424       OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16425 }
16426 
ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,SourceLocation KindKwLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16427 OMPClause *SemaOpenMP::ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,
16428                                                  SourceLocation KindKwLoc,
16429                                                  SourceLocation StartLoc,
16430                                                  SourceLocation LParenLoc,
16431                                                  SourceLocation EndLoc) {
16432   if (Kind == OMPC_SEVERITY_unknown) {
16433     Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16434         << getListOfPossibleValues(OMPC_severity, /*First=*/0,
16435                                    /*Last=*/OMPC_SEVERITY_unknown)
16436         << getOpenMPClauseNameForDiag(OMPC_severity);
16437     return nullptr;
16438   }
16439   return new (getASTContext())
16440       OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16441 }
16442 
ActOnOpenMPMessageClause(Expr * ME,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16443 OMPClause *SemaOpenMP::ActOnOpenMPMessageClause(Expr *ME,
16444                                                 SourceLocation StartLoc,
16445                                                 SourceLocation LParenLoc,
16446                                                 SourceLocation EndLoc) {
16447   assert(ME && "NULL expr in Message clause");
16448   if (!isa<StringLiteral>(ME)) {
16449     Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
16450         << getOpenMPClauseNameForDiag(OMPC_message);
16451     return nullptr;
16452   }
16453   return new (getASTContext())
16454       OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc);
16455 }
16456 
ActOnOpenMPOrderClause(OpenMPOrderClauseModifier Modifier,OpenMPOrderClauseKind Kind,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation MLoc,SourceLocation KindLoc,SourceLocation EndLoc)16457 OMPClause *SemaOpenMP::ActOnOpenMPOrderClause(
16458     OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind,
16459     SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
16460     SourceLocation KindLoc, SourceLocation EndLoc) {
16461   if (Kind != OMPC_ORDER_concurrent ||
16462       (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
16463     // Kind should be concurrent,
16464     // Modifiers introduced in OpenMP 5.1
16465     static_assert(OMPC_ORDER_unknown > 0,
16466                   "OMPC_ORDER_unknown not greater than 0");
16467 
16468     Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16469         << getListOfPossibleValues(OMPC_order,
16470                                    /*First=*/0,
16471                                    /*Last=*/OMPC_ORDER_unknown)
16472         << getOpenMPClauseNameForDiag(OMPC_order);
16473     return nullptr;
16474   }
16475   if (getLangOpts().OpenMP >= 51 && Modifier == OMPC_ORDER_MODIFIER_unknown &&
16476       MLoc.isValid()) {
16477     Diag(MLoc, diag::err_omp_unexpected_clause_value)
16478         << getListOfPossibleValues(OMPC_order,
16479                                    /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
16480                                    /*Last=*/OMPC_ORDER_MODIFIER_last)
16481         << getOpenMPClauseNameForDiag(OMPC_order);
16482   } else if (getLangOpts().OpenMP >= 50) {
16483     DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
16484     if (DSAStack->getCurScope()) {
16485       // mark the current scope with 'order' flag
16486       unsigned existingFlags = DSAStack->getCurScope()->getFlags();
16487       DSAStack->getCurScope()->setFlags(existingFlags |
16488                                         Scope::OpenMPOrderClauseScope);
16489     }
16490   }
16491   return new (getASTContext()) OMPOrderClause(
16492       Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
16493 }
16494 
ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind,SourceLocation KindKwLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16495 OMPClause *SemaOpenMP::ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind,
16496                                                SourceLocation KindKwLoc,
16497                                                SourceLocation StartLoc,
16498                                                SourceLocation LParenLoc,
16499                                                SourceLocation EndLoc) {
16500   if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
16501       Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
16502     SmallVector<unsigned> Except = {
16503         OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
16504         OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
16505     if (getLangOpts().OpenMP < 51)
16506       Except.push_back(OMPC_DEPEND_inoutset);
16507     Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16508         << getListOfPossibleValues(OMPC_depend, /*First=*/0,
16509                                    /*Last=*/OMPC_DEPEND_unknown, Except)
16510         << getOpenMPClauseNameForDiag(OMPC_update);
16511     return nullptr;
16512   }
16513   return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc,
16514                                  KindKwLoc, Kind, EndLoc);
16515 }
16516 
ActOnOpenMPSizesClause(ArrayRef<Expr * > SizeExprs,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16517 OMPClause *SemaOpenMP::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs,
16518                                               SourceLocation StartLoc,
16519                                               SourceLocation LParenLoc,
16520                                               SourceLocation EndLoc) {
16521   SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
16522 
16523   for (Expr *&SizeExpr : SanitizedSizeExprs) {
16524     // Skip if already sanitized, e.g. during a partial template instantiation.
16525     if (!SizeExpr)
16526       continue;
16527 
16528     bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes,
16529                                              /*StrictlyPositive=*/true);
16530 
16531     // isNonNegativeIntegerValue returns true for non-integral types (but still
16532     // emits error diagnostic), so check for the expected type explicitly.
16533     QualType SizeTy = SizeExpr->getType();
16534     if (!SizeTy->isIntegerType())
16535       IsValid = false;
16536 
16537     // Handling in templates is tricky. There are four possibilities to
16538     // consider:
16539     //
16540     // 1a. The expression is valid and we are in a instantiated template or not
16541     //     in a template:
16542     //       Pass valid expression to be further analysed later in Sema.
16543     // 1b. The expression is valid and we are in a template (including partial
16544     //     instantiation):
16545     //       isNonNegativeIntegerValue skipped any checks so there is no
16546     //       guarantee it will be correct after instantiation.
16547     //       ActOnOpenMPSizesClause will be called again at instantiation when
16548     //       it is not in a dependent context anymore. This may cause warnings
16549     //       to be emitted multiple times.
16550     // 2a. The expression is invalid and we are in an instantiated template or
16551     //     not in a template:
16552     //       Invalidate the expression with a clearly wrong value (nullptr) so
16553     //       later in Sema we do not have to do the same validity analysis again
16554     //       or crash from unexpected data. Error diagnostics have already been
16555     //       emitted.
16556     // 2b. The expression is invalid and we are in a template (including partial
16557     //     instantiation):
16558     //       Pass the invalid expression as-is, template instantiation may
16559     //       replace unexpected types/values with valid ones. The directives
16560     //       with this clause must not try to use these expressions in dependent
16561     //       contexts, but delay analysis until full instantiation.
16562     if (!SizeExpr->isInstantiationDependent() && !IsValid)
16563       SizeExpr = nullptr;
16564   }
16565 
16566   return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
16567                                 SanitizedSizeExprs);
16568 }
16569 
ActOnOpenMPPermutationClause(ArrayRef<Expr * > PermExprs,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16570 OMPClause *SemaOpenMP::ActOnOpenMPPermutationClause(ArrayRef<Expr *> PermExprs,
16571                                                     SourceLocation StartLoc,
16572                                                     SourceLocation LParenLoc,
16573                                                     SourceLocation EndLoc) {
16574   size_t NumLoops = PermExprs.size();
16575   SmallVector<Expr *> SanitizedPermExprs;
16576   llvm::append_range(SanitizedPermExprs, PermExprs);
16577 
16578   for (Expr *&PermExpr : SanitizedPermExprs) {
16579     // Skip if template-dependent or already sanitized, e.g. during a partial
16580     // template instantiation.
16581     if (!PermExpr || PermExpr->isInstantiationDependent())
16582       continue;
16583 
16584     llvm::APSInt PermVal;
16585     ExprResult PermEvalExpr = SemaRef.VerifyIntegerConstantExpression(
16586         PermExpr, &PermVal, AllowFoldKind::Allow);
16587     bool IsValid = PermEvalExpr.isUsable();
16588     if (IsValid)
16589       PermExpr = PermEvalExpr.get();
16590 
16591     if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
16592       SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
16593                             PermEvalExpr.get()->getEndLoc());
16594       Diag(PermEvalExpr.get()->getExprLoc(),
16595            diag::err_omp_interchange_permutation_value_range)
16596           << NumLoops << ExprRange;
16597       IsValid = false;
16598     }
16599 
16600     if (!PermExpr->isInstantiationDependent() && !IsValid)
16601       PermExpr = nullptr;
16602   }
16603 
16604   return OMPPermutationClause::Create(getASTContext(), StartLoc, LParenLoc,
16605                                       EndLoc, SanitizedPermExprs);
16606 }
16607 
ActOnOpenMPFullClause(SourceLocation StartLoc,SourceLocation EndLoc)16608 OMPClause *SemaOpenMP::ActOnOpenMPFullClause(SourceLocation StartLoc,
16609                                              SourceLocation EndLoc) {
16610   return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc);
16611 }
16612 
ActOnOpenMPPartialClause(Expr * FactorExpr,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16613 OMPClause *SemaOpenMP::ActOnOpenMPPartialClause(Expr *FactorExpr,
16614                                                 SourceLocation StartLoc,
16615                                                 SourceLocation LParenLoc,
16616                                                 SourceLocation EndLoc) {
16617   if (FactorExpr) {
16618     // If an argument is specified, it must be a constant (or an unevaluated
16619     // template expression).
16620     ExprResult FactorResult = VerifyPositiveIntegerConstantInClause(
16621         FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
16622     if (FactorResult.isInvalid())
16623       return nullptr;
16624     FactorExpr = FactorResult.get();
16625   }
16626 
16627   return OMPPartialClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
16628                                   FactorExpr);
16629 }
16630 
ActOnOpenMPAlignClause(Expr * A,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16631 OMPClause *SemaOpenMP::ActOnOpenMPAlignClause(Expr *A, SourceLocation StartLoc,
16632                                               SourceLocation LParenLoc,
16633                                               SourceLocation EndLoc) {
16634   ExprResult AlignVal;
16635   AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
16636   if (AlignVal.isInvalid())
16637     return nullptr;
16638   return OMPAlignClause::Create(getASTContext(), AlignVal.get(), StartLoc,
16639                                 LParenLoc, EndLoc);
16640 }
16641 
ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,ArrayRef<unsigned> Argument,Expr * Expr,SourceLocation StartLoc,SourceLocation LParenLoc,ArrayRef<SourceLocation> ArgumentLoc,SourceLocation DelimLoc,SourceLocation EndLoc)16642 OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause(
16643     OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,
16644     SourceLocation StartLoc, SourceLocation LParenLoc,
16645     ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
16646     SourceLocation EndLoc) {
16647   OMPClause *Res = nullptr;
16648   switch (Kind) {
16649   case OMPC_schedule:
16650     enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
16651     assert(Argument.size() == NumberOfElements &&
16652            ArgumentLoc.size() == NumberOfElements);
16653     Res = ActOnOpenMPScheduleClause(
16654         static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
16655         static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
16656         static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
16657         StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
16658         ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
16659     break;
16660   case OMPC_if:
16661     assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16662     Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
16663                               Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
16664                               DelimLoc, EndLoc);
16665     break;
16666   case OMPC_dist_schedule:
16667     Res = ActOnOpenMPDistScheduleClause(
16668         static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
16669         StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
16670     break;
16671   case OMPC_defaultmap:
16672     enum { Modifier, DefaultmapKind };
16673     Res = ActOnOpenMPDefaultmapClause(
16674         static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
16675         static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
16676         StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
16677         EndLoc);
16678     break;
16679   case OMPC_order:
16680     enum { OrderModifier, OrderKind };
16681     Res = ActOnOpenMPOrderClause(
16682         static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
16683         static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
16684         LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
16685     break;
16686   case OMPC_device:
16687     assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16688     Res = ActOnOpenMPDeviceClause(
16689         static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
16690         StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16691     break;
16692   case OMPC_grainsize:
16693     assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16694            "Modifier for grainsize clause and its location are expected.");
16695     Res = ActOnOpenMPGrainsizeClause(
16696         static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
16697         StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16698     break;
16699   case OMPC_num_tasks:
16700     assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16701            "Modifier for num_tasks clause and its location are expected.");
16702     Res = ActOnOpenMPNumTasksClause(
16703         static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
16704         StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16705     break;
16706   case OMPC_num_threads:
16707     assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16708            "Modifier for num_threads clause and its location are expected.");
16709     Res = ActOnOpenMPNumThreadsClause(
16710         static_cast<OpenMPNumThreadsClauseModifier>(Argument.back()), Expr,
16711         StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16712     break;
16713   case OMPC_final:
16714   case OMPC_safelen:
16715   case OMPC_simdlen:
16716   case OMPC_sizes:
16717   case OMPC_allocator:
16718   case OMPC_collapse:
16719   case OMPC_default:
16720   case OMPC_proc_bind:
16721   case OMPC_private:
16722   case OMPC_firstprivate:
16723   case OMPC_lastprivate:
16724   case OMPC_shared:
16725   case OMPC_reduction:
16726   case OMPC_task_reduction:
16727   case OMPC_in_reduction:
16728   case OMPC_linear:
16729   case OMPC_aligned:
16730   case OMPC_copyin:
16731   case OMPC_copyprivate:
16732   case OMPC_ordered:
16733   case OMPC_nowait:
16734   case OMPC_untied:
16735   case OMPC_mergeable:
16736   case OMPC_threadprivate:
16737   case OMPC_allocate:
16738   case OMPC_flush:
16739   case OMPC_depobj:
16740   case OMPC_read:
16741   case OMPC_write:
16742   case OMPC_update:
16743   case OMPC_capture:
16744   case OMPC_compare:
16745   case OMPC_seq_cst:
16746   case OMPC_acq_rel:
16747   case OMPC_acquire:
16748   case OMPC_release:
16749   case OMPC_relaxed:
16750   case OMPC_depend:
16751   case OMPC_threads:
16752   case OMPC_simd:
16753   case OMPC_map:
16754   case OMPC_num_teams:
16755   case OMPC_thread_limit:
16756   case OMPC_priority:
16757   case OMPC_nogroup:
16758   case OMPC_hint:
16759   case OMPC_unknown:
16760   case OMPC_uniform:
16761   case OMPC_to:
16762   case OMPC_from:
16763   case OMPC_use_device_ptr:
16764   case OMPC_use_device_addr:
16765   case OMPC_is_device_ptr:
16766   case OMPC_has_device_addr:
16767   case OMPC_unified_address:
16768   case OMPC_unified_shared_memory:
16769   case OMPC_reverse_offload:
16770   case OMPC_dynamic_allocators:
16771   case OMPC_atomic_default_mem_order:
16772   case OMPC_self_maps:
16773   case OMPC_device_type:
16774   case OMPC_match:
16775   case OMPC_nontemporal:
16776   case OMPC_at:
16777   case OMPC_severity:
16778   case OMPC_message:
16779   case OMPC_destroy:
16780   case OMPC_novariants:
16781   case OMPC_nocontext:
16782   case OMPC_detach:
16783   case OMPC_inclusive:
16784   case OMPC_exclusive:
16785   case OMPC_uses_allocators:
16786   case OMPC_affinity:
16787   case OMPC_when:
16788   case OMPC_bind:
16789   default:
16790     llvm_unreachable("Clause is not allowed.");
16791   }
16792   return Res;
16793 }
16794 
checkScheduleModifiers(Sema & S,OpenMPScheduleClauseModifier M1,OpenMPScheduleClauseModifier M2,SourceLocation M1Loc,SourceLocation M2Loc)16795 static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1,
16796                                    OpenMPScheduleClauseModifier M2,
16797                                    SourceLocation M1Loc, SourceLocation M2Loc) {
16798   if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
16799     SmallVector<unsigned, 2> Excluded;
16800     if (M2 != OMPC_SCHEDULE_MODIFIER_unknown)
16801       Excluded.push_back(M2);
16802     if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
16803       Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
16804     if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
16805       Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
16806     S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
16807         << getListOfPossibleValues(OMPC_schedule,
16808                                    /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
16809                                    /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
16810                                    Excluded)
16811         << getOpenMPClauseNameForDiag(OMPC_schedule);
16812     return true;
16813   }
16814   return false;
16815 }
16816 
ActOnOpenMPScheduleClause(OpenMPScheduleClauseModifier M1,OpenMPScheduleClauseModifier M2,OpenMPScheduleClauseKind Kind,Expr * ChunkSize,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation M1Loc,SourceLocation M2Loc,SourceLocation KindLoc,SourceLocation CommaLoc,SourceLocation EndLoc)16817 OMPClause *SemaOpenMP::ActOnOpenMPScheduleClause(
16818     OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
16819     OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
16820     SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
16821     SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
16822   if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) ||
16823       checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc))
16824     return nullptr;
16825   // OpenMP, 2.7.1, Loop Construct, Restrictions
16826   // Either the monotonic modifier or the nonmonotonic modifier can be specified
16827   // but not both.
16828   if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
16829       (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
16830        M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
16831       (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
16832        M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
16833     Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
16834         << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
16835         << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
16836     return nullptr;
16837   }
16838   if (Kind == OMPC_SCHEDULE_unknown) {
16839     std::string Values;
16840     if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
16841       unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
16842       Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16843                                        /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
16844                                        Exclude);
16845     } else {
16846       Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16847                                        /*Last=*/OMPC_SCHEDULE_unknown);
16848     }
16849     Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16850         << Values << getOpenMPClauseNameForDiag(OMPC_schedule);
16851     return nullptr;
16852   }
16853   // OpenMP, 2.7.1, Loop Construct, Restrictions
16854   // The nonmonotonic modifier can only be specified with schedule(dynamic) or
16855   // schedule(guided).
16856   // OpenMP 5.0 does not have this restriction.
16857   if (getLangOpts().OpenMP < 50 &&
16858       (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
16859        M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
16860       Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
16861     Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
16862          diag::err_omp_schedule_nonmonotonic_static);
16863     return nullptr;
16864   }
16865   Expr *ValExpr = ChunkSize;
16866   Stmt *HelperValStmt = nullptr;
16867   if (ChunkSize) {
16868     if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
16869         !ChunkSize->isInstantiationDependent() &&
16870         !ChunkSize->containsUnexpandedParameterPack()) {
16871       SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
16872       ExprResult Val =
16873           PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
16874       if (Val.isInvalid())
16875         return nullptr;
16876 
16877       ValExpr = Val.get();
16878 
16879       // OpenMP [2.7.1, Restrictions]
16880       //  chunk_size must be a loop invariant integer expression with a positive
16881       //  value.
16882       if (std::optional<llvm::APSInt> Result =
16883               ValExpr->getIntegerConstantExpr(getASTContext())) {
16884         if (Result->isSigned() && !Result->isStrictlyPositive()) {
16885           Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
16886               << "schedule" << 1 << ChunkSize->getSourceRange();
16887           return nullptr;
16888         }
16889       } else if (getOpenMPCaptureRegionForClause(
16890                      DSAStack->getCurrentDirective(), OMPC_schedule,
16891                      getLangOpts().OpenMP) != OMPD_unknown &&
16892                  !SemaRef.CurContext->isDependentContext()) {
16893         ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16894         llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16895         ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16896         HelperValStmt = buildPreInits(getASTContext(), Captures);
16897       }
16898     }
16899   }
16900 
16901   return new (getASTContext())
16902       OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
16903                         ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
16904 }
16905 
ActOnOpenMPClause(OpenMPClauseKind Kind,SourceLocation StartLoc,SourceLocation EndLoc)16906 OMPClause *SemaOpenMP::ActOnOpenMPClause(OpenMPClauseKind Kind,
16907                                          SourceLocation StartLoc,
16908                                          SourceLocation EndLoc) {
16909   OMPClause *Res = nullptr;
16910   switch (Kind) {
16911   case OMPC_ordered:
16912     Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
16913     break;
16914   case OMPC_nowait:
16915     Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
16916     break;
16917   case OMPC_untied:
16918     Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
16919     break;
16920   case OMPC_mergeable:
16921     Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
16922     break;
16923   case OMPC_read:
16924     Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
16925     break;
16926   case OMPC_write:
16927     Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
16928     break;
16929   case OMPC_update:
16930     Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
16931     break;
16932   case OMPC_capture:
16933     Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
16934     break;
16935   case OMPC_compare:
16936     Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
16937     break;
16938   case OMPC_fail:
16939     Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
16940     break;
16941   case OMPC_seq_cst:
16942     Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
16943     break;
16944   case OMPC_acq_rel:
16945     Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
16946     break;
16947   case OMPC_acquire:
16948     Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
16949     break;
16950   case OMPC_release:
16951     Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
16952     break;
16953   case OMPC_relaxed:
16954     Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
16955     break;
16956   case OMPC_weak:
16957     Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
16958     break;
16959   case OMPC_threads:
16960     Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
16961     break;
16962   case OMPC_simd:
16963     Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
16964     break;
16965   case OMPC_nogroup:
16966     Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
16967     break;
16968   case OMPC_unified_address:
16969     Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
16970     break;
16971   case OMPC_unified_shared_memory:
16972     Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
16973     break;
16974   case OMPC_reverse_offload:
16975     Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
16976     break;
16977   case OMPC_dynamic_allocators:
16978     Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
16979     break;
16980   case OMPC_self_maps:
16981     Res = ActOnOpenMPSelfMapsClause(StartLoc, EndLoc);
16982     break;
16983   case OMPC_destroy:
16984     Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
16985                                    /*LParenLoc=*/SourceLocation(),
16986                                    /*VarLoc=*/SourceLocation(), EndLoc);
16987     break;
16988   case OMPC_full:
16989     Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
16990     break;
16991   case OMPC_partial:
16992     Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
16993     break;
16994   case OMPC_ompx_bare:
16995     Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
16996     break;
16997   case OMPC_if:
16998   case OMPC_final:
16999   case OMPC_num_threads:
17000   case OMPC_safelen:
17001   case OMPC_simdlen:
17002   case OMPC_sizes:
17003   case OMPC_allocator:
17004   case OMPC_collapse:
17005   case OMPC_schedule:
17006   case OMPC_private:
17007   case OMPC_firstprivate:
17008   case OMPC_lastprivate:
17009   case OMPC_shared:
17010   case OMPC_reduction:
17011   case OMPC_task_reduction:
17012   case OMPC_in_reduction:
17013   case OMPC_linear:
17014   case OMPC_aligned:
17015   case OMPC_copyin:
17016   case OMPC_copyprivate:
17017   case OMPC_default:
17018   case OMPC_proc_bind:
17019   case OMPC_threadprivate:
17020   case OMPC_allocate:
17021   case OMPC_flush:
17022   case OMPC_depobj:
17023   case OMPC_depend:
17024   case OMPC_device:
17025   case OMPC_map:
17026   case OMPC_num_teams:
17027   case OMPC_thread_limit:
17028   case OMPC_priority:
17029   case OMPC_grainsize:
17030   case OMPC_num_tasks:
17031   case OMPC_hint:
17032   case OMPC_dist_schedule:
17033   case OMPC_defaultmap:
17034   case OMPC_unknown:
17035   case OMPC_uniform:
17036   case OMPC_to:
17037   case OMPC_from:
17038   case OMPC_use_device_ptr:
17039   case OMPC_use_device_addr:
17040   case OMPC_is_device_ptr:
17041   case OMPC_has_device_addr:
17042   case OMPC_atomic_default_mem_order:
17043   case OMPC_device_type:
17044   case OMPC_match:
17045   case OMPC_nontemporal:
17046   case OMPC_order:
17047   case OMPC_at:
17048   case OMPC_severity:
17049   case OMPC_message:
17050   case OMPC_novariants:
17051   case OMPC_nocontext:
17052   case OMPC_detach:
17053   case OMPC_inclusive:
17054   case OMPC_exclusive:
17055   case OMPC_uses_allocators:
17056   case OMPC_affinity:
17057   case OMPC_when:
17058   case OMPC_ompx_dyn_cgroup_mem:
17059   default:
17060     llvm_unreachable("Clause is not allowed.");
17061   }
17062   return Res;
17063 }
17064 
ActOnOpenMPNowaitClause(SourceLocation StartLoc,SourceLocation EndLoc)17065 OMPClause *SemaOpenMP::ActOnOpenMPNowaitClause(SourceLocation StartLoc,
17066                                                SourceLocation EndLoc) {
17067   DSAStack->setNowaitRegion();
17068   return new (getASTContext()) OMPNowaitClause(StartLoc, EndLoc);
17069 }
17070 
ActOnOpenMPUntiedClause(SourceLocation StartLoc,SourceLocation EndLoc)17071 OMPClause *SemaOpenMP::ActOnOpenMPUntiedClause(SourceLocation StartLoc,
17072                                                SourceLocation EndLoc) {
17073   DSAStack->setUntiedRegion();
17074   return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
17075 }
17076 
ActOnOpenMPMergeableClause(SourceLocation StartLoc,SourceLocation EndLoc)17077 OMPClause *SemaOpenMP::ActOnOpenMPMergeableClause(SourceLocation StartLoc,
17078                                                   SourceLocation EndLoc) {
17079   return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
17080 }
17081 
ActOnOpenMPReadClause(SourceLocation StartLoc,SourceLocation EndLoc)17082 OMPClause *SemaOpenMP::ActOnOpenMPReadClause(SourceLocation StartLoc,
17083                                              SourceLocation EndLoc) {
17084   return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
17085 }
17086 
ActOnOpenMPWriteClause(SourceLocation StartLoc,SourceLocation EndLoc)17087 OMPClause *SemaOpenMP::ActOnOpenMPWriteClause(SourceLocation StartLoc,
17088                                               SourceLocation EndLoc) {
17089   return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
17090 }
17091 
ActOnOpenMPUpdateClause(SourceLocation StartLoc,SourceLocation EndLoc)17092 OMPClause *SemaOpenMP::ActOnOpenMPUpdateClause(SourceLocation StartLoc,
17093                                                SourceLocation EndLoc) {
17094   return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc);
17095 }
17096 
ActOnOpenMPCaptureClause(SourceLocation StartLoc,SourceLocation EndLoc)17097 OMPClause *SemaOpenMP::ActOnOpenMPCaptureClause(SourceLocation StartLoc,
17098                                                 SourceLocation EndLoc) {
17099   return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
17100 }
17101 
ActOnOpenMPCompareClause(SourceLocation StartLoc,SourceLocation EndLoc)17102 OMPClause *SemaOpenMP::ActOnOpenMPCompareClause(SourceLocation StartLoc,
17103                                                 SourceLocation EndLoc) {
17104   return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
17105 }
17106 
ActOnOpenMPFailClause(SourceLocation StartLoc,SourceLocation EndLoc)17107 OMPClause *SemaOpenMP::ActOnOpenMPFailClause(SourceLocation StartLoc,
17108                                              SourceLocation EndLoc) {
17109   return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
17110 }
17111 
ActOnOpenMPFailClause(OpenMPClauseKind Parameter,SourceLocation KindLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)17112 OMPClause *SemaOpenMP::ActOnOpenMPFailClause(OpenMPClauseKind Parameter,
17113                                              SourceLocation KindLoc,
17114                                              SourceLocation StartLoc,
17115                                              SourceLocation LParenLoc,
17116                                              SourceLocation EndLoc) {
17117 
17118   if (!checkFailClauseParameter(Parameter)) {
17119     Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
17120     return nullptr;
17121   }
17122   return new (getASTContext())
17123       OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
17124 }
17125 
ActOnOpenMPSeqCstClause(SourceLocation StartLoc,SourceLocation EndLoc)17126 OMPClause *SemaOpenMP::ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
17127                                                SourceLocation EndLoc) {
17128   return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
17129 }
17130 
ActOnOpenMPAcqRelClause(SourceLocation StartLoc,SourceLocation EndLoc)17131 OMPClause *SemaOpenMP::ActOnOpenMPAcqRelClause(SourceLocation StartLoc,
17132                                                SourceLocation EndLoc) {
17133   return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
17134 }
17135 
ActOnOpenMPAcquireClause(SourceLocation StartLoc,SourceLocation EndLoc)17136 OMPClause *SemaOpenMP::ActOnOpenMPAcquireClause(SourceLocation StartLoc,
17137                                                 SourceLocation EndLoc) {
17138   return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
17139 }
17140 
ActOnOpenMPReleaseClause(SourceLocation StartLoc,SourceLocation EndLoc)17141 OMPClause *SemaOpenMP::ActOnOpenMPReleaseClause(SourceLocation StartLoc,
17142                                                 SourceLocation EndLoc) {
17143   return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
17144 }
17145 
ActOnOpenMPRelaxedClause(SourceLocation StartLoc,SourceLocation EndLoc)17146 OMPClause *SemaOpenMP::ActOnOpenMPRelaxedClause(SourceLocation StartLoc,
17147                                                 SourceLocation EndLoc) {
17148   return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
17149 }
17150 
ActOnOpenMPWeakClause(SourceLocation StartLoc,SourceLocation EndLoc)17151 OMPClause *SemaOpenMP::ActOnOpenMPWeakClause(SourceLocation StartLoc,
17152                                              SourceLocation EndLoc) {
17153   return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
17154 }
17155 
ActOnOpenMPThreadsClause(SourceLocation StartLoc,SourceLocation EndLoc)17156 OMPClause *SemaOpenMP::ActOnOpenMPThreadsClause(SourceLocation StartLoc,
17157                                                 SourceLocation EndLoc) {
17158   return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
17159 }
17160 
ActOnOpenMPSIMDClause(SourceLocation StartLoc,SourceLocation EndLoc)17161 OMPClause *SemaOpenMP::ActOnOpenMPSIMDClause(SourceLocation StartLoc,
17162                                              SourceLocation EndLoc) {
17163   return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
17164 }
17165 
ActOnOpenMPNogroupClause(SourceLocation StartLoc,SourceLocation EndLoc)17166 OMPClause *SemaOpenMP::ActOnOpenMPNogroupClause(SourceLocation StartLoc,
17167                                                 SourceLocation EndLoc) {
17168   return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
17169 }
17170 
ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,SourceLocation EndLoc)17171 OMPClause *SemaOpenMP::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,
17172                                                        SourceLocation EndLoc) {
17173   return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
17174 }
17175 
17176 OMPClause *
ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,SourceLocation EndLoc)17177 SemaOpenMP::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
17178                                                  SourceLocation EndLoc) {
17179   return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17180 }
17181 
ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,SourceLocation EndLoc)17182 OMPClause *SemaOpenMP::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
17183                                                        SourceLocation EndLoc) {
17184   return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
17185 }
17186 
17187 OMPClause *
ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,SourceLocation EndLoc)17188 SemaOpenMP::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,
17189                                                SourceLocation EndLoc) {
17190   return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
17191 }
17192 
ActOnOpenMPSelfMapsClause(SourceLocation StartLoc,SourceLocation EndLoc)17193 OMPClause *SemaOpenMP::ActOnOpenMPSelfMapsClause(SourceLocation StartLoc,
17194                                                  SourceLocation EndLoc) {
17195   return new (getASTContext()) OMPSelfMapsClause(StartLoc, EndLoc);
17196 }
17197 
17198 StmtResult
ActOnOpenMPInteropDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc)17199 SemaOpenMP::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
17200                                         SourceLocation StartLoc,
17201                                         SourceLocation EndLoc) {
17202 
17203   // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17204   // At least one action-clause must appear on a directive.
17205   if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
17206     unsigned OMPVersion = getLangOpts().OpenMP;
17207     StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
17208     Diag(StartLoc, diag::err_omp_no_clause_for_directive)
17209         << Expected << getOpenMPDirectiveName(OMPD_interop, OMPVersion);
17210     return StmtError();
17211   }
17212 
17213   // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17214   // A depend clause can only appear on the directive if a targetsync
17215   // interop-type is present or the interop-var was initialized with
17216   // the targetsync interop-type.
17217 
17218   // If there is any 'init' clause diagnose if there is no 'init' clause with
17219   // interop-type of 'targetsync'. Cases involving other directives cannot be
17220   // diagnosed.
17221   const OMPDependClause *DependClause = nullptr;
17222   bool HasInitClause = false;
17223   bool IsTargetSync = false;
17224   for (const OMPClause *C : Clauses) {
17225     if (IsTargetSync)
17226       break;
17227     if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
17228       HasInitClause = true;
17229       if (InitClause->getIsTargetSync())
17230         IsTargetSync = true;
17231     } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
17232       DependClause = DC;
17233     }
17234   }
17235   if (DependClause && HasInitClause && !IsTargetSync) {
17236     Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
17237     return StmtError();
17238   }
17239 
17240   // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17241   // Each interop-var may be specified for at most one action-clause of each
17242   // interop construct.
17243   llvm::SmallPtrSet<const ValueDecl *, 4> InteropVars;
17244   for (OMPClause *C : Clauses) {
17245     OpenMPClauseKind ClauseKind = C->getClauseKind();
17246     std::pair<ValueDecl *, bool> DeclResult;
17247     SourceLocation ELoc;
17248     SourceRange ERange;
17249 
17250     if (ClauseKind == OMPC_init) {
17251       auto *E = cast<OMPInitClause>(C)->getInteropVar();
17252       DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
17253     } else if (ClauseKind == OMPC_use) {
17254       auto *E = cast<OMPUseClause>(C)->getInteropVar();
17255       DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
17256     } else if (ClauseKind == OMPC_destroy) {
17257       auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
17258       DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
17259     }
17260 
17261     if (DeclResult.first) {
17262       if (!InteropVars.insert(DeclResult.first).second) {
17263         Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
17264             << DeclResult.first;
17265         return StmtError();
17266       }
17267     }
17268   }
17269 
17270   return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc,
17271                                      Clauses);
17272 }
17273 
isValidInteropVariable(Sema & SemaRef,Expr * InteropVarExpr,SourceLocation VarLoc,OpenMPClauseKind Kind)17274 static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
17275                                    SourceLocation VarLoc,
17276                                    OpenMPClauseKind Kind) {
17277   SourceLocation ELoc;
17278   SourceRange ERange;
17279   Expr *RefExpr = InteropVarExpr;
17280   auto Res =
17281       getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
17282                      /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
17283 
17284   if (Res.second) {
17285     // It will be analyzed later.
17286     return true;
17287   }
17288 
17289   if (!Res.first)
17290     return false;
17291 
17292   // Interop variable should be of type omp_interop_t.
17293   bool HasError = false;
17294   QualType InteropType;
17295   LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
17296                       VarLoc, Sema::LookupOrdinaryName);
17297   if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
17298     NamedDecl *ND = Result.getFoundDecl();
17299     if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
17300       InteropType = QualType(TD->getTypeForDecl(), 0);
17301     } else {
17302       HasError = true;
17303     }
17304   } else {
17305     HasError = true;
17306   }
17307 
17308   if (HasError) {
17309     SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
17310         << "omp_interop_t";
17311     return false;
17312   }
17313 
17314   QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
17315   if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
17316     SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
17317     return false;
17318   }
17319 
17320   // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17321   // The interop-var passed to init or destroy must be non-const.
17322   if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
17323       isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
17324     SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
17325         << /*non-const*/ 1;
17326     return false;
17327   }
17328   return true;
17329 }
17330 
ActOnOpenMPInitClause(Expr * InteropVar,OMPInteropInfo & InteropInfo,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation VarLoc,SourceLocation EndLoc)17331 OMPClause *SemaOpenMP::ActOnOpenMPInitClause(
17332     Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
17333     SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
17334 
17335   if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init))
17336     return nullptr;
17337 
17338   // Check prefer_type values.  These foreign-runtime-id values are either
17339   // string literals or constant integral expressions.
17340   for (const Expr *E : InteropInfo.PreferTypes) {
17341     if (E->isValueDependent() || E->isTypeDependent() ||
17342         E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
17343       continue;
17344     if (E->isIntegerConstantExpr(getASTContext()))
17345       continue;
17346     if (isa<StringLiteral>(E))
17347       continue;
17348     Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
17349     return nullptr;
17350   }
17351 
17352   return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo,
17353                                StartLoc, LParenLoc, VarLoc, EndLoc);
17354 }
17355 
ActOnOpenMPUseClause(Expr * InteropVar,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation VarLoc,SourceLocation EndLoc)17356 OMPClause *SemaOpenMP::ActOnOpenMPUseClause(Expr *InteropVar,
17357                                             SourceLocation StartLoc,
17358                                             SourceLocation LParenLoc,
17359                                             SourceLocation VarLoc,
17360                                             SourceLocation EndLoc) {
17361 
17362   if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use))
17363     return nullptr;
17364 
17365   return new (getASTContext())
17366       OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17367 }
17368 
ActOnOpenMPDestroyClause(Expr * InteropVar,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation VarLoc,SourceLocation EndLoc)17369 OMPClause *SemaOpenMP::ActOnOpenMPDestroyClause(Expr *InteropVar,
17370                                                 SourceLocation StartLoc,
17371                                                 SourceLocation LParenLoc,
17372                                                 SourceLocation VarLoc,
17373                                                 SourceLocation EndLoc) {
17374   if (!InteropVar && getLangOpts().OpenMP >= 52 &&
17375       DSAStack->getCurrentDirective() == OMPD_depobj) {
17376     unsigned OMPVersion = getLangOpts().OpenMP;
17377     Diag(StartLoc, diag::err_omp_expected_clause_argument)
17378         << getOpenMPClauseNameForDiag(OMPC_destroy)
17379         << getOpenMPDirectiveName(OMPD_depobj, OMPVersion);
17380     return nullptr;
17381   }
17382   if (InteropVar &&
17383       !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy))
17384     return nullptr;
17385 
17386   return new (getASTContext())
17387       OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17388 }
17389 
ActOnOpenMPNovariantsClause(Expr * Condition,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)17390 OMPClause *SemaOpenMP::ActOnOpenMPNovariantsClause(Expr *Condition,
17391                                                    SourceLocation StartLoc,
17392                                                    SourceLocation LParenLoc,
17393                                                    SourceLocation EndLoc) {
17394   Expr *ValExpr = Condition;
17395   Stmt *HelperValStmt = nullptr;
17396   OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17397   if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17398       !Condition->isInstantiationDependent() &&
17399       !Condition->containsUnexpandedParameterPack()) {
17400     ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
17401     if (Val.isInvalid())
17402       return nullptr;
17403 
17404     ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
17405 
17406     OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17407     CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
17408                                                     getLangOpts().OpenMP);
17409     if (CaptureRegion != OMPD_unknown &&
17410         !SemaRef.CurContext->isDependentContext()) {
17411       ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17412       llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17413       ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17414       HelperValStmt = buildPreInits(getASTContext(), Captures);
17415     }
17416   }
17417 
17418   return new (getASTContext()) OMPNovariantsClause(
17419       ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17420 }
17421 
ActOnOpenMPNocontextClause(Expr * Condition,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)17422 OMPClause *SemaOpenMP::ActOnOpenMPNocontextClause(Expr *Condition,
17423                                                   SourceLocation StartLoc,
17424                                                   SourceLocation LParenLoc,
17425                                                   SourceLocation EndLoc) {
17426   Expr *ValExpr = Condition;
17427   Stmt *HelperValStmt = nullptr;
17428   OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17429   if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17430       !Condition->isInstantiationDependent() &&
17431       !Condition->containsUnexpandedParameterPack()) {
17432     ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
17433     if (Val.isInvalid())
17434       return nullptr;
17435 
17436     ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
17437 
17438     OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17439     CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext,
17440                                                     getLangOpts().OpenMP);
17441     if (CaptureRegion != OMPD_unknown &&
17442         !SemaRef.CurContext->isDependentContext()) {
17443       ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17444       llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17445       ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17446       HelperValStmt = buildPreInits(getASTContext(), Captures);
17447     }
17448   }
17449 
17450   return new (getASTContext()) OMPNocontextClause(
17451       ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17452 }
17453 
ActOnOpenMPFilterClause(Expr * ThreadID,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)17454 OMPClause *SemaOpenMP::ActOnOpenMPFilterClause(Expr *ThreadID,
17455                                                SourceLocation StartLoc,
17456                                                SourceLocation LParenLoc,
17457                                                SourceLocation EndLoc) {
17458   Expr *ValExpr = ThreadID;
17459   Stmt *HelperValStmt = nullptr;
17460 
17461   OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17462   OpenMPDirectiveKind CaptureRegion =
17463       getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP);
17464   if (CaptureRegion != OMPD_unknown &&
17465       !SemaRef.CurContext->isDependentContext()) {
17466     ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17467     llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17468     ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17469     HelperValStmt = buildPreInits(getASTContext(), Captures);
17470   }
17471 
17472   return new (getASTContext()) OMPFilterClause(
17473       ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17474 }
17475 
ActOnOpenMPVarListClause(OpenMPClauseKind Kind,ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs,OpenMPVarListDataTy & Data)17476 OMPClause *SemaOpenMP::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
17477                                                 ArrayRef<Expr *> VarList,
17478                                                 const OMPVarListLocTy &Locs,
17479                                                 OpenMPVarListDataTy &Data) {
17480   SourceLocation StartLoc = Locs.StartLoc;
17481   SourceLocation LParenLoc = Locs.LParenLoc;
17482   SourceLocation EndLoc = Locs.EndLoc;
17483   OMPClause *Res = nullptr;
17484   int ExtraModifier = Data.ExtraModifier;
17485   int OriginalSharingModifier = Data.OriginalSharingModifier;
17486   SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
17487   SourceLocation ColonLoc = Data.ColonLoc;
17488   switch (Kind) {
17489   case OMPC_private:
17490     Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17491     break;
17492   case OMPC_firstprivate:
17493     Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17494     break;
17495   case OMPC_lastprivate:
17496     assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
17497            "Unexpected lastprivate modifier.");
17498     Res = ActOnOpenMPLastprivateClause(
17499         VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
17500         ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
17501     break;
17502   case OMPC_shared:
17503     Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
17504     break;
17505   case OMPC_reduction:
17506     assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
17507            "Unexpected lastprivate modifier.");
17508     Res = ActOnOpenMPReductionClause(
17509         VarList,
17510         OpenMPVarListDataTy::OpenMPReductionClauseModifiers(
17511             ExtraModifier, OriginalSharingModifier),
17512         StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
17513         Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17514     break;
17515   case OMPC_task_reduction:
17516     Res = ActOnOpenMPTaskReductionClause(
17517         VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17518         Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17519     break;
17520   case OMPC_in_reduction:
17521     Res = ActOnOpenMPInReductionClause(
17522         VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17523         Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17524     break;
17525   case OMPC_linear:
17526     assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
17527            "Unexpected linear modifier.");
17528     Res = ActOnOpenMPLinearClause(
17529         VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
17530         static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
17531         ColonLoc, Data.StepModifierLoc, EndLoc);
17532     break;
17533   case OMPC_aligned:
17534     Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
17535                                    LParenLoc, ColonLoc, EndLoc);
17536     break;
17537   case OMPC_copyin:
17538     Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
17539     break;
17540   case OMPC_copyprivate:
17541     Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17542     break;
17543   case OMPC_flush:
17544     Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
17545     break;
17546   case OMPC_depend:
17547     assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
17548            "Unexpected depend modifier.");
17549     Res = ActOnOpenMPDependClause(
17550         {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
17551          ColonLoc, Data.OmpAllMemoryLoc},
17552         Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
17553     break;
17554   case OMPC_map:
17555     assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
17556            "Unexpected map modifier.");
17557     Res = ActOnOpenMPMapClause(
17558         Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
17559         Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
17560         static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
17561         ExtraModifierLoc, ColonLoc, VarList, Locs);
17562     break;
17563   case OMPC_to:
17564     Res =
17565         ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc,
17566                             Data.ReductionOrMapperIdScopeSpec,
17567                             Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
17568     break;
17569   case OMPC_from:
17570     Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc,
17571                                 Data.ReductionOrMapperIdScopeSpec,
17572                                 Data.ReductionOrMapperId, ColonLoc, VarList,
17573                                 Locs);
17574     break;
17575   case OMPC_use_device_ptr:
17576     Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
17577     break;
17578   case OMPC_use_device_addr:
17579     Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
17580     break;
17581   case OMPC_is_device_ptr:
17582     Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
17583     break;
17584   case OMPC_has_device_addr:
17585     Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
17586     break;
17587   case OMPC_allocate: {
17588     OpenMPAllocateClauseModifier Modifier1 = OMPC_ALLOCATE_unknown;
17589     OpenMPAllocateClauseModifier Modifier2 = OMPC_ALLOCATE_unknown;
17590     SourceLocation Modifier1Loc, Modifier2Loc;
17591     if (!Data.AllocClauseModifiers.empty()) {
17592       assert(Data.AllocClauseModifiers.size() <= 2 &&
17593              "More allocate modifiers than expected");
17594       Modifier1 = Data.AllocClauseModifiers[0];
17595       Modifier1Loc = Data.AllocClauseModifiersLoc[0];
17596       if (Data.AllocClauseModifiers.size() == 2) {
17597         Modifier2 = Data.AllocClauseModifiers[1];
17598         Modifier2Loc = Data.AllocClauseModifiersLoc[1];
17599       }
17600     }
17601     Res = ActOnOpenMPAllocateClause(
17602         Data.DepModOrTailExpr, Data.AllocateAlignment, Modifier1, Modifier1Loc,
17603         Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
17604         EndLoc);
17605     break;
17606   }
17607   case OMPC_nontemporal:
17608     Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
17609     break;
17610   case OMPC_inclusive:
17611     Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17612     break;
17613   case OMPC_exclusive:
17614     Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17615     break;
17616   case OMPC_affinity:
17617     Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
17618                                     Data.DepModOrTailExpr, VarList);
17619     break;
17620   case OMPC_doacross:
17621     Res = ActOnOpenMPDoacrossClause(
17622         static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
17623         ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
17624     break;
17625   case OMPC_num_teams:
17626     Res = ActOnOpenMPNumTeamsClause(VarList, StartLoc, LParenLoc, EndLoc);
17627     break;
17628   case OMPC_thread_limit:
17629     Res = ActOnOpenMPThreadLimitClause(VarList, StartLoc, LParenLoc, EndLoc);
17630     break;
17631   case OMPC_if:
17632   case OMPC_depobj:
17633   case OMPC_final:
17634   case OMPC_num_threads:
17635   case OMPC_safelen:
17636   case OMPC_simdlen:
17637   case OMPC_sizes:
17638   case OMPC_allocator:
17639   case OMPC_collapse:
17640   case OMPC_default:
17641   case OMPC_proc_bind:
17642   case OMPC_schedule:
17643   case OMPC_ordered:
17644   case OMPC_nowait:
17645   case OMPC_untied:
17646   case OMPC_mergeable:
17647   case OMPC_threadprivate:
17648   case OMPC_read:
17649   case OMPC_write:
17650   case OMPC_update:
17651   case OMPC_capture:
17652   case OMPC_compare:
17653   case OMPC_seq_cst:
17654   case OMPC_acq_rel:
17655   case OMPC_acquire:
17656   case OMPC_release:
17657   case OMPC_relaxed:
17658   case OMPC_device:
17659   case OMPC_threads:
17660   case OMPC_simd:
17661   case OMPC_priority:
17662   case OMPC_grainsize:
17663   case OMPC_nogroup:
17664   case OMPC_num_tasks:
17665   case OMPC_hint:
17666   case OMPC_dist_schedule:
17667   case OMPC_defaultmap:
17668   case OMPC_unknown:
17669   case OMPC_uniform:
17670   case OMPC_unified_address:
17671   case OMPC_unified_shared_memory:
17672   case OMPC_reverse_offload:
17673   case OMPC_dynamic_allocators:
17674   case OMPC_atomic_default_mem_order:
17675   case OMPC_self_maps:
17676   case OMPC_device_type:
17677   case OMPC_match:
17678   case OMPC_order:
17679   case OMPC_at:
17680   case OMPC_severity:
17681   case OMPC_message:
17682   case OMPC_destroy:
17683   case OMPC_novariants:
17684   case OMPC_nocontext:
17685   case OMPC_detach:
17686   case OMPC_uses_allocators:
17687   case OMPC_when:
17688   case OMPC_bind:
17689   default:
17690     llvm_unreachable("Clause is not allowed.");
17691   }
17692   return Res;
17693 }
17694 
getOpenMPCapturedExpr(VarDecl * Capture,ExprValueKind VK,ExprObjectKind OK,SourceLocation Loc)17695 ExprResult SemaOpenMP::getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
17696                                              ExprObjectKind OK,
17697                                              SourceLocation Loc) {
17698   ExprResult Res = SemaRef.BuildDeclRefExpr(
17699       Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
17700   if (!Res.isUsable())
17701     return ExprError();
17702   if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
17703     Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
17704     if (!Res.isUsable())
17705       return ExprError();
17706   }
17707   if (VK != VK_LValue && Res.get()->isGLValue()) {
17708     Res = SemaRef.DefaultLvalueConversion(Res.get());
17709     if (!Res.isUsable())
17710       return ExprError();
17711   }
17712   return Res;
17713 }
17714 
ActOnOpenMPPrivateClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)17715 OMPClause *SemaOpenMP::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
17716                                                 SourceLocation StartLoc,
17717                                                 SourceLocation LParenLoc,
17718                                                 SourceLocation EndLoc) {
17719   SmallVector<Expr *, 8> Vars;
17720   SmallVector<Expr *, 8> PrivateCopies;
17721   unsigned OMPVersion = getLangOpts().OpenMP;
17722   bool IsImplicitClause =
17723       StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17724   for (Expr *RefExpr : VarList) {
17725     assert(RefExpr && "NULL expr in OpenMP private clause.");
17726     SourceLocation ELoc;
17727     SourceRange ERange;
17728     Expr *SimpleRefExpr = RefExpr;
17729     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17730     if (Res.second) {
17731       // It will be analyzed later.
17732       Vars.push_back(RefExpr);
17733       PrivateCopies.push_back(nullptr);
17734     }
17735     ValueDecl *D = Res.first;
17736     if (!D)
17737       continue;
17738 
17739     QualType Type = D->getType();
17740     auto *VD = dyn_cast<VarDecl>(D);
17741 
17742     // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17743     //  A variable that appears in a private clause must not have an incomplete
17744     //  type or a reference type.
17745     if (SemaRef.RequireCompleteType(ELoc, Type,
17746                                     diag::err_omp_private_incomplete_type))
17747       continue;
17748     Type = Type.getNonReferenceType();
17749 
17750     // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
17751     // A variable that is privatized must not have a const-qualified type
17752     // unless it is of class type with a mutable member. This restriction does
17753     // not apply to the firstprivate clause.
17754     //
17755     // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
17756     // A variable that appears in a private clause must not have a
17757     // const-qualified type unless it is of class type with a mutable member.
17758     if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc))
17759       continue;
17760 
17761     // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17762     // in a Construct]
17763     //  Variables with the predetermined data-sharing attributes may not be
17764     //  listed in data-sharing attributes clauses, except for the cases
17765     //  listed below. For these exceptions only, listing a predetermined
17766     //  variable in a data-sharing attribute clause is allowed and overrides
17767     //  the variable's predetermined data-sharing attributes.
17768     DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17769     if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
17770       Diag(ELoc, diag::err_omp_wrong_dsa)
17771           << getOpenMPClauseNameForDiag(DVar.CKind)
17772           << getOpenMPClauseNameForDiag(OMPC_private);
17773       reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17774       continue;
17775     }
17776 
17777     OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17778     // Variably modified types are not supported for tasks.
17779     if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
17780         isOpenMPTaskingDirective(CurrDir)) {
17781       Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17782           << getOpenMPClauseNameForDiag(OMPC_private) << Type
17783           << getOpenMPDirectiveName(CurrDir, OMPVersion);
17784       bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17785                                VarDecl::DeclarationOnly;
17786       Diag(D->getLocation(),
17787            IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17788           << D;
17789       continue;
17790     }
17791 
17792     // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17793     // A list item cannot appear in both a map clause and a data-sharing
17794     // attribute clause on the same construct
17795     //
17796     // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17797     // A list item cannot appear in both a map clause and a data-sharing
17798     // attribute clause on the same construct unless the construct is a
17799     // combined construct.
17800     if ((getLangOpts().OpenMP <= 45 &&
17801          isOpenMPTargetExecutionDirective(CurrDir)) ||
17802         CurrDir == OMPD_target) {
17803       OpenMPClauseKind ConflictKind;
17804       if (DSAStack->checkMappableExprComponentListsForDecl(
17805               VD, /*CurrentRegionOnly=*/true,
17806               [&](OMPClauseMappableExprCommon::MappableExprComponentListRef,
17807                   OpenMPClauseKind WhereFoundClauseKind) -> bool {
17808                 ConflictKind = WhereFoundClauseKind;
17809                 return true;
17810               })) {
17811         Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17812             << getOpenMPClauseNameForDiag(OMPC_private)
17813             << getOpenMPClauseNameForDiag(ConflictKind)
17814             << getOpenMPDirectiveName(CurrDir, OMPVersion);
17815         reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17816         continue;
17817       }
17818     }
17819 
17820     // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
17821     //  A variable of class type (or array thereof) that appears in a private
17822     //  clause requires an accessible, unambiguous default constructor for the
17823     //  class type.
17824     // Generate helper private variable and initialize it with the default
17825     // value. The address of the original variable is replaced by the address of
17826     // the new private variable in CodeGen. This new variable is not added to
17827     // IdResolver, so the code in the OpenMP region uses original variable for
17828     // proper diagnostics.
17829     Type = Type.getUnqualifiedType();
17830     VarDecl *VDPrivate =
17831         buildVarDecl(SemaRef, ELoc, Type, D->getName(),
17832                      D->hasAttrs() ? &D->getAttrs() : nullptr,
17833                      VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
17834     SemaRef.ActOnUninitializedDecl(VDPrivate);
17835     if (VDPrivate->isInvalidDecl())
17836       continue;
17837     DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
17838         SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
17839 
17840     DeclRefExpr *Ref = nullptr;
17841     if (!VD && !SemaRef.CurContext->isDependentContext()) {
17842       auto *FD = dyn_cast<FieldDecl>(D);
17843       VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
17844       if (VD)
17845         Ref = buildDeclRefExpr(SemaRef, VD, VD->getType().getNonReferenceType(),
17846                                RefExpr->getExprLoc());
17847       else
17848         Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
17849     }
17850     if (!IsImplicitClause)
17851       DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
17852     Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17853                        ? RefExpr->IgnoreParens()
17854                        : Ref);
17855     PrivateCopies.push_back(VDPrivateRefExpr);
17856   }
17857 
17858   if (Vars.empty())
17859     return nullptr;
17860 
17861   return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17862                                   Vars, PrivateCopies);
17863 }
17864 
ActOnOpenMPFirstprivateClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)17865 OMPClause *SemaOpenMP::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
17866                                                      SourceLocation StartLoc,
17867                                                      SourceLocation LParenLoc,
17868                                                      SourceLocation EndLoc) {
17869   SmallVector<Expr *, 8> Vars;
17870   SmallVector<Expr *, 8> PrivateCopies;
17871   SmallVector<Expr *, 8> Inits;
17872   SmallVector<Decl *, 4> ExprCaptures;
17873   bool IsImplicitClause =
17874       StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17875   SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
17876   unsigned OMPVersion = getLangOpts().OpenMP;
17877 
17878   for (Expr *RefExpr : VarList) {
17879     assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
17880     SourceLocation ELoc;
17881     SourceRange ERange;
17882     Expr *SimpleRefExpr = RefExpr;
17883     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17884     if (Res.second) {
17885       // It will be analyzed later.
17886       Vars.push_back(RefExpr);
17887       PrivateCopies.push_back(nullptr);
17888       Inits.push_back(nullptr);
17889     }
17890     ValueDecl *D = Res.first;
17891     if (!D)
17892       continue;
17893 
17894     ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
17895     QualType Type = D->getType();
17896     auto *VD = dyn_cast<VarDecl>(D);
17897 
17898     // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17899     //  A variable that appears in a private clause must not have an incomplete
17900     //  type or a reference type.
17901     if (SemaRef.RequireCompleteType(ELoc, Type,
17902                                     diag::err_omp_firstprivate_incomplete_type))
17903       continue;
17904     Type = Type.getNonReferenceType();
17905 
17906     // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
17907     //  A variable of class type (or array thereof) that appears in a private
17908     //  clause requires an accessible, unambiguous copy constructor for the
17909     //  class type.
17910     QualType ElemType =
17911         getASTContext().getBaseElementType(Type).getNonReferenceType();
17912 
17913     // If an implicit firstprivate variable found it was checked already.
17914     DSAStackTy::DSAVarData TopDVar;
17915     if (!IsImplicitClause) {
17916       DSAStackTy::DSAVarData DVar =
17917           DSAStack->getTopDSA(D, /*FromParent=*/false);
17918       TopDVar = DVar;
17919       OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17920       bool IsConstant = ElemType.isConstant(getASTContext());
17921       // OpenMP [2.4.13, Data-sharing Attribute Clauses]
17922       //  A list item that specifies a given variable may not appear in more
17923       // than one clause on the same directive, except that a variable may be
17924       //  specified in both firstprivate and lastprivate clauses.
17925       // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
17926       // A list item may appear in a firstprivate or lastprivate clause but not
17927       // both.
17928       if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
17929           (isOpenMPDistributeDirective(CurrDir) ||
17930            DVar.CKind != OMPC_lastprivate) &&
17931           DVar.RefExpr) {
17932         Diag(ELoc, diag::err_omp_wrong_dsa)
17933             << getOpenMPClauseNameForDiag(DVar.CKind)
17934             << getOpenMPClauseNameForDiag(OMPC_firstprivate);
17935         reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17936         continue;
17937       }
17938 
17939       // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17940       // in a Construct]
17941       //  Variables with the predetermined data-sharing attributes may not be
17942       //  listed in data-sharing attributes clauses, except for the cases
17943       //  listed below. For these exceptions only, listing a predetermined
17944       //  variable in a data-sharing attribute clause is allowed and overrides
17945       //  the variable's predetermined data-sharing attributes.
17946       // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17947       // in a Construct, C/C++, p.2]
17948       //  Variables with const-qualified type having no mutable member may be
17949       //  listed in a firstprivate clause, even if they are static data members.
17950       if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
17951           DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
17952         Diag(ELoc, diag::err_omp_wrong_dsa)
17953             << getOpenMPClauseNameForDiag(DVar.CKind)
17954             << getOpenMPClauseNameForDiag(OMPC_firstprivate);
17955         reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17956         continue;
17957       }
17958 
17959       // OpenMP [2.9.3.4, Restrictions, p.2]
17960       //  A list item that is private within a parallel region must not appear
17961       //  in a firstprivate clause on a worksharing construct if any of the
17962       //  worksharing regions arising from the worksharing construct ever bind
17963       //  to any of the parallel regions arising from the parallel construct.
17964       // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17965       // A list item that is private within a teams region must not appear in a
17966       // firstprivate clause on a distribute construct if any of the distribute
17967       // regions arising from the distribute construct ever bind to any of the
17968       // teams regions arising from the teams construct.
17969       // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17970       // A list item that appears in a reduction clause of a teams construct
17971       // must not appear in a firstprivate clause on a distribute construct if
17972       // any of the distribute regions arising from the distribute construct
17973       // ever bind to any of the teams regions arising from the teams construct.
17974       if ((isOpenMPWorksharingDirective(CurrDir) ||
17975            isOpenMPDistributeDirective(CurrDir)) &&
17976           !isOpenMPParallelDirective(CurrDir) &&
17977           !isOpenMPTeamsDirective(CurrDir)) {
17978         DVar = DSAStack->getImplicitDSA(D, true);
17979         if (DVar.CKind != OMPC_shared &&
17980             (isOpenMPParallelDirective(DVar.DKind) ||
17981              isOpenMPTeamsDirective(DVar.DKind) ||
17982              DVar.DKind == OMPD_unknown)) {
17983           Diag(ELoc, diag::err_omp_required_access)
17984               << getOpenMPClauseNameForDiag(OMPC_firstprivate)
17985               << getOpenMPClauseNameForDiag(OMPC_shared);
17986           reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17987           continue;
17988         }
17989       }
17990       // OpenMP [2.9.3.4, Restrictions, p.3]
17991       //  A list item that appears in a reduction clause of a parallel construct
17992       //  must not appear in a firstprivate clause on a worksharing or task
17993       //  construct if any of the worksharing or task regions arising from the
17994       //  worksharing or task construct ever bind to any of the parallel regions
17995       //  arising from the parallel construct.
17996       // OpenMP [2.9.3.4, Restrictions, p.4]
17997       //  A list item that appears in a reduction clause in worksharing
17998       //  construct must not appear in a firstprivate clause in a task construct
17999       //  encountered during execution of any of the worksharing regions arising
18000       //  from the worksharing construct.
18001       if (isOpenMPTaskingDirective(CurrDir)) {
18002         DVar = DSAStack->hasInnermostDSA(
18003             D,
18004             [](OpenMPClauseKind C, bool AppliedToPointee) {
18005               return C == OMPC_reduction && !AppliedToPointee;
18006             },
18007             [](OpenMPDirectiveKind K) {
18008               return isOpenMPParallelDirective(K) ||
18009                      isOpenMPWorksharingDirective(K) ||
18010                      isOpenMPTeamsDirective(K);
18011             },
18012             /*FromParent=*/true);
18013         if (DVar.CKind == OMPC_reduction &&
18014             (isOpenMPParallelDirective(DVar.DKind) ||
18015              isOpenMPWorksharingDirective(DVar.DKind) ||
18016              isOpenMPTeamsDirective(DVar.DKind))) {
18017           Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
18018               << getOpenMPDirectiveName(DVar.DKind, OMPVersion);
18019           reportOriginalDsa(SemaRef, DSAStack, D, DVar);
18020           continue;
18021         }
18022       }
18023 
18024       // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18025       // A list item cannot appear in both a map clause and a data-sharing
18026       // attribute clause on the same construct
18027       //
18028       // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18029       // A list item cannot appear in both a map clause and a data-sharing
18030       // attribute clause on the same construct unless the construct is a
18031       // combined construct.
18032       if ((getLangOpts().OpenMP <= 45 &&
18033            isOpenMPTargetExecutionDirective(CurrDir)) ||
18034           CurrDir == OMPD_target) {
18035         OpenMPClauseKind ConflictKind;
18036         if (DSAStack->checkMappableExprComponentListsForDecl(
18037                 VD, /*CurrentRegionOnly=*/true,
18038                 [&ConflictKind](
18039                     OMPClauseMappableExprCommon::MappableExprComponentListRef,
18040                     OpenMPClauseKind WhereFoundClauseKind) {
18041                   ConflictKind = WhereFoundClauseKind;
18042                   return true;
18043                 })) {
18044           Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18045               << getOpenMPClauseNameForDiag(OMPC_firstprivate)
18046               << getOpenMPClauseNameForDiag(ConflictKind)
18047               << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
18048                                         OMPVersion);
18049           reportOriginalDsa(SemaRef, DSAStack, D, DVar);
18050           continue;
18051         }
18052       }
18053     }
18054 
18055     // Variably modified types are not supported for tasks.
18056     if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
18057         isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
18058       Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18059           << getOpenMPClauseNameForDiag(OMPC_firstprivate) << Type
18060           << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
18061                                     OMPVersion);
18062       bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
18063                                VarDecl::DeclarationOnly;
18064       Diag(D->getLocation(),
18065            IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18066           << D;
18067       continue;
18068     }
18069 
18070     Type = Type.getUnqualifiedType();
18071     VarDecl *VDPrivate =
18072         buildVarDecl(SemaRef, ELoc, Type, D->getName(),
18073                      D->hasAttrs() ? &D->getAttrs() : nullptr,
18074                      VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18075     // Generate helper private variable and initialize it with the value of the
18076     // original variable. The address of the original variable is replaced by
18077     // the address of the new private variable in the CodeGen. This new variable
18078     // is not added to IdResolver, so the code in the OpenMP region uses
18079     // original variable for proper diagnostics and variable capturing.
18080     Expr *VDInitRefExpr = nullptr;
18081     // For arrays generate initializer for single element and replace it by the
18082     // original array element in CodeGen.
18083     if (Type->isArrayType()) {
18084       VarDecl *VDInit =
18085           buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName());
18086       VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc);
18087       Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get();
18088       ElemType = ElemType.getUnqualifiedType();
18089       VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(),
18090                                          ElemType, ".firstprivate.temp");
18091       InitializedEntity Entity =
18092           InitializedEntity::InitializeVariable(VDInitTemp);
18093       InitializationKind Kind = InitializationKind::CreateCopy(ELoc, ELoc);
18094 
18095       InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
18096       ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init);
18097       if (Result.isInvalid())
18098         VDPrivate->setInvalidDecl();
18099       else
18100         VDPrivate->setInit(Result.getAs<Expr>());
18101       // Remove temp variable declaration.
18102       getASTContext().Deallocate(VDInitTemp);
18103     } else {
18104       VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type,
18105                                      ".firstprivate.temp");
18106       VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(),
18107                                        RefExpr->getExprLoc());
18108       SemaRef.AddInitializerToDecl(
18109           VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
18110           /*DirectInit=*/false);
18111     }
18112     if (VDPrivate->isInvalidDecl()) {
18113       if (IsImplicitClause) {
18114         Diag(RefExpr->getExprLoc(),
18115              diag::note_omp_task_predetermined_firstprivate_here);
18116       }
18117       continue;
18118     }
18119     SemaRef.CurContext->addDecl(VDPrivate);
18120     DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18121         SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(),
18122         RefExpr->getExprLoc());
18123     DeclRefExpr *Ref = nullptr;
18124     if (!VD && !SemaRef.CurContext->isDependentContext()) {
18125       if (TopDVar.CKind == OMPC_lastprivate) {
18126         Ref = TopDVar.PrivateCopy;
18127       } else {
18128         auto *FD = dyn_cast<FieldDecl>(D);
18129         VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18130         if (VD)
18131           Ref =
18132               buildDeclRefExpr(SemaRef, VD, VD->getType().getNonReferenceType(),
18133                                RefExpr->getExprLoc());
18134         else
18135           Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
18136         if (VD || !isOpenMPCapturedDecl(D))
18137           ExprCaptures.push_back(Ref->getDecl());
18138       }
18139     }
18140     if (!IsImplicitClause)
18141       DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
18142     Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
18143                        ? RefExpr->IgnoreParens()
18144                        : Ref);
18145     PrivateCopies.push_back(VDPrivateRefExpr);
18146     Inits.push_back(VDInitRefExpr);
18147   }
18148 
18149   if (Vars.empty())
18150     return nullptr;
18151 
18152   return OMPFirstprivateClause::Create(
18153       getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
18154       buildPreInits(getASTContext(), ExprCaptures));
18155 }
18156 
ActOnOpenMPLastprivateClause(ArrayRef<Expr * > VarList,OpenMPLastprivateModifier LPKind,SourceLocation LPKindLoc,SourceLocation ColonLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)18157 OMPClause *SemaOpenMP::ActOnOpenMPLastprivateClause(
18158     ArrayRef<Expr *> VarList, OpenMPLastprivateModifier LPKind,
18159     SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
18160     SourceLocation LParenLoc, SourceLocation EndLoc) {
18161   if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
18162     assert(ColonLoc.isValid() && "Colon location must be valid.");
18163     Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
18164         << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
18165                                    /*Last=*/OMPC_LASTPRIVATE_unknown)
18166         << getOpenMPClauseNameForDiag(OMPC_lastprivate);
18167     return nullptr;
18168   }
18169 
18170   SmallVector<Expr *, 8> Vars;
18171   SmallVector<Expr *, 8> SrcExprs;
18172   SmallVector<Expr *, 8> DstExprs;
18173   SmallVector<Expr *, 8> AssignmentOps;
18174   SmallVector<Decl *, 4> ExprCaptures;
18175   SmallVector<Expr *, 4> ExprPostUpdates;
18176   for (Expr *RefExpr : VarList) {
18177     assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18178     SourceLocation ELoc;
18179     SourceRange ERange;
18180     Expr *SimpleRefExpr = RefExpr;
18181     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
18182     if (Res.second) {
18183       // It will be analyzed later.
18184       Vars.push_back(RefExpr);
18185       SrcExprs.push_back(nullptr);
18186       DstExprs.push_back(nullptr);
18187       AssignmentOps.push_back(nullptr);
18188     }
18189     ValueDecl *D = Res.first;
18190     if (!D)
18191       continue;
18192 
18193     QualType Type = D->getType();
18194     auto *VD = dyn_cast<VarDecl>(D);
18195 
18196     // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
18197     //  A variable that appears in a lastprivate clause must not have an
18198     //  incomplete type or a reference type.
18199     if (SemaRef.RequireCompleteType(ELoc, Type,
18200                                     diag::err_omp_lastprivate_incomplete_type))
18201       continue;
18202     Type = Type.getNonReferenceType();
18203 
18204     // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18205     // A variable that is privatized must not have a const-qualified type
18206     // unless it is of class type with a mutable member. This restriction does
18207     // not apply to the firstprivate clause.
18208     //
18209     // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
18210     // A variable that appears in a lastprivate clause must not have a
18211     // const-qualified type unless it is of class type with a mutable member.
18212     if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc))
18213       continue;
18214 
18215     // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
18216     // A list item that appears in a lastprivate clause with the conditional
18217     // modifier must be a scalar variable.
18218     if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
18219       Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
18220       bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
18221                                VarDecl::DeclarationOnly;
18222       Diag(D->getLocation(),
18223            IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18224           << D;
18225       continue;
18226     }
18227 
18228     OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18229     // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18230     // in a Construct]
18231     //  Variables with the predetermined data-sharing attributes may not be
18232     //  listed in data-sharing attributes clauses, except for the cases
18233     //  listed below.
18234     // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18235     // A list item may appear in a firstprivate or lastprivate clause but not
18236     // both.
18237     DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18238     if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
18239         (isOpenMPDistributeDirective(CurrDir) ||
18240          DVar.CKind != OMPC_firstprivate) &&
18241         (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
18242       Diag(ELoc, diag::err_omp_wrong_dsa)
18243           << getOpenMPClauseNameForDiag(DVar.CKind)
18244           << getOpenMPClauseNameForDiag(OMPC_lastprivate);
18245       reportOriginalDsa(SemaRef, DSAStack, D, DVar);
18246       continue;
18247     }
18248 
18249     // OpenMP [2.14.3.5, Restrictions, p.2]
18250     // A list item that is private within a parallel region, or that appears in
18251     // the reduction clause of a parallel construct, must not appear in a
18252     // lastprivate clause on a worksharing construct if any of the corresponding
18253     // worksharing regions ever binds to any of the corresponding parallel
18254     // regions.
18255     DSAStackTy::DSAVarData TopDVar = DVar;
18256     if (isOpenMPWorksharingDirective(CurrDir) &&
18257         !isOpenMPParallelDirective(CurrDir) &&
18258         !isOpenMPTeamsDirective(CurrDir)) {
18259       DVar = DSAStack->getImplicitDSA(D, true);
18260       if (DVar.CKind != OMPC_shared) {
18261         Diag(ELoc, diag::err_omp_required_access)
18262             << getOpenMPClauseNameForDiag(OMPC_lastprivate)
18263             << getOpenMPClauseNameForDiag(OMPC_shared);
18264         reportOriginalDsa(SemaRef, DSAStack, D, DVar);
18265         continue;
18266       }
18267     }
18268 
18269     // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
18270     //  A variable of class type (or array thereof) that appears in a
18271     //  lastprivate clause requires an accessible, unambiguous default
18272     //  constructor for the class type, unless the list item is also specified
18273     //  in a firstprivate clause.
18274     //  A variable of class type (or array thereof) that appears in a
18275     //  lastprivate clause requires an accessible, unambiguous copy assignment
18276     //  operator for the class type.
18277     Type = getASTContext().getBaseElementType(Type).getNonReferenceType();
18278     VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(),
18279                                   Type.getUnqualifiedType(), ".lastprivate.src",
18280                                   D->hasAttrs() ? &D->getAttrs() : nullptr);
18281     DeclRefExpr *PseudoSrcExpr =
18282         buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc);
18283     VarDecl *DstVD =
18284         buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst",
18285                      D->hasAttrs() ? &D->getAttrs() : nullptr);
18286     DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
18287     // For arrays generate assignment operation for single element and replace
18288     // it by the original array element in CodeGen.
18289     ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
18290                                                  PseudoDstExpr, PseudoSrcExpr);
18291     if (AssignmentOp.isInvalid())
18292       continue;
18293     AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
18294                                                /*DiscardedValue=*/false);
18295     if (AssignmentOp.isInvalid())
18296       continue;
18297 
18298     DeclRefExpr *Ref = nullptr;
18299     if (!VD && !SemaRef.CurContext->isDependentContext()) {
18300       if (TopDVar.CKind == OMPC_firstprivate) {
18301         Ref = TopDVar.PrivateCopy;
18302       } else {
18303         Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
18304         if (!isOpenMPCapturedDecl(D))
18305           ExprCaptures.push_back(Ref->getDecl());
18306       }
18307       if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
18308           (!isOpenMPCapturedDecl(D) &&
18309            Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
18310         ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
18311         if (!RefRes.isUsable())
18312           continue;
18313         ExprResult PostUpdateRes =
18314             SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
18315                                SimpleRefExpr, RefRes.get());
18316         if (!PostUpdateRes.isUsable())
18317           continue;
18318         ExprPostUpdates.push_back(
18319             SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
18320       }
18321     }
18322     DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
18323     Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
18324                        ? RefExpr->IgnoreParens()
18325                        : Ref);
18326     SrcExprs.push_back(PseudoSrcExpr);
18327     DstExprs.push_back(PseudoDstExpr);
18328     AssignmentOps.push_back(AssignmentOp.get());
18329   }
18330 
18331   if (Vars.empty())
18332     return nullptr;
18333 
18334   return OMPLastprivateClause::Create(
18335       getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
18336       AssignmentOps, LPKind, LPKindLoc, ColonLoc,
18337       buildPreInits(getASTContext(), ExprCaptures),
18338       buildPostUpdate(SemaRef, ExprPostUpdates));
18339 }
18340 
ActOnOpenMPSharedClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)18341 OMPClause *SemaOpenMP::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
18342                                                SourceLocation StartLoc,
18343                                                SourceLocation LParenLoc,
18344                                                SourceLocation EndLoc) {
18345   SmallVector<Expr *, 8> Vars;
18346   for (Expr *RefExpr : VarList) {
18347     assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18348     SourceLocation ELoc;
18349     SourceRange ERange;
18350     Expr *SimpleRefExpr = RefExpr;
18351     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
18352     if (Res.second) {
18353       // It will be analyzed later.
18354       Vars.push_back(RefExpr);
18355     }
18356     ValueDecl *D = Res.first;
18357     if (!D)
18358       continue;
18359 
18360     auto *VD = dyn_cast<VarDecl>(D);
18361     // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18362     // in a Construct]
18363     //  Variables with the predetermined data-sharing attributes may not be
18364     //  listed in data-sharing attributes clauses, except for the cases
18365     //  listed below. For these exceptions only, listing a predetermined
18366     //  variable in a data-sharing attribute clause is allowed and overrides
18367     //  the variable's predetermined data-sharing attributes.
18368     DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18369     if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
18370         DVar.RefExpr) {
18371       Diag(ELoc, diag::err_omp_wrong_dsa)
18372           << getOpenMPClauseNameForDiag(DVar.CKind)
18373           << getOpenMPClauseNameForDiag(OMPC_shared);
18374       reportOriginalDsa(SemaRef, DSAStack, D, DVar);
18375       continue;
18376     }
18377 
18378     DeclRefExpr *Ref = nullptr;
18379     if (!VD && isOpenMPCapturedDecl(D) &&
18380         !SemaRef.CurContext->isDependentContext())
18381       Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
18382     DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
18383     Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext())
18384                        ? RefExpr->IgnoreParens()
18385                        : Ref);
18386   }
18387 
18388   if (Vars.empty())
18389     return nullptr;
18390 
18391   return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
18392                                  Vars);
18393 }
18394 
18395 namespace {
18396 class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
18397   DSAStackTy *Stack;
18398 
18399 public:
VisitDeclRefExpr(DeclRefExpr * E)18400   bool VisitDeclRefExpr(DeclRefExpr *E) {
18401     if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
18402       DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
18403       if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
18404         return false;
18405       if (DVar.CKind != OMPC_unknown)
18406         return true;
18407       DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
18408           VD,
18409           [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
18410             return isOpenMPPrivate(C) && !AppliedToPointee;
18411           },
18412           [](OpenMPDirectiveKind) { return true; },
18413           /*FromParent=*/true);
18414       return DVarPrivate.CKind != OMPC_unknown;
18415     }
18416     return false;
18417   }
VisitStmt(Stmt * S)18418   bool VisitStmt(Stmt *S) {
18419     for (Stmt *Child : S->children()) {
18420       if (Child && Visit(Child))
18421         return true;
18422     }
18423     return false;
18424   }
DSARefChecker(DSAStackTy * S)18425   explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
18426 };
18427 } // namespace
18428 
18429 namespace {
18430 // Transform MemberExpression for specified FieldDecl of current class to
18431 // DeclRefExpr to specified OMPCapturedExprDecl.
18432 class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
18433   typedef TreeTransform<TransformExprToCaptures> BaseTransform;
18434   ValueDecl *Field = nullptr;
18435   DeclRefExpr *CapturedExpr = nullptr;
18436 
18437 public:
TransformExprToCaptures(Sema & SemaRef,ValueDecl * FieldDecl)18438   TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
18439       : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
18440 
TransformMemberExpr(MemberExpr * E)18441   ExprResult TransformMemberExpr(MemberExpr *E) {
18442     if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
18443         E->getMemberDecl() == Field) {
18444       CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
18445       return CapturedExpr;
18446     }
18447     return BaseTransform::TransformMemberExpr(E);
18448   }
getCapturedExpr()18449   DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
18450 };
18451 } // namespace
18452 
18453 template <typename T, typename U>
filterLookupForUDReductionAndMapper(SmallVectorImpl<U> & Lookups,const llvm::function_ref<T (ValueDecl *)> Gen)18454 static T filterLookupForUDReductionAndMapper(
18455     SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
18456   for (U &Set : Lookups) {
18457     for (auto *D : Set) {
18458       if (T Res = Gen(cast<ValueDecl>(D)))
18459         return Res;
18460     }
18461   }
18462   return T();
18463 }
18464 
findAcceptableDecl(Sema & SemaRef,NamedDecl * D)18465 static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
18466   assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
18467 
18468   for (auto *RD : D->redecls()) {
18469     // Don't bother with extra checks if we already know this one isn't visible.
18470     if (RD == D)
18471       continue;
18472 
18473     auto ND = cast<NamedDecl>(RD);
18474     if (LookupResult::isVisible(SemaRef, ND))
18475       return ND;
18476   }
18477 
18478   return nullptr;
18479 }
18480 
18481 static void
argumentDependentLookup(Sema & SemaRef,const DeclarationNameInfo & Id,SourceLocation Loc,QualType Ty,SmallVectorImpl<UnresolvedSet<8>> & Lookups)18482 argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id,
18483                         SourceLocation Loc, QualType Ty,
18484                         SmallVectorImpl<UnresolvedSet<8>> &Lookups) {
18485   // Find all of the associated namespaces and classes based on the
18486   // arguments we have.
18487   Sema::AssociatedNamespaceSet AssociatedNamespaces;
18488   Sema::AssociatedClassSet AssociatedClasses;
18489   OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
18490   SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
18491                                              AssociatedClasses);
18492 
18493   // C++ [basic.lookup.argdep]p3:
18494   //   Let X be the lookup set produced by unqualified lookup (3.4.1)
18495   //   and let Y be the lookup set produced by argument dependent
18496   //   lookup (defined as follows). If X contains [...] then Y is
18497   //   empty. Otherwise Y is the set of declarations found in the
18498   //   namespaces associated with the argument types as described
18499   //   below. The set of declarations found by the lookup of the name
18500   //   is the union of X and Y.
18501   //
18502   // Here, we compute Y and add its members to the overloaded
18503   // candidate set.
18504   for (auto *NS : AssociatedNamespaces) {
18505     //   When considering an associated namespace, the lookup is the
18506     //   same as the lookup performed when the associated namespace is
18507     //   used as a qualifier (3.4.3.2) except that:
18508     //
18509     //     -- Any using-directives in the associated namespace are
18510     //        ignored.
18511     //
18512     //     -- Any namespace-scope friend functions declared in
18513     //        associated classes are visible within their respective
18514     //        namespaces even if they are not visible during an ordinary
18515     //        lookup (11.4).
18516     DeclContext::lookup_result R = NS->lookup(Id.getName());
18517     for (auto *D : R) {
18518       auto *Underlying = D;
18519       if (auto *USD = dyn_cast<UsingShadowDecl>(D))
18520         Underlying = USD->getTargetDecl();
18521 
18522       if (!isa<OMPDeclareReductionDecl>(Underlying) &&
18523           !isa<OMPDeclareMapperDecl>(Underlying))
18524         continue;
18525 
18526       if (!SemaRef.isVisible(D)) {
18527         D = findAcceptableDecl(SemaRef, D);
18528         if (!D)
18529           continue;
18530         if (auto *USD = dyn_cast<UsingShadowDecl>(D))
18531           Underlying = USD->getTargetDecl();
18532       }
18533       Lookups.emplace_back();
18534       Lookups.back().addDecl(Underlying);
18535     }
18536   }
18537 }
18538 
18539 static ExprResult
buildDeclareReductionRef(Sema & SemaRef,SourceLocation Loc,SourceRange Range,Scope * S,CXXScopeSpec & ReductionIdScopeSpec,const DeclarationNameInfo & ReductionId,QualType Ty,CXXCastPath & BasePath,Expr * UnresolvedReduction)18540 buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
18541                          Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
18542                          const DeclarationNameInfo &ReductionId, QualType Ty,
18543                          CXXCastPath &BasePath, Expr *UnresolvedReduction) {
18544   if (ReductionIdScopeSpec.isInvalid())
18545     return ExprError();
18546   SmallVector<UnresolvedSet<8>, 4> Lookups;
18547   if (S) {
18548     LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18549     Lookup.suppressDiagnostics();
18550     while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec,
18551                                          /*ObjectType=*/QualType())) {
18552       NamedDecl *D = Lookup.getRepresentativeDecl();
18553       do {
18554         S = S->getParent();
18555       } while (S && !S->isDeclScope(D));
18556       if (S)
18557         S = S->getParent();
18558       Lookups.emplace_back();
18559       Lookups.back().append(Lookup.begin(), Lookup.end());
18560       Lookup.clear();
18561     }
18562   } else if (auto *ULE =
18563                  cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
18564     Lookups.push_back(UnresolvedSet<8>());
18565     Decl *PrevD = nullptr;
18566     for (NamedDecl *D : ULE->decls()) {
18567       if (D == PrevD)
18568         Lookups.push_back(UnresolvedSet<8>());
18569       else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
18570         Lookups.back().addDecl(DRD);
18571       PrevD = D;
18572     }
18573   }
18574   if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
18575       Ty->isInstantiationDependentType() ||
18576       Ty->containsUnexpandedParameterPack() ||
18577       filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
18578         return !D->isInvalidDecl() &&
18579                (D->getType()->isDependentType() ||
18580                 D->getType()->isInstantiationDependentType() ||
18581                 D->getType()->containsUnexpandedParameterPack());
18582       })) {
18583     UnresolvedSet<8> ResSet;
18584     for (const UnresolvedSet<8> &Set : Lookups) {
18585       if (Set.empty())
18586         continue;
18587       ResSet.append(Set.begin(), Set.end());
18588       // The last item marks the end of all declarations at the specified scope.
18589       ResSet.addDecl(Set[Set.size() - 1]);
18590     }
18591     return UnresolvedLookupExpr::Create(
18592         SemaRef.Context, /*NamingClass=*/nullptr,
18593         ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
18594         /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false,
18595         /*KnownInstantiationDependent=*/false);
18596   }
18597   // Lookup inside the classes.
18598   // C++ [over.match.oper]p3:
18599   //   For a unary operator @ with an operand of a type whose
18600   //   cv-unqualified version is T1, and for a binary operator @ with
18601   //   a left operand of a type whose cv-unqualified version is T1 and
18602   //   a right operand of a type whose cv-unqualified version is T2,
18603   //   three sets of candidate functions, designated member
18604   //   candidates, non-member candidates and built-in candidates, are
18605   //   constructed as follows:
18606   //     -- If T1 is a complete class type or a class currently being
18607   //        defined, the set of member candidates is the result of the
18608   //        qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
18609   //        the set of member candidates is empty.
18610   LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18611   Lookup.suppressDiagnostics();
18612   if (const auto *TyRec = Ty->getAs<RecordType>()) {
18613     // Complete the type if it can be completed.
18614     // If the type is neither complete nor being defined, bail out now.
18615     if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() ||
18616         TyRec->getDecl()->getDefinition()) {
18617       Lookup.clear();
18618       SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
18619       if (Lookup.empty()) {
18620         Lookups.emplace_back();
18621         Lookups.back().append(Lookup.begin(), Lookup.end());
18622       }
18623     }
18624   }
18625   // Perform ADL.
18626   if (SemaRef.getLangOpts().CPlusPlus)
18627     argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
18628   if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18629           Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
18630             if (!D->isInvalidDecl() &&
18631                 SemaRef.Context.hasSameType(D->getType(), Ty))
18632               return D;
18633             return nullptr;
18634           }))
18635     return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
18636                                     VK_LValue, Loc);
18637   if (SemaRef.getLangOpts().CPlusPlus) {
18638     if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18639             Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
18640               if (!D->isInvalidDecl() &&
18641                   SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
18642                   !Ty.isMoreQualifiedThan(D->getType(),
18643                                           SemaRef.getASTContext()))
18644                 return D;
18645               return nullptr;
18646             })) {
18647       CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
18648                          /*DetectVirtual=*/false);
18649       if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
18650         if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
18651                 VD->getType().getUnqualifiedType()))) {
18652           if (SemaRef.CheckBaseClassAccess(
18653                   Loc, VD->getType(), Ty, Paths.front(),
18654                   /*DiagID=*/0) != Sema::AR_inaccessible) {
18655             SemaRef.BuildBasePathArray(Paths, BasePath);
18656             return SemaRef.BuildDeclRefExpr(
18657                 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc);
18658           }
18659         }
18660       }
18661     }
18662   }
18663   if (ReductionIdScopeSpec.isSet()) {
18664     SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
18665         << Ty << Range;
18666     return ExprError();
18667   }
18668   return ExprEmpty();
18669 }
18670 
18671 namespace {
18672 /// Data for the reduction-based clauses.
18673 struct ReductionData {
18674   /// List of original reduction items.
18675   SmallVector<Expr *, 8> Vars;
18676   /// List of private copies of the reduction items.
18677   SmallVector<Expr *, 8> Privates;
18678   /// LHS expressions for the reduction_op expressions.
18679   SmallVector<Expr *, 8> LHSs;
18680   /// RHS expressions for the reduction_op expressions.
18681   SmallVector<Expr *, 8> RHSs;
18682   /// Reduction operation expression.
18683   SmallVector<Expr *, 8> ReductionOps;
18684   /// inscan copy operation expressions.
18685   SmallVector<Expr *, 8> InscanCopyOps;
18686   /// inscan copy temp array expressions for prefix sums.
18687   SmallVector<Expr *, 8> InscanCopyArrayTemps;
18688   /// inscan copy temp array element expressions for prefix sums.
18689   SmallVector<Expr *, 8> InscanCopyArrayElems;
18690   /// Taskgroup descriptors for the corresponding reduction items in
18691   /// in_reduction clauses.
18692   SmallVector<Expr *, 8> TaskgroupDescriptors;
18693   /// List of captures for clause.
18694   SmallVector<Decl *, 4> ExprCaptures;
18695   /// List of postupdate expressions.
18696   SmallVector<Expr *, 4> ExprPostUpdates;
18697   /// Reduction modifier.
18698   unsigned RedModifier = 0;
18699   /// Original modifier.
18700   unsigned OrigSharingModifier = 0;
18701   /// Private Variable Reduction
18702   SmallVector<bool, 8> IsPrivateVarReduction;
18703   ReductionData() = delete;
18704   /// Reserves required memory for the reduction data.
ReductionData__anon1dd12e447411::ReductionData18705   ReductionData(unsigned Size, unsigned Modifier = 0, unsigned OrgModifier = 0)
18706       : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
18707     Vars.reserve(Size);
18708     Privates.reserve(Size);
18709     LHSs.reserve(Size);
18710     RHSs.reserve(Size);
18711     ReductionOps.reserve(Size);
18712     IsPrivateVarReduction.reserve(Size);
18713     if (RedModifier == OMPC_REDUCTION_inscan) {
18714       InscanCopyOps.reserve(Size);
18715       InscanCopyArrayTemps.reserve(Size);
18716       InscanCopyArrayElems.reserve(Size);
18717     }
18718     TaskgroupDescriptors.reserve(Size);
18719     ExprCaptures.reserve(Size);
18720     ExprPostUpdates.reserve(Size);
18721   }
18722   /// Stores reduction item and reduction operation only (required for dependent
18723   /// reduction item).
push__anon1dd12e447411::ReductionData18724   void push(Expr *Item, Expr *ReductionOp) {
18725     Vars.emplace_back(Item);
18726     Privates.emplace_back(nullptr);
18727     LHSs.emplace_back(nullptr);
18728     RHSs.emplace_back(nullptr);
18729     ReductionOps.emplace_back(ReductionOp);
18730     IsPrivateVarReduction.emplace_back(false);
18731     TaskgroupDescriptors.emplace_back(nullptr);
18732     if (RedModifier == OMPC_REDUCTION_inscan) {
18733       InscanCopyOps.push_back(nullptr);
18734       InscanCopyArrayTemps.push_back(nullptr);
18735       InscanCopyArrayElems.push_back(nullptr);
18736     }
18737   }
18738   /// Stores reduction data.
push__anon1dd12e447411::ReductionData18739   void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
18740             Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
18741             Expr *CopyArrayElem, bool IsPrivate) {
18742     Vars.emplace_back(Item);
18743     Privates.emplace_back(Private);
18744     LHSs.emplace_back(LHS);
18745     RHSs.emplace_back(RHS);
18746     ReductionOps.emplace_back(ReductionOp);
18747     TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
18748     if (RedModifier == OMPC_REDUCTION_inscan) {
18749       InscanCopyOps.push_back(CopyOp);
18750       InscanCopyArrayTemps.push_back(CopyArrayTemp);
18751       InscanCopyArrayElems.push_back(CopyArrayElem);
18752     } else {
18753       assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
18754              CopyArrayElem == nullptr &&
18755              "Copy operation must be used for inscan reductions only.");
18756     }
18757     IsPrivateVarReduction.emplace_back(IsPrivate);
18758   }
18759 };
18760 } // namespace
18761 
checkOMPArraySectionConstantForReduction(ASTContext & Context,const ArraySectionExpr * OASE,bool & SingleElement,SmallVectorImpl<llvm::APSInt> & ArraySizes)18762 static bool checkOMPArraySectionConstantForReduction(
18763     ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
18764     SmallVectorImpl<llvm::APSInt> &ArraySizes) {
18765   const Expr *Length = OASE->getLength();
18766   if (Length == nullptr) {
18767     // For array sections of the form [1:] or [:], we would need to analyze
18768     // the lower bound...
18769     if (OASE->getColonLocFirst().isValid())
18770       return false;
18771 
18772     // This is an array subscript which has implicit length 1!
18773     SingleElement = true;
18774     ArraySizes.push_back(llvm::APSInt::get(1));
18775   } else {
18776     Expr::EvalResult Result;
18777     if (!Length->EvaluateAsInt(Result, Context))
18778       return false;
18779 
18780     llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18781     SingleElement = (ConstantLengthValue.getSExtValue() == 1);
18782     ArraySizes.push_back(ConstantLengthValue);
18783   }
18784 
18785   // Get the base of this array section and walk up from there.
18786   const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
18787 
18788   // We require length = 1 for all array sections except the right-most to
18789   // guarantee that the memory region is contiguous and has no holes in it.
18790   while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) {
18791     Length = TempOASE->getLength();
18792     if (Length == nullptr) {
18793       // For array sections of the form [1:] or [:], we would need to analyze
18794       // the lower bound...
18795       if (OASE->getColonLocFirst().isValid())
18796         return false;
18797 
18798       // This is an array subscript which has implicit length 1!
18799       llvm::APSInt ConstantOne = llvm::APSInt::get(1);
18800       ArraySizes.push_back(ConstantOne);
18801     } else {
18802       Expr::EvalResult Result;
18803       if (!Length->EvaluateAsInt(Result, Context))
18804         return false;
18805 
18806       llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18807       if (ConstantLengthValue.getSExtValue() != 1)
18808         return false;
18809 
18810       ArraySizes.push_back(ConstantLengthValue);
18811     }
18812     Base = TempOASE->getBase()->IgnoreParenImpCasts();
18813   }
18814 
18815   // If we have a single element, we don't need to add the implicit lengths.
18816   if (!SingleElement) {
18817     while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
18818       // Has implicit length 1!
18819       llvm::APSInt ConstantOne = llvm::APSInt::get(1);
18820       ArraySizes.push_back(ConstantOne);
18821       Base = TempASE->getBase()->IgnoreParenImpCasts();
18822     }
18823   }
18824 
18825   // This array section can be privatized as a single value or as a constant
18826   // sized array.
18827   return true;
18828 }
18829 
18830 static BinaryOperatorKind
getRelatedCompoundReductionOp(BinaryOperatorKind BOK)18831 getRelatedCompoundReductionOp(BinaryOperatorKind BOK) {
18832   if (BOK == BO_Add)
18833     return BO_AddAssign;
18834   if (BOK == BO_Mul)
18835     return BO_MulAssign;
18836   if (BOK == BO_And)
18837     return BO_AndAssign;
18838   if (BOK == BO_Or)
18839     return BO_OrAssign;
18840   if (BOK == BO_Xor)
18841     return BO_XorAssign;
18842   return BOK;
18843 }
18844 
actOnOMPReductionKindClause(Sema & S,DSAStackTy * Stack,OpenMPClauseKind ClauseKind,ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ColonLoc,SourceLocation EndLoc,CXXScopeSpec & ReductionIdScopeSpec,const DeclarationNameInfo & ReductionId,ArrayRef<Expr * > UnresolvedReductions,ReductionData & RD)18845 static bool actOnOMPReductionKindClause(
18846     Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
18847     ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
18848     SourceLocation ColonLoc, SourceLocation EndLoc,
18849     CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
18850     ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
18851   DeclarationName DN = ReductionId.getName();
18852   OverloadedOperatorKind OOK = DN.getCXXOverloadedOperator();
18853   BinaryOperatorKind BOK = BO_Comma;
18854 
18855   ASTContext &Context = S.Context;
18856   // OpenMP [2.14.3.6, reduction clause]
18857   // C
18858   // reduction-identifier is either an identifier or one of the following
18859   // operators: +, -, *,  &, |, ^, && and ||
18860   // C++
18861   // reduction-identifier is either an id-expression or one of the following
18862   // operators: +, -, *, &, |, ^, && and ||
18863   switch (OOK) {
18864   case OO_Plus:
18865     BOK = BO_Add;
18866     break;
18867   case OO_Minus:
18868     // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
18869     // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
18870     // reduction identifier.
18871     if (S.LangOpts.OpenMP > 52)
18872       BOK = BO_Comma;
18873     else
18874       BOK = BO_Add;
18875     break;
18876   case OO_Star:
18877     BOK = BO_Mul;
18878     break;
18879   case OO_Amp:
18880     BOK = BO_And;
18881     break;
18882   case OO_Pipe:
18883     BOK = BO_Or;
18884     break;
18885   case OO_Caret:
18886     BOK = BO_Xor;
18887     break;
18888   case OO_AmpAmp:
18889     BOK = BO_LAnd;
18890     break;
18891   case OO_PipePipe:
18892     BOK = BO_LOr;
18893     break;
18894   case OO_New:
18895   case OO_Delete:
18896   case OO_Array_New:
18897   case OO_Array_Delete:
18898   case OO_Slash:
18899   case OO_Percent:
18900   case OO_Tilde:
18901   case OO_Exclaim:
18902   case OO_Equal:
18903   case OO_Less:
18904   case OO_Greater:
18905   case OO_LessEqual:
18906   case OO_GreaterEqual:
18907   case OO_PlusEqual:
18908   case OO_MinusEqual:
18909   case OO_StarEqual:
18910   case OO_SlashEqual:
18911   case OO_PercentEqual:
18912   case OO_CaretEqual:
18913   case OO_AmpEqual:
18914   case OO_PipeEqual:
18915   case OO_LessLess:
18916   case OO_GreaterGreater:
18917   case OO_LessLessEqual:
18918   case OO_GreaterGreaterEqual:
18919   case OO_EqualEqual:
18920   case OO_ExclaimEqual:
18921   case OO_Spaceship:
18922   case OO_PlusPlus:
18923   case OO_MinusMinus:
18924   case OO_Comma:
18925   case OO_ArrowStar:
18926   case OO_Arrow:
18927   case OO_Call:
18928   case OO_Subscript:
18929   case OO_Conditional:
18930   case OO_Coawait:
18931   case NUM_OVERLOADED_OPERATORS:
18932     llvm_unreachable("Unexpected reduction identifier");
18933   case OO_None:
18934     if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
18935       if (II->isStr("max"))
18936         BOK = BO_GT;
18937       else if (II->isStr("min"))
18938         BOK = BO_LT;
18939     }
18940     break;
18941   }
18942 
18943   // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
18944   // A reduction clause with the minus (-) operator was deprecated
18945   if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
18946     S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
18947 
18948   SourceRange ReductionIdRange;
18949   if (ReductionIdScopeSpec.isValid())
18950     ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
18951   else
18952     ReductionIdRange.setBegin(ReductionId.getBeginLoc());
18953   ReductionIdRange.setEnd(ReductionId.getEndLoc());
18954 
18955   auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
18956   bool FirstIter = true;
18957   for (Expr *RefExpr : VarList) {
18958     assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
18959     // OpenMP [2.1, C/C++]
18960     //  A list item is a variable or array section, subject to the restrictions
18961     //  specified in Section 2.4 on page 42 and in each of the sections
18962     // describing clauses and directives for which a list appears.
18963     // OpenMP  [2.14.3.3, Restrictions, p.1]
18964     //  A variable that is part of another variable (as an array or
18965     //  structure element) cannot appear in a private clause.
18966     if (!FirstIter && IR != ER)
18967       ++IR;
18968     FirstIter = false;
18969     SourceLocation ELoc;
18970     SourceRange ERange;
18971     bool IsPrivate = false;
18972     Expr *SimpleRefExpr = RefExpr;
18973     auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
18974                               /*AllowArraySection=*/true);
18975     if (Res.second) {
18976       // Try to find 'declare reduction' corresponding construct before using
18977       // builtin/overloaded operators.
18978       QualType Type = Context.DependentTy;
18979       CXXCastPath BasePath;
18980       ExprResult DeclareReductionRef = buildDeclareReductionRef(
18981           S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18982           ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
18983       Expr *ReductionOp = nullptr;
18984       if (S.CurContext->isDependentContext() &&
18985           (DeclareReductionRef.isUnset() ||
18986            isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
18987         ReductionOp = DeclareReductionRef.get();
18988       // It will be analyzed later.
18989       RD.push(RefExpr, ReductionOp);
18990     }
18991     ValueDecl *D = Res.first;
18992     if (!D)
18993       continue;
18994 
18995     Expr *TaskgroupDescriptor = nullptr;
18996     QualType Type;
18997     auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
18998     auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
18999     if (ASE) {
19000       Type = ASE->getType().getNonReferenceType();
19001     } else if (OASE) {
19002       QualType BaseType =
19003           ArraySectionExpr::getBaseOriginalType(OASE->getBase());
19004       if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
19005         Type = ATy->getElementType();
19006       else
19007         Type = BaseType->getPointeeType();
19008       Type = Type.getNonReferenceType();
19009     } else {
19010       Type = Context.getBaseElementType(D->getType().getNonReferenceType());
19011     }
19012     auto *VD = dyn_cast<VarDecl>(D);
19013 
19014     // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19015     //  A variable that appears in a private clause must not have an incomplete
19016     //  type or a reference type.
19017     if (S.RequireCompleteType(ELoc, D->getType(),
19018                               diag::err_omp_reduction_incomplete_type))
19019       continue;
19020     // OpenMP [2.14.3.6, reduction clause, Restrictions]
19021     // A list item that appears in a reduction clause must not be
19022     // const-qualified.
19023     if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
19024                                   /*AcceptIfMutable=*/false, ASE || OASE))
19025       continue;
19026 
19027     OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
19028     // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
19029     //  If a list-item is a reference type then it must bind to the same object
19030     //  for all threads of the team.
19031     if (!ASE && !OASE) {
19032       if (VD) {
19033         VarDecl *VDDef = VD->getDefinition();
19034         if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
19035           DSARefChecker Check(Stack);
19036           if (Check.Visit(VDDef->getInit())) {
19037             S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
19038                 << getOpenMPClauseNameForDiag(ClauseKind) << ERange;
19039             S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
19040             continue;
19041           }
19042         }
19043       }
19044 
19045       // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19046       // in a Construct]
19047       //  Variables with the predetermined data-sharing attributes may not be
19048       //  listed in data-sharing attributes clauses, except for the cases
19049       //  listed below. For these exceptions only, listing a predetermined
19050       //  variable in a data-sharing attribute clause is allowed and overrides
19051       //  the variable's predetermined data-sharing attributes.
19052       // OpenMP [2.14.3.6, Restrictions, p.3]
19053       //  Any number of reduction clauses can be specified on the directive,
19054       //  but a list item can appear only once in the reduction clauses for that
19055       //  directive.
19056       DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19057       if (DVar.CKind == OMPC_reduction) {
19058         S.Diag(ELoc, diag::err_omp_once_referenced)
19059             << getOpenMPClauseNameForDiag(ClauseKind);
19060         if (DVar.RefExpr)
19061           S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
19062         continue;
19063       }
19064       if (DVar.CKind != OMPC_unknown) {
19065         S.Diag(ELoc, diag::err_omp_wrong_dsa)
19066             << getOpenMPClauseNameForDiag(DVar.CKind)
19067             << getOpenMPClauseNameForDiag(OMPC_reduction);
19068         reportOriginalDsa(S, Stack, D, DVar);
19069         continue;
19070       }
19071 
19072       // OpenMP [2.14.3.6, Restrictions, p.1]
19073       //  A list item that appears in a reduction clause of a worksharing
19074       //  construct must be shared in the parallel regions to which any of the
19075       //  worksharing regions arising from the worksharing construct bind.
19076 
19077       if (S.getLangOpts().OpenMP <= 52 &&
19078           isOpenMPWorksharingDirective(CurrDir) &&
19079           !isOpenMPParallelDirective(CurrDir) &&
19080           !isOpenMPTeamsDirective(CurrDir)) {
19081         DVar = Stack->getImplicitDSA(D, true);
19082         if (DVar.CKind != OMPC_shared) {
19083           S.Diag(ELoc, diag::err_omp_required_access)
19084               << getOpenMPClauseNameForDiag(OMPC_reduction)
19085               << getOpenMPClauseNameForDiag(OMPC_shared);
19086           reportOriginalDsa(S, Stack, D, DVar);
19087           continue;
19088         }
19089       } else if (isOpenMPWorksharingDirective(CurrDir) &&
19090                  !isOpenMPParallelDirective(CurrDir) &&
19091                  !isOpenMPTeamsDirective(CurrDir)) {
19092         // OpenMP 6.0 [ 7.6.10 ]
19093         // Support Reduction over private variables with reduction clause.
19094         // A list item in a reduction clause can now be private in the enclosing
19095         // context. For orphaned constructs it is assumed to be shared unless
19096         // the original(private) modifier appears in the clause.
19097         DVar = Stack->getImplicitDSA(D, true);
19098         // Determine if the variable should be considered private
19099         IsPrivate = DVar.CKind != OMPC_shared;
19100         bool IsOrphaned = false;
19101         OpenMPDirectiveKind ParentDir = Stack->getParentDirective();
19102         IsOrphaned = ParentDir == OMPD_unknown;
19103         if ((IsOrphaned &&
19104              RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
19105           IsPrivate = true;
19106       }
19107     } else {
19108       // Threadprivates cannot be shared between threads, so dignose if the base
19109       // is a threadprivate variable.
19110       DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19111       if (DVar.CKind == OMPC_threadprivate) {
19112         S.Diag(ELoc, diag::err_omp_wrong_dsa)
19113             << getOpenMPClauseNameForDiag(DVar.CKind)
19114             << getOpenMPClauseNameForDiag(OMPC_reduction);
19115         reportOriginalDsa(S, Stack, D, DVar);
19116         continue;
19117       }
19118     }
19119 
19120     // Try to find 'declare reduction' corresponding construct before using
19121     // builtin/overloaded operators.
19122     CXXCastPath BasePath;
19123     ExprResult DeclareReductionRef = buildDeclareReductionRef(
19124         S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19125         ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19126     if (DeclareReductionRef.isInvalid())
19127       continue;
19128     if (S.CurContext->isDependentContext() &&
19129         (DeclareReductionRef.isUnset() ||
19130          isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
19131       RD.push(RefExpr, DeclareReductionRef.get());
19132       continue;
19133     }
19134     if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
19135       // Not allowed reduction identifier is found.
19136       if (S.LangOpts.OpenMP > 52)
19137         S.Diag(ReductionId.getBeginLoc(),
19138                diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
19139             << Type << ReductionIdRange;
19140       else
19141         S.Diag(ReductionId.getBeginLoc(),
19142                diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
19143             << Type << ReductionIdRange;
19144       continue;
19145     }
19146 
19147     // OpenMP [2.14.3.6, reduction clause, Restrictions]
19148     // The type of a list item that appears in a reduction clause must be valid
19149     // for the reduction-identifier. For a max or min reduction in C, the type
19150     // of the list item must be an allowed arithmetic data type: char, int,
19151     // float, double, or _Bool, possibly modified with long, short, signed, or
19152     // unsigned. For a max or min reduction in C++, the type of the list item
19153     // must be an allowed arithmetic data type: char, wchar_t, int, float,
19154     // double, or bool, possibly modified with long, short, signed, or unsigned.
19155     if (DeclareReductionRef.isUnset()) {
19156       if ((BOK == BO_GT || BOK == BO_LT) &&
19157           !(Type->isScalarType() ||
19158             (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
19159         S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
19160             << getOpenMPClauseNameForDiag(ClauseKind)
19161             << S.getLangOpts().CPlusPlus;
19162         if (!ASE && !OASE) {
19163           bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19164                                    VarDecl::DeclarationOnly;
19165           S.Diag(D->getLocation(),
19166                  IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19167               << D;
19168         }
19169         continue;
19170       }
19171       if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
19172           !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
19173         S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
19174             << getOpenMPClauseNameForDiag(ClauseKind);
19175         if (!ASE && !OASE) {
19176           bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19177                                    VarDecl::DeclarationOnly;
19178           S.Diag(D->getLocation(),
19179                  IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19180               << D;
19181         }
19182         continue;
19183       }
19184     }
19185 
19186     Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
19187     VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
19188                                   D->hasAttrs() ? &D->getAttrs() : nullptr);
19189     VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
19190                                   D->hasAttrs() ? &D->getAttrs() : nullptr);
19191     QualType PrivateTy = Type;
19192 
19193     // Try if we can determine constant lengths for all array sections and avoid
19194     // the VLA.
19195     bool ConstantLengthOASE = false;
19196     if (OASE) {
19197       bool SingleElement;
19198       llvm::SmallVector<llvm::APSInt, 4> ArraySizes;
19199       ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
19200           Context, OASE, SingleElement, ArraySizes);
19201 
19202       // If we don't have a single element, we must emit a constant array type.
19203       if (ConstantLengthOASE && !SingleElement) {
19204         for (llvm::APSInt &Size : ArraySizes)
19205           PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
19206                                                    ArraySizeModifier::Normal,
19207                                                    /*IndexTypeQuals=*/0);
19208       }
19209     }
19210 
19211     if ((OASE && !ConstantLengthOASE) ||
19212         (!OASE && !ASE &&
19213          D->getType().getNonReferenceType()->isVariablyModifiedType())) {
19214       if (!Context.getTargetInfo().isVLASupported()) {
19215         if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
19216           S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19217           S.Diag(ELoc, diag::note_vla_unsupported);
19218           continue;
19219         } else {
19220           S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19221           S.targetDiag(ELoc, diag::note_vla_unsupported);
19222         }
19223       }
19224       // For arrays/array sections only:
19225       // Create pseudo array type for private copy. The size for this array will
19226       // be generated during codegen.
19227       // For array subscripts or single variables Private Ty is the same as Type
19228       // (type of the variable or single array element).
19229       PrivateTy = Context.getVariableArrayType(
19230           Type,
19231           new (Context)
19232               OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
19233           ArraySizeModifier::Normal, /*IndexTypeQuals=*/0);
19234     } else if (!ASE && !OASE &&
19235                Context.getAsArrayType(D->getType().getNonReferenceType())) {
19236       PrivateTy = D->getType().getNonReferenceType();
19237     }
19238     // Private copy.
19239     VarDecl *PrivateVD =
19240         buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19241                      D->hasAttrs() ? &D->getAttrs() : nullptr,
19242                      VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19243     // Add initializer for private variable.
19244     Expr *Init = nullptr;
19245     DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
19246     DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
19247     if (DeclareReductionRef.isUsable()) {
19248       auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
19249       auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
19250       if (DRD->getInitializer()) {
19251         Init = DRDRef;
19252         RHSVD->setInit(DRDRef);
19253         RHSVD->setInitStyle(VarDecl::CallInit);
19254       }
19255     } else {
19256       switch (BOK) {
19257       case BO_Add:
19258       case BO_Xor:
19259       case BO_Or:
19260       case BO_LOr:
19261         // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
19262         if (Type->isScalarType() || Type->isAnyComplexType())
19263           Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
19264         break;
19265       case BO_Mul:
19266       case BO_LAnd:
19267         if (Type->isScalarType() || Type->isAnyComplexType()) {
19268           // '*' and '&&' reduction ops - initializer is '1'.
19269           Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
19270         }
19271         break;
19272       case BO_And: {
19273         // '&' reduction op - initializer is '~0'.
19274         QualType OrigType = Type;
19275         if (auto *ComplexTy = OrigType->getAs<ComplexType>())
19276           Type = ComplexTy->getElementType();
19277         if (Type->isRealFloatingType()) {
19278           llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
19279               Context.getFloatTypeSemantics(Type));
19280           Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19281                                          Type, ELoc);
19282         } else if (Type->isScalarType()) {
19283           uint64_t Size = Context.getTypeSize(Type);
19284           QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
19285           llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
19286           Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19287         }
19288         if (Init && OrigType->isAnyComplexType()) {
19289           // Init = 0xFFFF + 0xFFFFi;
19290           auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
19291           Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
19292         }
19293         Type = OrigType;
19294         break;
19295       }
19296       case BO_LT:
19297       case BO_GT: {
19298         // 'min' reduction op - initializer is 'Largest representable number in
19299         // the reduction list item type'.
19300         // 'max' reduction op - initializer is 'Least representable number in
19301         // the reduction list item type'.
19302         if (Type->isIntegerType() || Type->isPointerType()) {
19303           bool IsSigned = Type->hasSignedIntegerRepresentation();
19304           uint64_t Size = Context.getTypeSize(Type);
19305           QualType IntTy =
19306               Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
19307           llvm::APInt InitValue =
19308               (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
19309                                         : llvm::APInt::getMinValue(Size)
19310               : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
19311                              : llvm::APInt::getMaxValue(Size);
19312           Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19313           if (Type->isPointerType()) {
19314             // Cast to pointer type.
19315             ExprResult CastExpr = S.BuildCStyleCastExpr(
19316                 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
19317             if (CastExpr.isInvalid())
19318               continue;
19319             Init = CastExpr.get();
19320           }
19321         } else if (Type->isRealFloatingType()) {
19322           llvm::APFloat InitValue = llvm::APFloat::getLargest(
19323               Context.getFloatTypeSemantics(Type), BOK != BO_LT);
19324           Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19325                                          Type, ELoc);
19326         }
19327         break;
19328       }
19329       case BO_PtrMemD:
19330       case BO_PtrMemI:
19331       case BO_MulAssign:
19332       case BO_Div:
19333       case BO_Rem:
19334       case BO_Sub:
19335       case BO_Shl:
19336       case BO_Shr:
19337       case BO_LE:
19338       case BO_GE:
19339       case BO_EQ:
19340       case BO_NE:
19341       case BO_Cmp:
19342       case BO_AndAssign:
19343       case BO_XorAssign:
19344       case BO_OrAssign:
19345       case BO_Assign:
19346       case BO_AddAssign:
19347       case BO_SubAssign:
19348       case BO_DivAssign:
19349       case BO_RemAssign:
19350       case BO_ShlAssign:
19351       case BO_ShrAssign:
19352       case BO_Comma:
19353         llvm_unreachable("Unexpected reduction operation");
19354       }
19355     }
19356     if (Init && DeclareReductionRef.isUnset()) {
19357       S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
19358       // Store initializer for single element in private copy. Will be used
19359       // during codegen.
19360       PrivateVD->setInit(RHSVD->getInit());
19361       PrivateVD->setInitStyle(RHSVD->getInitStyle());
19362     } else if (!Init) {
19363       S.ActOnUninitializedDecl(RHSVD);
19364       // Store initializer for single element in private copy. Will be used
19365       // during codegen.
19366       PrivateVD->setInit(RHSVD->getInit());
19367       PrivateVD->setInitStyle(RHSVD->getInitStyle());
19368     }
19369     if (RHSVD->isInvalidDecl())
19370       continue;
19371     if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
19372       S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
19373           << Type << ReductionIdRange;
19374       bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19375                                VarDecl::DeclarationOnly;
19376       S.Diag(D->getLocation(),
19377              IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19378           << D;
19379       continue;
19380     }
19381     DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
19382     ExprResult ReductionOp;
19383     if (DeclareReductionRef.isUsable()) {
19384       QualType RedTy = DeclareReductionRef.get()->getType();
19385       QualType PtrRedTy = Context.getPointerType(RedTy);
19386       ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
19387       ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
19388       if (!BasePath.empty()) {
19389         LHS = S.DefaultLvalueConversion(LHS.get());
19390         RHS = S.DefaultLvalueConversion(RHS.get());
19391         LHS = ImplicitCastExpr::Create(
19392             Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
19393             LHS.get()->getValueKind(), FPOptionsOverride());
19394         RHS = ImplicitCastExpr::Create(
19395             Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
19396             RHS.get()->getValueKind(), FPOptionsOverride());
19397       }
19398       FunctionProtoType::ExtProtoInfo EPI;
19399       QualType Params[] = {PtrRedTy, PtrRedTy};
19400       QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
19401       auto *OVE = new (Context) OpaqueValueExpr(
19402           ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
19403           S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
19404       Expr *Args[] = {LHS.get(), RHS.get()};
19405       ReductionOp =
19406           CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
19407                            S.CurFPFeatureOverrides());
19408     } else {
19409       BinaryOperatorKind CombBOK = getRelatedCompoundReductionOp(BOK);
19410       if (Type->isRecordType() && CombBOK != BOK) {
19411         Sema::TentativeAnalysisScope Trap(S);
19412         ReductionOp =
19413             S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19414                          CombBOK, LHSDRE, RHSDRE);
19415       }
19416       if (!ReductionOp.isUsable()) {
19417         ReductionOp =
19418             S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
19419                          LHSDRE, RHSDRE);
19420         if (ReductionOp.isUsable()) {
19421           if (BOK != BO_LT && BOK != BO_GT) {
19422             ReductionOp =
19423                 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19424                              BO_Assign, LHSDRE, ReductionOp.get());
19425           } else {
19426             auto *ConditionalOp = new (Context)
19427                 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
19428                                     RHSDRE, Type, VK_LValue, OK_Ordinary);
19429             ReductionOp =
19430                 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19431                              BO_Assign, LHSDRE, ConditionalOp);
19432           }
19433         }
19434       }
19435       if (ReductionOp.isUsable())
19436         ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
19437                                             /*DiscardedValue=*/false);
19438       if (!ReductionOp.isUsable())
19439         continue;
19440     }
19441 
19442     // Add copy operations for inscan reductions.
19443     // LHS = RHS;
19444     ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
19445     if (ClauseKind == OMPC_reduction &&
19446         RD.RedModifier == OMPC_REDUCTION_inscan) {
19447       ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
19448       CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
19449                                RHS.get());
19450       if (!CopyOpRes.isUsable())
19451         continue;
19452       CopyOpRes =
19453           S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
19454       if (!CopyOpRes.isUsable())
19455         continue;
19456       // For simd directive and simd-based directives in simd mode no need to
19457       // construct temp array, need just a single temp element.
19458       if (Stack->getCurrentDirective() == OMPD_simd ||
19459           (S.getLangOpts().OpenMPSimd &&
19460            isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
19461         VarDecl *TempArrayVD =
19462             buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19463                          D->hasAttrs() ? &D->getAttrs() : nullptr);
19464         // Add a constructor to the temp decl.
19465         S.ActOnUninitializedDecl(TempArrayVD);
19466         TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
19467       } else {
19468         // Build temp array for prefix sum.
19469         auto *Dim = new (S.Context)
19470             OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
19471         QualType ArrayTy = S.Context.getVariableArrayType(
19472             PrivateTy, Dim, ArraySizeModifier::Normal,
19473             /*IndexTypeQuals=*/0);
19474         VarDecl *TempArrayVD =
19475             buildVarDecl(S, ELoc, ArrayTy, D->getName(),
19476                          D->hasAttrs() ? &D->getAttrs() : nullptr);
19477         // Add a constructor to the temp decl.
19478         S.ActOnUninitializedDecl(TempArrayVD);
19479         TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
19480         TempArrayElem =
19481             S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
19482         auto *Idx = new (S.Context)
19483             OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
19484         TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
19485                                                           ELoc, Idx, ELoc);
19486       }
19487     }
19488 
19489     // OpenMP [2.15.4.6, Restrictions, p.2]
19490     // A list item that appears in an in_reduction clause of a task construct
19491     // must appear in a task_reduction clause of a construct associated with a
19492     // taskgroup region that includes the participating task in its taskgroup
19493     // set. The construct associated with the innermost region that meets this
19494     // condition must specify the same reduction-identifier as the in_reduction
19495     // clause.
19496     if (ClauseKind == OMPC_in_reduction) {
19497       SourceRange ParentSR;
19498       BinaryOperatorKind ParentBOK;
19499       const Expr *ParentReductionOp = nullptr;
19500       Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
19501       DSAStackTy::DSAVarData ParentBOKDSA =
19502           Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
19503                                                   ParentBOKTD);
19504       DSAStackTy::DSAVarData ParentReductionOpDSA =
19505           Stack->getTopMostTaskgroupReductionData(
19506               D, ParentSR, ParentReductionOp, ParentReductionOpTD);
19507       bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
19508       bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
19509       if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
19510           (DeclareReductionRef.isUsable() && IsParentBOK) ||
19511           (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
19512         bool EmitError = true;
19513         if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
19514           llvm::FoldingSetNodeID RedId, ParentRedId;
19515           ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
19516           DeclareReductionRef.get()->Profile(RedId, Context,
19517                                              /*Canonical=*/true);
19518           EmitError = RedId != ParentRedId;
19519         }
19520         if (EmitError) {
19521           S.Diag(ReductionId.getBeginLoc(),
19522                  diag::err_omp_reduction_identifier_mismatch)
19523               << ReductionIdRange << RefExpr->getSourceRange();
19524           S.Diag(ParentSR.getBegin(),
19525                  diag::note_omp_previous_reduction_identifier)
19526               << ParentSR
19527               << (IsParentBOK ? ParentBOKDSA.RefExpr
19528                               : ParentReductionOpDSA.RefExpr)
19529                      ->getSourceRange();
19530           continue;
19531         }
19532       }
19533       TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
19534     }
19535 
19536     DeclRefExpr *Ref = nullptr;
19537     Expr *VarsExpr = RefExpr->IgnoreParens();
19538     if (!VD && !S.CurContext->isDependentContext()) {
19539       if (ASE || OASE) {
19540         TransformExprToCaptures RebuildToCapture(S, D);
19541         VarsExpr =
19542             RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
19543         Ref = RebuildToCapture.getCapturedExpr();
19544       } else {
19545         VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
19546       }
19547       if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
19548         RD.ExprCaptures.emplace_back(Ref->getDecl());
19549         if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19550           ExprResult RefRes = S.DefaultLvalueConversion(Ref);
19551           if (!RefRes.isUsable())
19552             continue;
19553           ExprResult PostUpdateRes =
19554               S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
19555                            RefRes.get());
19556           if (!PostUpdateRes.isUsable())
19557             continue;
19558           if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
19559               Stack->getCurrentDirective() == OMPD_taskgroup) {
19560             S.Diag(RefExpr->getExprLoc(),
19561                    diag::err_omp_reduction_non_addressable_expression)
19562                 << RefExpr->getSourceRange();
19563             continue;
19564           }
19565           RD.ExprPostUpdates.emplace_back(
19566               S.IgnoredValueConversions(PostUpdateRes.get()).get());
19567         }
19568       }
19569     }
19570     // All reduction items are still marked as reduction (to do not increase
19571     // code base size).
19572     unsigned Modifier = RD.RedModifier;
19573     // Consider task_reductions as reductions with task modifier. Required for
19574     // correct analysis of in_reduction clauses.
19575     if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
19576       Modifier = OMPC_REDUCTION_task;
19577     Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
19578                   ASE || OASE);
19579     if (Modifier == OMPC_REDUCTION_task &&
19580         (CurrDir == OMPD_taskgroup ||
19581          ((isOpenMPParallelDirective(CurrDir) ||
19582            isOpenMPWorksharingDirective(CurrDir)) &&
19583           !isOpenMPSimdDirective(CurrDir)))) {
19584       if (DeclareReductionRef.isUsable())
19585         Stack->addTaskgroupReductionData(D, ReductionIdRange,
19586                                          DeclareReductionRef.get());
19587       else
19588         Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
19589     }
19590     RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
19591             TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
19592             TempArrayElem.get(), IsPrivate);
19593   }
19594   return RD.Vars.empty();
19595 }
19596 
ActOnOpenMPReductionClause(ArrayRef<Expr * > VarList,OpenMPVarListDataTy::OpenMPReductionClauseModifiers Modifiers,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ModifierLoc,SourceLocation ColonLoc,SourceLocation EndLoc,CXXScopeSpec & ReductionIdScopeSpec,const DeclarationNameInfo & ReductionId,ArrayRef<Expr * > UnresolvedReductions)19597 OMPClause *SemaOpenMP::ActOnOpenMPReductionClause(
19598     ArrayRef<Expr *> VarList,
19599     OpenMPVarListDataTy::OpenMPReductionClauseModifiers Modifiers,
19600     SourceLocation StartLoc, SourceLocation LParenLoc,
19601     SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
19602     CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19603     ArrayRef<Expr *> UnresolvedReductions) {
19604   OpenMPReductionClauseModifier Modifier =
19605       static_cast<OpenMPReductionClauseModifier>(Modifiers.ExtraModifier);
19606   OpenMPOriginalSharingModifier OriginalSharingModifier =
19607       static_cast<OpenMPOriginalSharingModifier>(
19608           Modifiers.OriginalSharingModifier);
19609   if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
19610     Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
19611         << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
19612                                    /*Last=*/OMPC_REDUCTION_unknown)
19613         << getOpenMPClauseNameForDiag(OMPC_reduction);
19614     return nullptr;
19615   }
19616   // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
19617   // A reduction clause with the inscan reduction-modifier may only appear on a
19618   // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
19619   // construct, a parallel worksharing-loop construct or a parallel
19620   // worksharing-loop SIMD construct.
19621   if (Modifier == OMPC_REDUCTION_inscan &&
19622       (DSAStack->getCurrentDirective() != OMPD_for &&
19623        DSAStack->getCurrentDirective() != OMPD_for_simd &&
19624        DSAStack->getCurrentDirective() != OMPD_simd &&
19625        DSAStack->getCurrentDirective() != OMPD_parallel_for &&
19626        DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
19627     Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
19628     return nullptr;
19629   }
19630   ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
19631   if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
19632                                   StartLoc, LParenLoc, ColonLoc, EndLoc,
19633                                   ReductionIdScopeSpec, ReductionId,
19634                                   UnresolvedReductions, RD))
19635     return nullptr;
19636 
19637   return OMPReductionClause::Create(
19638       getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
19639       Modifier, RD.Vars,
19640       ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19641       RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
19642       RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
19643       buildPreInits(getASTContext(), RD.ExprCaptures),
19644       buildPostUpdate(SemaRef, RD.ExprPostUpdates), RD.IsPrivateVarReduction,
19645       OriginalSharingModifier);
19646 }
19647 
ActOnOpenMPTaskReductionClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ColonLoc,SourceLocation EndLoc,CXXScopeSpec & ReductionIdScopeSpec,const DeclarationNameInfo & ReductionId,ArrayRef<Expr * > UnresolvedReductions)19648 OMPClause *SemaOpenMP::ActOnOpenMPTaskReductionClause(
19649     ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19650     SourceLocation ColonLoc, SourceLocation EndLoc,
19651     CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19652     ArrayRef<Expr *> UnresolvedReductions) {
19653   ReductionData RD(VarList.size());
19654   if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction,
19655                                   VarList, StartLoc, LParenLoc, ColonLoc,
19656                                   EndLoc, ReductionIdScopeSpec, ReductionId,
19657                                   UnresolvedReductions, RD))
19658     return nullptr;
19659 
19660   return OMPTaskReductionClause::Create(
19661       getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19662       ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19663       RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
19664       buildPreInits(getASTContext(), RD.ExprCaptures),
19665       buildPostUpdate(SemaRef, RD.ExprPostUpdates));
19666 }
19667 
ActOnOpenMPInReductionClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ColonLoc,SourceLocation EndLoc,CXXScopeSpec & ReductionIdScopeSpec,const DeclarationNameInfo & ReductionId,ArrayRef<Expr * > UnresolvedReductions)19668 OMPClause *SemaOpenMP::ActOnOpenMPInReductionClause(
19669     ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19670     SourceLocation ColonLoc, SourceLocation EndLoc,
19671     CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19672     ArrayRef<Expr *> UnresolvedReductions) {
19673   ReductionData RD(VarList.size());
19674   if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList,
19675                                   StartLoc, LParenLoc, ColonLoc, EndLoc,
19676                                   ReductionIdScopeSpec, ReductionId,
19677                                   UnresolvedReductions, RD))
19678     return nullptr;
19679 
19680   return OMPInReductionClause::Create(
19681       getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19682       ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19683       RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
19684       buildPreInits(getASTContext(), RD.ExprCaptures),
19685       buildPostUpdate(SemaRef, RD.ExprPostUpdates));
19686 }
19687 
CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,SourceLocation LinLoc)19688 bool SemaOpenMP::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
19689                                            SourceLocation LinLoc) {
19690   if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
19691       LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
19692     Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
19693         << getLangOpts().CPlusPlus;
19694     return true;
19695   }
19696   return false;
19697 }
19698 
CheckOpenMPLinearDecl(const ValueDecl * D,SourceLocation ELoc,OpenMPLinearClauseKind LinKind,QualType Type,bool IsDeclareSimd)19699 bool SemaOpenMP::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc,
19700                                        OpenMPLinearClauseKind LinKind,
19701                                        QualType Type, bool IsDeclareSimd) {
19702   const auto *VD = dyn_cast_or_null<VarDecl>(D);
19703   // A variable must not have an incomplete type or a reference type.
19704   if (SemaRef.RequireCompleteType(ELoc, Type,
19705                                   diag::err_omp_linear_incomplete_type))
19706     return true;
19707   if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
19708       !Type->isReferenceType()) {
19709     Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
19710         << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
19711     return true;
19712   }
19713   Type = Type.getNonReferenceType();
19714 
19715   // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19716   // A variable that is privatized must not have a const-qualified type
19717   // unless it is of class type with a mutable member. This restriction does
19718   // not apply to the firstprivate clause, nor to the linear clause on
19719   // declarative directives (like declare simd).
19720   if (!IsDeclareSimd &&
19721       rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc))
19722     return true;
19723 
19724   // A list item must be of integral or pointer type.
19725   Type = Type.getUnqualifiedType().getCanonicalType();
19726   const auto *Ty = Type.getTypePtrOrNull();
19727   if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
19728               !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) {
19729     Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
19730     if (D) {
19731       bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19732                                VarDecl::DeclarationOnly;
19733       Diag(D->getLocation(),
19734            IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19735           << D;
19736     }
19737     return true;
19738   }
19739   return false;
19740 }
19741 
ActOnOpenMPLinearClause(ArrayRef<Expr * > VarList,Expr * Step,SourceLocation StartLoc,SourceLocation LParenLoc,OpenMPLinearClauseKind LinKind,SourceLocation LinLoc,SourceLocation ColonLoc,SourceLocation StepModifierLoc,SourceLocation EndLoc)19742 OMPClause *SemaOpenMP::ActOnOpenMPLinearClause(
19743     ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
19744     SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
19745     SourceLocation LinLoc, SourceLocation ColonLoc,
19746     SourceLocation StepModifierLoc, SourceLocation EndLoc) {
19747   SmallVector<Expr *, 8> Vars;
19748   SmallVector<Expr *, 8> Privates;
19749   SmallVector<Expr *, 8> Inits;
19750   SmallVector<Decl *, 4> ExprCaptures;
19751   SmallVector<Expr *, 4> ExprPostUpdates;
19752   // OpenMP 5.2 [Section 5.4.6, linear clause]
19753   // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
19754   // 'ref'
19755   if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
19756       getLangOpts().OpenMP >= 52)
19757     Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
19758   if (CheckOpenMPLinearModifier(LinKind, LinLoc))
19759     LinKind = OMPC_LINEAR_val;
19760   for (Expr *RefExpr : VarList) {
19761     assert(RefExpr && "NULL expr in OpenMP linear clause.");
19762     SourceLocation ELoc;
19763     SourceRange ERange;
19764     Expr *SimpleRefExpr = RefExpr;
19765     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19766     if (Res.second) {
19767       // It will be analyzed later.
19768       Vars.push_back(RefExpr);
19769       Privates.push_back(nullptr);
19770       Inits.push_back(nullptr);
19771     }
19772     ValueDecl *D = Res.first;
19773     if (!D)
19774       continue;
19775 
19776     QualType Type = D->getType();
19777     auto *VD = dyn_cast<VarDecl>(D);
19778 
19779     // OpenMP [2.14.3.7, linear clause]
19780     //  A list-item cannot appear in more than one linear clause.
19781     //  A list-item that appears in a linear clause cannot appear in any
19782     //  other data-sharing attribute clause.
19783     DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19784     if (DVar.RefExpr) {
19785       Diag(ELoc, diag::err_omp_wrong_dsa)
19786           << getOpenMPClauseNameForDiag(DVar.CKind)
19787           << getOpenMPClauseNameForDiag(OMPC_linear);
19788       reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19789       continue;
19790     }
19791 
19792     if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
19793       continue;
19794     Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19795 
19796     // Build private copy of original var.
19797     VarDecl *Private =
19798         buildVarDecl(SemaRef, ELoc, Type, D->getName(),
19799                      D->hasAttrs() ? &D->getAttrs() : nullptr,
19800                      VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19801     DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc);
19802     // Build var to save initial value.
19803     VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start");
19804     Expr *InitExpr;
19805     DeclRefExpr *Ref = nullptr;
19806     if (!VD && !SemaRef.CurContext->isDependentContext()) {
19807       Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19808       if (!isOpenMPCapturedDecl(D)) {
19809         ExprCaptures.push_back(Ref->getDecl());
19810         if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19811           ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
19812           if (!RefRes.isUsable())
19813             continue;
19814           ExprResult PostUpdateRes =
19815               SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
19816                                  SimpleRefExpr, RefRes.get());
19817           if (!PostUpdateRes.isUsable())
19818             continue;
19819           ExprPostUpdates.push_back(
19820               SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
19821         }
19822       }
19823     }
19824     if (LinKind == OMPC_LINEAR_uval)
19825       InitExpr = VD ? VD->getInit() : SimpleRefExpr;
19826     else
19827       InitExpr = VD ? SimpleRefExpr : Ref;
19828     SemaRef.AddInitializerToDecl(
19829         Init, SemaRef.DefaultLvalueConversion(InitExpr).get(),
19830         /*DirectInit=*/false);
19831     DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc);
19832 
19833     DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
19834     Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19835                        ? RefExpr->IgnoreParens()
19836                        : Ref);
19837     Privates.push_back(PrivateRef);
19838     Inits.push_back(InitRef);
19839   }
19840 
19841   if (Vars.empty())
19842     return nullptr;
19843 
19844   Expr *StepExpr = Step;
19845   Expr *CalcStepExpr = nullptr;
19846   if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
19847       !Step->isInstantiationDependent() &&
19848       !Step->containsUnexpandedParameterPack()) {
19849     SourceLocation StepLoc = Step->getBeginLoc();
19850     ExprResult Val = PerformOpenMPImplicitIntegerConversion(StepLoc, Step);
19851     if (Val.isInvalid())
19852       return nullptr;
19853     StepExpr = Val.get();
19854 
19855     // Build var to save the step value.
19856     VarDecl *SaveVar =
19857         buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step");
19858     ExprResult SaveRef =
19859         buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc);
19860     ExprResult CalcStep = SemaRef.BuildBinOp(
19861         SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr);
19862     CalcStep =
19863         SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue=*/false);
19864 
19865     // Warn about zero linear step (it would be probably better specified as
19866     // making corresponding variables 'const').
19867     if (std::optional<llvm::APSInt> Result =
19868             StepExpr->getIntegerConstantExpr(getASTContext())) {
19869       if (!Result->isNegative() && !Result->isStrictlyPositive())
19870         Diag(StepLoc, diag::warn_omp_linear_step_zero)
19871             << Vars[0] << (Vars.size() > 1);
19872     } else if (CalcStep.isUsable()) {
19873       // Calculate the step beforehand instead of doing this on each iteration.
19874       // (This is not used if the number of iterations may be kfold-ed).
19875       CalcStepExpr = CalcStep.get();
19876     }
19877   }
19878 
19879   return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind,
19880                                  LinLoc, ColonLoc, StepModifierLoc, EndLoc,
19881                                  Vars, Privates, Inits, StepExpr, CalcStepExpr,
19882                                  buildPreInits(getASTContext(), ExprCaptures),
19883                                  buildPostUpdate(SemaRef, ExprPostUpdates));
19884 }
19885 
FinishOpenMPLinearClause(OMPLinearClause & Clause,DeclRefExpr * IV,Expr * NumIterations,Sema & SemaRef,Scope * S,DSAStackTy * Stack)19886 static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
19887                                      Expr *NumIterations, Sema &SemaRef,
19888                                      Scope *S, DSAStackTy *Stack) {
19889   // Walk the vars and build update/final expressions for the CodeGen.
19890   SmallVector<Expr *, 8> Updates;
19891   SmallVector<Expr *, 8> Finals;
19892   SmallVector<Expr *, 8> UsedExprs;
19893   Expr *Step = Clause.getStep();
19894   Expr *CalcStep = Clause.getCalcStep();
19895   // OpenMP [2.14.3.7, linear clause]
19896   // If linear-step is not specified it is assumed to be 1.
19897   if (!Step)
19898     Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
19899   else if (CalcStep)
19900     Step = cast<BinaryOperator>(CalcStep)->getLHS();
19901   bool HasErrors = false;
19902   auto CurInit = Clause.inits().begin();
19903   auto CurPrivate = Clause.privates().begin();
19904   OpenMPLinearClauseKind LinKind = Clause.getModifier();
19905   for (Expr *RefExpr : Clause.varlist()) {
19906     SourceLocation ELoc;
19907     SourceRange ERange;
19908     Expr *SimpleRefExpr = RefExpr;
19909     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19910     ValueDecl *D = Res.first;
19911     if (Res.second || !D) {
19912       Updates.push_back(nullptr);
19913       Finals.push_back(nullptr);
19914       HasErrors = true;
19915       continue;
19916     }
19917     auto &&Info = Stack->isLoopControlVariable(D);
19918     // OpenMP [2.15.11, distribute simd Construct]
19919     // A list item may not appear in a linear clause, unless it is the loop
19920     // iteration variable.
19921     if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
19922         isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
19923       SemaRef.Diag(ELoc,
19924                    diag::err_omp_linear_distribute_var_non_loop_iteration);
19925       Updates.push_back(nullptr);
19926       Finals.push_back(nullptr);
19927       HasErrors = true;
19928       continue;
19929     }
19930     Expr *InitExpr = *CurInit;
19931 
19932     // Build privatized reference to the current linear var.
19933     auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
19934     Expr *CapturedRef;
19935     if (LinKind == OMPC_LINEAR_uval)
19936       CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
19937     else
19938       CapturedRef =
19939           buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
19940                            DE->getType().getUnqualifiedType(), DE->getExprLoc(),
19941                            /*RefersToCapture=*/true);
19942 
19943     // Build update: Var = InitExpr + IV * Step
19944     ExprResult Update;
19945     if (!Info.first)
19946       Update = buildCounterUpdate(
19947           SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
19948           /*Subtract=*/false, /*IsNonRectangularLB=*/false);
19949     else
19950       Update = *CurPrivate;
19951     Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
19952                                          /*DiscardedValue=*/false);
19953 
19954     // Build final: Var = PrivCopy;
19955     ExprResult Final;
19956     if (!Info.first)
19957       Final = SemaRef.BuildBinOp(
19958           S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
19959           SemaRef.DefaultLvalueConversion(*CurPrivate).get());
19960     else
19961       Final = *CurPrivate;
19962     Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
19963                                         /*DiscardedValue=*/false);
19964 
19965     if (!Update.isUsable() || !Final.isUsable()) {
19966       Updates.push_back(nullptr);
19967       Finals.push_back(nullptr);
19968       UsedExprs.push_back(nullptr);
19969       HasErrors = true;
19970     } else {
19971       Updates.push_back(Update.get());
19972       Finals.push_back(Final.get());
19973       if (!Info.first)
19974         UsedExprs.push_back(SimpleRefExpr);
19975     }
19976     ++CurInit;
19977     ++CurPrivate;
19978   }
19979   if (Expr *S = Clause.getStep())
19980     UsedExprs.push_back(S);
19981   // Fill the remaining part with the nullptr.
19982   UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
19983   Clause.setUpdates(Updates);
19984   Clause.setFinals(Finals);
19985   Clause.setUsedExprs(UsedExprs);
19986   return HasErrors;
19987 }
19988 
ActOnOpenMPAlignedClause(ArrayRef<Expr * > VarList,Expr * Alignment,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ColonLoc,SourceLocation EndLoc)19989 OMPClause *SemaOpenMP::ActOnOpenMPAlignedClause(
19990     ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
19991     SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
19992   SmallVector<Expr *, 8> Vars;
19993   for (Expr *RefExpr : VarList) {
19994     assert(RefExpr && "NULL expr in OpenMP linear clause.");
19995     SourceLocation ELoc;
19996     SourceRange ERange;
19997     Expr *SimpleRefExpr = RefExpr;
19998     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19999     if (Res.second) {
20000       // It will be analyzed later.
20001       Vars.push_back(RefExpr);
20002     }
20003     ValueDecl *D = Res.first;
20004     if (!D)
20005       continue;
20006 
20007     QualType QType = D->getType();
20008     auto *VD = dyn_cast<VarDecl>(D);
20009 
20010     // OpenMP  [2.8.1, simd construct, Restrictions]
20011     // The type of list items appearing in the aligned clause must be
20012     // array, pointer, reference to array, or reference to pointer.
20013     QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20014     const Type *Ty = QType.getTypePtrOrNull();
20015     if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
20016       Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
20017           << QType << getLangOpts().CPlusPlus << ERange;
20018       bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20019                                VarDecl::DeclarationOnly;
20020       Diag(D->getLocation(),
20021            IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20022           << D;
20023       continue;
20024     }
20025 
20026     // OpenMP  [2.8.1, simd construct, Restrictions]
20027     // A list-item cannot appear in more than one aligned clause.
20028     if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
20029       Diag(ELoc, diag::err_omp_used_in_clause_twice)
20030           << 0 << getOpenMPClauseNameForDiag(OMPC_aligned) << ERange;
20031       Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
20032           << getOpenMPClauseNameForDiag(OMPC_aligned);
20033       continue;
20034     }
20035 
20036     DeclRefExpr *Ref = nullptr;
20037     if (!VD && isOpenMPCapturedDecl(D))
20038       Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
20039     Vars.push_back(SemaRef
20040                        .DefaultFunctionArrayConversion(
20041                            (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
20042                        .get());
20043   }
20044 
20045   // OpenMP [2.8.1, simd construct, Description]
20046   // The parameter of the aligned clause, alignment, must be a constant
20047   // positive integer expression.
20048   // If no optional parameter is specified, implementation-defined default
20049   // alignments for SIMD instructions on the target platforms are assumed.
20050   if (Alignment != nullptr) {
20051     ExprResult AlignResult =
20052         VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
20053     if (AlignResult.isInvalid())
20054       return nullptr;
20055     Alignment = AlignResult.get();
20056   }
20057   if (Vars.empty())
20058     return nullptr;
20059 
20060   return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc,
20061                                   ColonLoc, EndLoc, Vars, Alignment);
20062 }
20063 
ActOnOpenMPCopyinClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)20064 OMPClause *SemaOpenMP::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
20065                                                SourceLocation StartLoc,
20066                                                SourceLocation LParenLoc,
20067                                                SourceLocation EndLoc) {
20068   SmallVector<Expr *, 8> Vars;
20069   SmallVector<Expr *, 8> SrcExprs;
20070   SmallVector<Expr *, 8> DstExprs;
20071   SmallVector<Expr *, 8> AssignmentOps;
20072   for (Expr *RefExpr : VarList) {
20073     assert(RefExpr && "NULL expr in OpenMP copyin clause.");
20074     if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20075       // It will be analyzed later.
20076       Vars.push_back(RefExpr);
20077       SrcExprs.push_back(nullptr);
20078       DstExprs.push_back(nullptr);
20079       AssignmentOps.push_back(nullptr);
20080       continue;
20081     }
20082 
20083     SourceLocation ELoc = RefExpr->getExprLoc();
20084     // OpenMP [2.1, C/C++]
20085     //  A list item is a variable name.
20086     // OpenMP  [2.14.4.1, Restrictions, p.1]
20087     //  A list item that appears in a copyin clause must be threadprivate.
20088     auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
20089     if (!DE || !isa<VarDecl>(DE->getDecl())) {
20090       Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
20091           << 0 << RefExpr->getSourceRange();
20092       continue;
20093     }
20094 
20095     Decl *D = DE->getDecl();
20096     auto *VD = cast<VarDecl>(D);
20097 
20098     QualType Type = VD->getType();
20099     if (Type->isDependentType() || Type->isInstantiationDependentType()) {
20100       // It will be analyzed later.
20101       Vars.push_back(DE);
20102       SrcExprs.push_back(nullptr);
20103       DstExprs.push_back(nullptr);
20104       AssignmentOps.push_back(nullptr);
20105       continue;
20106     }
20107 
20108     // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
20109     //  A list item that appears in a copyin clause must be threadprivate.
20110     if (!DSAStack->isThreadPrivate(VD)) {
20111       unsigned OMPVersion = getLangOpts().OpenMP;
20112       Diag(ELoc, diag::err_omp_required_access)
20113           << getOpenMPClauseNameForDiag(OMPC_copyin)
20114           << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion);
20115       continue;
20116     }
20117 
20118     // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20119     //  A variable of class type (or array thereof) that appears in a
20120     //  copyin clause requires an accessible, unambiguous copy assignment
20121     //  operator for the class type.
20122     QualType ElemType =
20123         getASTContext().getBaseElementType(Type).getNonReferenceType();
20124     VarDecl *SrcVD =
20125         buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
20126                      ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20127     DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
20128         SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
20129     VarDecl *DstVD =
20130         buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst",
20131                      VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20132     DeclRefExpr *PseudoDstExpr =
20133         buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc());
20134     // For arrays generate assignment operation for single element and replace
20135     // it by the original array element in CodeGen.
20136     ExprResult AssignmentOp =
20137         SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
20138                            PseudoDstExpr, PseudoSrcExpr);
20139     if (AssignmentOp.isInvalid())
20140       continue;
20141     AssignmentOp =
20142         SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
20143                                     /*DiscardedValue=*/false);
20144     if (AssignmentOp.isInvalid())
20145       continue;
20146 
20147     DSAStack->addDSA(VD, DE, OMPC_copyin);
20148     Vars.push_back(DE);
20149     SrcExprs.push_back(PseudoSrcExpr);
20150     DstExprs.push_back(PseudoDstExpr);
20151     AssignmentOps.push_back(AssignmentOp.get());
20152   }
20153 
20154   if (Vars.empty())
20155     return nullptr;
20156 
20157   return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
20158                                  Vars, SrcExprs, DstExprs, AssignmentOps);
20159 }
20160 
ActOnOpenMPCopyprivateClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)20161 OMPClause *SemaOpenMP::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
20162                                                     SourceLocation StartLoc,
20163                                                     SourceLocation LParenLoc,
20164                                                     SourceLocation EndLoc) {
20165   SmallVector<Expr *, 8> Vars;
20166   SmallVector<Expr *, 8> SrcExprs;
20167   SmallVector<Expr *, 8> DstExprs;
20168   SmallVector<Expr *, 8> AssignmentOps;
20169   for (Expr *RefExpr : VarList) {
20170     assert(RefExpr && "NULL expr in OpenMP linear clause.");
20171     SourceLocation ELoc;
20172     SourceRange ERange;
20173     Expr *SimpleRefExpr = RefExpr;
20174     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20175     if (Res.second) {
20176       // It will be analyzed later.
20177       Vars.push_back(RefExpr);
20178       SrcExprs.push_back(nullptr);
20179       DstExprs.push_back(nullptr);
20180       AssignmentOps.push_back(nullptr);
20181     }
20182     ValueDecl *D = Res.first;
20183     if (!D)
20184       continue;
20185 
20186     QualType Type = D->getType();
20187     auto *VD = dyn_cast<VarDecl>(D);
20188 
20189     // OpenMP [2.14.4.2, Restrictions, p.2]
20190     //  A list item that appears in a copyprivate clause may not appear in a
20191     //  private or firstprivate clause on the single construct.
20192     if (!VD || !DSAStack->isThreadPrivate(VD)) {
20193       DSAStackTy::DSAVarData DVar =
20194           DSAStack->getTopDSA(D, /*FromParent=*/false);
20195       if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
20196           DVar.RefExpr) {
20197         Diag(ELoc, diag::err_omp_wrong_dsa)
20198             << getOpenMPClauseNameForDiag(DVar.CKind)
20199             << getOpenMPClauseNameForDiag(OMPC_copyprivate);
20200         reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20201         continue;
20202       }
20203 
20204       // OpenMP [2.11.4.2, Restrictions, p.1]
20205       //  All list items that appear in a copyprivate clause must be either
20206       //  threadprivate or private in the enclosing context.
20207       if (DVar.CKind == OMPC_unknown) {
20208         DVar = DSAStack->getImplicitDSA(D, false);
20209         if (DVar.CKind == OMPC_shared) {
20210           Diag(ELoc, diag::err_omp_required_access)
20211               << getOpenMPClauseNameForDiag(OMPC_copyprivate)
20212               << "threadprivate or private in the enclosing context";
20213           reportOriginalDsa(SemaRef, DSAStack, D, DVar);
20214           continue;
20215         }
20216       }
20217     }
20218 
20219     // Variably modified types are not supported.
20220     if (!Type->isAnyPointerType() && Type->isVariablyModifiedType()) {
20221       unsigned OMPVersion = getLangOpts().OpenMP;
20222       Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
20223           << getOpenMPClauseNameForDiag(OMPC_copyprivate) << Type
20224           << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
20225                                     OMPVersion);
20226       bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20227                                VarDecl::DeclarationOnly;
20228       Diag(D->getLocation(),
20229            IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20230           << D;
20231       continue;
20232     }
20233 
20234     // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20235     //  A variable of class type (or array thereof) that appears in a
20236     //  copyin clause requires an accessible, unambiguous copy assignment
20237     //  operator for the class type.
20238     Type = getASTContext()
20239                .getBaseElementType(Type.getNonReferenceType())
20240                .getUnqualifiedType();
20241     VarDecl *SrcVD =
20242         buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
20243                      D->hasAttrs() ? &D->getAttrs() : nullptr);
20244     DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc);
20245     VarDecl *DstVD =
20246         buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
20247                      D->hasAttrs() ? &D->getAttrs() : nullptr);
20248     DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
20249     ExprResult AssignmentOp = SemaRef.BuildBinOp(
20250         DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
20251     if (AssignmentOp.isInvalid())
20252       continue;
20253     AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
20254                                                /*DiscardedValue=*/false);
20255     if (AssignmentOp.isInvalid())
20256       continue;
20257 
20258     // No need to mark vars as copyprivate, they are already threadprivate or
20259     // implicitly private.
20260     assert(VD || isOpenMPCapturedDecl(D));
20261     Vars.push_back(
20262         VD ? RefExpr->IgnoreParens()
20263            : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false));
20264     SrcExprs.push_back(PseudoSrcExpr);
20265     DstExprs.push_back(PseudoDstExpr);
20266     AssignmentOps.push_back(AssignmentOp.get());
20267   }
20268 
20269   if (Vars.empty())
20270     return nullptr;
20271 
20272   return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc,
20273                                       EndLoc, Vars, SrcExprs, DstExprs,
20274                                       AssignmentOps);
20275 }
20276 
ActOnOpenMPFlushClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)20277 OMPClause *SemaOpenMP::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
20278                                               SourceLocation StartLoc,
20279                                               SourceLocation LParenLoc,
20280                                               SourceLocation EndLoc) {
20281   if (VarList.empty())
20282     return nullptr;
20283 
20284   return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
20285                                 VarList);
20286 }
20287 
20288 /// Tries to find omp_depend_t. type.
findOMPDependT(Sema & S,SourceLocation Loc,DSAStackTy * Stack,bool Diagnose=true)20289 static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
20290                            bool Diagnose = true) {
20291   QualType OMPDependT = Stack->getOMPDependT();
20292   if (!OMPDependT.isNull())
20293     return true;
20294   IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
20295   ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
20296   if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
20297     if (Diagnose)
20298       S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
20299     return false;
20300   }
20301   Stack->setOMPDependT(PT.get());
20302   return true;
20303 }
20304 
ActOnOpenMPDepobjClause(Expr * Depobj,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)20305 OMPClause *SemaOpenMP::ActOnOpenMPDepobjClause(Expr *Depobj,
20306                                                SourceLocation StartLoc,
20307                                                SourceLocation LParenLoc,
20308                                                SourceLocation EndLoc) {
20309   if (!Depobj)
20310     return nullptr;
20311 
20312   bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack);
20313 
20314   // OpenMP 5.0, 2.17.10.1 depobj Construct
20315   // depobj is an lvalue expression of type omp_depend_t.
20316   if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
20317       !Depobj->isInstantiationDependent() &&
20318       !Depobj->containsUnexpandedParameterPack() &&
20319       (OMPDependTFound && !getASTContext().typesAreCompatible(
20320                               DSAStack->getOMPDependT(), Depobj->getType(),
20321                               /*CompareUnqualified=*/true))) {
20322     Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20323         << 0 << Depobj->getType() << Depobj->getSourceRange();
20324   }
20325 
20326   if (!Depobj->isLValue()) {
20327     Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20328         << 1 << Depobj->getSourceRange();
20329   }
20330 
20331   return OMPDepobjClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
20332                                  Depobj);
20333 }
20334 
20335 namespace {
20336 // Utility struct that gathers the related info for doacross clause.
20337 struct DoacrossDataInfoTy {
20338   // The list of expressions.
20339   SmallVector<Expr *, 8> Vars;
20340   // The OperatorOffset for doacross loop.
20341   DSAStackTy::OperatorOffsetTy OpsOffs;
20342   // The depended loop count.
20343   llvm::APSInt TotalDepCount;
20344 };
20345 } // namespace
20346 static DoacrossDataInfoTy
ProcessOpenMPDoacrossClauseCommon(Sema & SemaRef,bool IsSource,ArrayRef<Expr * > VarList,DSAStackTy * Stack,SourceLocation EndLoc)20347 ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource,
20348                                   ArrayRef<Expr *> VarList, DSAStackTy *Stack,
20349                                   SourceLocation EndLoc) {
20350 
20351   SmallVector<Expr *, 8> Vars;
20352   DSAStackTy::OperatorOffsetTy OpsOffs;
20353   llvm::APSInt DepCounter(/*BitWidth=*/32);
20354   llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20355 
20356   if (const Expr *OrderedCountExpr =
20357           Stack->getParentOrderedRegionParam().first) {
20358     TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
20359     TotalDepCount.setIsUnsigned(/*Val=*/true);
20360   }
20361 
20362   for (Expr *RefExpr : VarList) {
20363     assert(RefExpr && "NULL expr in OpenMP doacross clause.");
20364     if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20365       // It will be analyzed later.
20366       Vars.push_back(RefExpr);
20367       continue;
20368     }
20369 
20370     SourceLocation ELoc = RefExpr->getExprLoc();
20371     Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20372     if (!IsSource) {
20373       if (Stack->getParentOrderedRegionParam().first &&
20374           DepCounter >= TotalDepCount) {
20375         SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
20376         continue;
20377       }
20378       ++DepCounter;
20379       // OpenMP  [2.13.9, Summary]
20380       // depend(dependence-type : vec), where dependence-type is:
20381       // 'sink' and where vec is the iteration vector, which has the form:
20382       //  x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
20383       // where n is the value specified by the ordered clause in the loop
20384       // directive, xi denotes the loop iteration variable of the i-th nested
20385       // loop associated with the loop directive, and di is a constant
20386       // non-negative integer.
20387       if (SemaRef.CurContext->isDependentContext()) {
20388         // It will be analyzed later.
20389         Vars.push_back(RefExpr);
20390         continue;
20391       }
20392       SimpleExpr = SimpleExpr->IgnoreImplicit();
20393       OverloadedOperatorKind OOK = OO_None;
20394       SourceLocation OOLoc;
20395       Expr *LHS = SimpleExpr;
20396       Expr *RHS = nullptr;
20397       if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
20398         OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
20399         OOLoc = BO->getOperatorLoc();
20400         LHS = BO->getLHS()->IgnoreParenImpCasts();
20401         RHS = BO->getRHS()->IgnoreParenImpCasts();
20402       } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
20403         OOK = OCE->getOperator();
20404         OOLoc = OCE->getOperatorLoc();
20405         LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20406         RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
20407       } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
20408         OOK = MCE->getMethodDecl()
20409                   ->getNameInfo()
20410                   .getName()
20411                   .getCXXOverloadedOperator();
20412         OOLoc = MCE->getCallee()->getExprLoc();
20413         LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
20414         RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20415       }
20416       SourceLocation ELoc;
20417       SourceRange ERange;
20418       auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
20419       if (Res.second) {
20420         // It will be analyzed later.
20421         Vars.push_back(RefExpr);
20422       }
20423       ValueDecl *D = Res.first;
20424       if (!D)
20425         continue;
20426 
20427       if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
20428         SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
20429         continue;
20430       }
20431       if (RHS) {
20432         ExprResult RHSRes =
20433             SemaRef.OpenMP().VerifyPositiveIntegerConstantInClause(
20434                 RHS, OMPC_depend, /*StrictlyPositive=*/false);
20435         if (RHSRes.isInvalid())
20436           continue;
20437       }
20438       if (!SemaRef.CurContext->isDependentContext() &&
20439           Stack->getParentOrderedRegionParam().first &&
20440           DepCounter != Stack->isParentLoopControlVariable(D).first) {
20441         const ValueDecl *VD =
20442             Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
20443         if (VD)
20444           SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20445               << 1 << VD;
20446         else
20447           SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20448               << 0;
20449         continue;
20450       }
20451       OpsOffs.emplace_back(RHS, OOK);
20452     }
20453     Vars.push_back(RefExpr->IgnoreParenImpCasts());
20454   }
20455   if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
20456       TotalDepCount > VarList.size() &&
20457       Stack->getParentOrderedRegionParam().first &&
20458       Stack->getParentLoopControlVariable(VarList.size() + 1)) {
20459     SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
20460         << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
20461   }
20462   return {Vars, OpsOffs, TotalDepCount};
20463 }
20464 
ActOnOpenMPDependClause(const OMPDependClause::DependDataTy & Data,Expr * DepModifier,ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)20465 OMPClause *SemaOpenMP::ActOnOpenMPDependClause(
20466     const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
20467     ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20468     SourceLocation EndLoc) {
20469   OpenMPDependClauseKind DepKind = Data.DepKind;
20470   SourceLocation DepLoc = Data.DepLoc;
20471   if (DSAStack->getCurrentDirective() == OMPD_ordered &&
20472       DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
20473     Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20474         << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_depend);
20475     return nullptr;
20476   }
20477   if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
20478       DepKind == OMPC_DEPEND_mutexinoutset) {
20479     Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
20480     return nullptr;
20481   }
20482   if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
20483        DSAStack->getCurrentDirective() == OMPD_depobj) &&
20484       (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
20485        DepKind == OMPC_DEPEND_sink ||
20486        ((getLangOpts().OpenMP < 50 ||
20487          DSAStack->getCurrentDirective() == OMPD_depobj) &&
20488         DepKind == OMPC_DEPEND_depobj))) {
20489     SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
20490                                        OMPC_DEPEND_outallmemory,
20491                                        OMPC_DEPEND_inoutallmemory};
20492     if (getLangOpts().OpenMP < 50 ||
20493         DSAStack->getCurrentDirective() == OMPD_depobj)
20494       Except.push_back(OMPC_DEPEND_depobj);
20495     if (getLangOpts().OpenMP < 51)
20496       Except.push_back(OMPC_DEPEND_inoutset);
20497     std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
20498                                ? "depend modifier(iterator) or "
20499                                : "";
20500     Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20501         << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
20502                                               /*Last=*/OMPC_DEPEND_unknown,
20503                                               Except)
20504         << getOpenMPClauseNameForDiag(OMPC_depend);
20505     return nullptr;
20506   }
20507   if (DepModifier &&
20508       (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
20509     Diag(DepModifier->getExprLoc(),
20510          diag::err_omp_depend_sink_source_with_modifier);
20511     return nullptr;
20512   }
20513   if (DepModifier &&
20514       !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
20515     Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
20516 
20517   SmallVector<Expr *, 8> Vars;
20518   DSAStackTy::OperatorOffsetTy OpsOffs;
20519   llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20520 
20521   if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
20522     DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
20523         SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
20524     Vars = VarOffset.Vars;
20525     OpsOffs = VarOffset.OpsOffs;
20526     TotalDepCount = VarOffset.TotalDepCount;
20527   } else {
20528     for (Expr *RefExpr : VarList) {
20529       assert(RefExpr && "NULL expr in OpenMP shared clause.");
20530       if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20531         // It will be analyzed later.
20532         Vars.push_back(RefExpr);
20533         continue;
20534       }
20535 
20536       SourceLocation ELoc = RefExpr->getExprLoc();
20537       Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20538       if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
20539         bool OMPDependTFound = getLangOpts().OpenMP >= 50;
20540         if (OMPDependTFound)
20541           OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack,
20542                                            DepKind == OMPC_DEPEND_depobj);
20543         if (DepKind == OMPC_DEPEND_depobj) {
20544           // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20545           // List items used in depend clauses with the depobj dependence type
20546           // must be expressions of the omp_depend_t type.
20547           if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20548               !RefExpr->isInstantiationDependent() &&
20549               !RefExpr->containsUnexpandedParameterPack() &&
20550               (OMPDependTFound &&
20551                !getASTContext().hasSameUnqualifiedType(
20552                    DSAStack->getOMPDependT(), RefExpr->getType()))) {
20553             Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20554                 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
20555             continue;
20556           }
20557           if (!RefExpr->isLValue()) {
20558             Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20559                 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
20560             continue;
20561           }
20562         } else {
20563           // OpenMP 5.0 [2.17.11, Restrictions]
20564           // List items used in depend clauses cannot be zero-length array
20565           // sections.
20566           QualType ExprTy = RefExpr->getType().getNonReferenceType();
20567           const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
20568           if (OASE) {
20569             QualType BaseType =
20570                 ArraySectionExpr::getBaseOriginalType(OASE->getBase());
20571             if (BaseType.isNull())
20572               return nullptr;
20573             if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20574               ExprTy = ATy->getElementType();
20575             else
20576               ExprTy = BaseType->getPointeeType();
20577             if (BaseType.isNull() || ExprTy.isNull())
20578               return nullptr;
20579             ExprTy = ExprTy.getNonReferenceType();
20580             const Expr *Length = OASE->getLength();
20581             Expr::EvalResult Result;
20582             if (Length && !Length->isValueDependent() &&
20583                 Length->EvaluateAsInt(Result, getASTContext()) &&
20584                 Result.Val.getInt().isZero()) {
20585               Diag(ELoc,
20586                    diag::err_omp_depend_zero_length_array_section_not_allowed)
20587                   << SimpleExpr->getSourceRange();
20588               continue;
20589             }
20590           }
20591 
20592           // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20593           // List items used in depend clauses with the in, out, inout,
20594           // inoutset, or mutexinoutset dependence types cannot be
20595           // expressions of the omp_depend_t type.
20596           if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20597               !RefExpr->isInstantiationDependent() &&
20598               !RefExpr->containsUnexpandedParameterPack() &&
20599               (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
20600                (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
20601                                        ExprTy.getTypePtr()))) {
20602             Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20603                 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20604                 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20605                 << RefExpr->getSourceRange();
20606             continue;
20607           }
20608 
20609           auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
20610           if (ASE && !ASE->getBase()->isTypeDependent() &&
20611               !ASE->getBase()
20612                    ->getType()
20613                    .getNonReferenceType()
20614                    ->isPointerType() &&
20615               !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
20616             Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20617                 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20618                 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20619                 << RefExpr->getSourceRange();
20620             continue;
20621           }
20622 
20623           ExprResult Res;
20624           {
20625             Sema::TentativeAnalysisScope Trap(SemaRef);
20626             Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
20627                                                RefExpr->IgnoreParenImpCasts());
20628           }
20629           if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
20630               !isa<OMPArrayShapingExpr>(SimpleExpr)) {
20631             Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20632                 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20633                 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20634                 << RefExpr->getSourceRange();
20635             continue;
20636           }
20637         }
20638       }
20639       Vars.push_back(RefExpr->IgnoreParenImpCasts());
20640     }
20641   }
20642 
20643   if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
20644       DepKind != OMPC_DEPEND_outallmemory &&
20645       DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
20646     return nullptr;
20647 
20648   auto *C = OMPDependClause::Create(
20649       getASTContext(), StartLoc, LParenLoc, EndLoc,
20650       {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
20651       TotalDepCount.getZExtValue());
20652   if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
20653       DSAStack->isParentOrderedRegion())
20654     DSAStack->addDoacrossDependClause(C, OpsOffs);
20655   return C;
20656 }
20657 
ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier,Expr * Device,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ModifierLoc,SourceLocation EndLoc)20658 OMPClause *SemaOpenMP::ActOnOpenMPDeviceClause(
20659     OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc,
20660     SourceLocation LParenLoc, SourceLocation ModifierLoc,
20661     SourceLocation EndLoc) {
20662   assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
20663          "Unexpected device modifier in OpenMP < 50.");
20664 
20665   bool ErrorFound = false;
20666   if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
20667     std::string Values =
20668         getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
20669     Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
20670         << Values << getOpenMPClauseNameForDiag(OMPC_device);
20671     ErrorFound = true;
20672   }
20673 
20674   Expr *ValExpr = Device;
20675   Stmt *HelperValStmt = nullptr;
20676 
20677   // OpenMP [2.9.1, Restrictions]
20678   // The device expression must evaluate to a non-negative integer value.
20679   ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device,
20680                                           /*StrictlyPositive=*/false) ||
20681                ErrorFound;
20682   if (ErrorFound)
20683     return nullptr;
20684 
20685   // OpenMP 5.0 [2.12.5, Restrictions]
20686   // In case of ancestor device-modifier, a requires directive with
20687   // the reverse_offload clause must be specified.
20688   if (Modifier == OMPC_DEVICE_ancestor) {
20689     if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
20690       SemaRef.targetDiag(
20691           StartLoc,
20692           diag::err_omp_device_ancestor_without_requires_reverse_offload);
20693       ErrorFound = true;
20694     }
20695   }
20696 
20697   OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
20698   OpenMPDirectiveKind CaptureRegion =
20699       getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP);
20700   if (CaptureRegion != OMPD_unknown &&
20701       !SemaRef.CurContext->isDependentContext()) {
20702     ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
20703     llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20704     ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
20705     HelperValStmt = buildPreInits(getASTContext(), Captures);
20706   }
20707 
20708   return new (getASTContext())
20709       OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
20710                       LParenLoc, ModifierLoc, EndLoc);
20711 }
20712 
checkTypeMappable(SourceLocation SL,SourceRange SR,Sema & SemaRef,DSAStackTy * Stack,QualType QTy,bool FullCheck=true)20713 static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
20714                               DSAStackTy *Stack, QualType QTy,
20715                               bool FullCheck = true) {
20716   if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
20717     return false;
20718   if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
20719       !QTy.isTriviallyCopyableType(SemaRef.Context))
20720     SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
20721   return true;
20722 }
20723 
20724 /// Return true if it can be proven that the provided array expression
20725 /// (array section or array subscript) does NOT specify the whole size of the
20726 /// array whose base type is \a BaseQTy.
checkArrayExpressionDoesNotReferToWholeSize(Sema & SemaRef,const Expr * E,QualType BaseQTy)20727 static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
20728                                                         const Expr *E,
20729                                                         QualType BaseQTy) {
20730   const auto *OASE = dyn_cast<ArraySectionExpr>(E);
20731 
20732   // If this is an array subscript, it refers to the whole size if the size of
20733   // the dimension is constant and equals 1. Also, an array section assumes the
20734   // format of an array subscript if no colon is used.
20735   if (isa<ArraySubscriptExpr>(E) ||
20736       (OASE && OASE->getColonLocFirst().isInvalid())) {
20737     if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20738       return ATy->getSExtSize() != 1;
20739     // Size can't be evaluated statically.
20740     return false;
20741   }
20742 
20743   assert(OASE && "Expecting array section if not an array subscript.");
20744   const Expr *LowerBound = OASE->getLowerBound();
20745   const Expr *Length = OASE->getLength();
20746 
20747   // If there is a lower bound that does not evaluates to zero, we are not
20748   // covering the whole dimension.
20749   if (LowerBound) {
20750     Expr::EvalResult Result;
20751     if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
20752       return false; // Can't get the integer value as a constant.
20753 
20754     llvm::APSInt ConstLowerBound = Result.Val.getInt();
20755     if (ConstLowerBound.getSExtValue())
20756       return true;
20757   }
20758 
20759   // If we don't have a length we covering the whole dimension.
20760   if (!Length)
20761     return false;
20762 
20763   // If the base is a pointer, we don't have a way to get the size of the
20764   // pointee.
20765   if (BaseQTy->isPointerType())
20766     return false;
20767 
20768   // We can only check if the length is the same as the size of the dimension
20769   // if we have a constant array.
20770   const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
20771   if (!CATy)
20772     return false;
20773 
20774   Expr::EvalResult Result;
20775   if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20776     return false; // Can't get the integer value as a constant.
20777 
20778   llvm::APSInt ConstLength = Result.Val.getInt();
20779   return CATy->getSExtSize() != ConstLength.getSExtValue();
20780 }
20781 
20782 // Return true if it can be proven that the provided array expression (array
20783 // section or array subscript) does NOT specify a single element of the array
20784 // whose base type is \a BaseQTy.
checkArrayExpressionDoesNotReferToUnitySize(Sema & SemaRef,const Expr * E,QualType BaseQTy)20785 static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
20786                                                         const Expr *E,
20787                                                         QualType BaseQTy) {
20788   const auto *OASE = dyn_cast<ArraySectionExpr>(E);
20789 
20790   // An array subscript always refer to a single element. Also, an array section
20791   // assumes the format of an array subscript if no colon is used.
20792   if (isa<ArraySubscriptExpr>(E) ||
20793       (OASE && OASE->getColonLocFirst().isInvalid()))
20794     return false;
20795 
20796   assert(OASE && "Expecting array section if not an array subscript.");
20797   const Expr *Length = OASE->getLength();
20798 
20799   // If we don't have a length we have to check if the array has unitary size
20800   // for this dimension. Also, we should always expect a length if the base type
20801   // is pointer.
20802   if (!Length) {
20803     if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20804       return ATy->getSExtSize() != 1;
20805     // We cannot assume anything.
20806     return false;
20807   }
20808 
20809   // Check if the length evaluates to 1.
20810   Expr::EvalResult Result;
20811   if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20812     return false; // Can't get the integer value as a constant.
20813 
20814   llvm::APSInt ConstLength = Result.Val.getInt();
20815   return ConstLength.getSExtValue() != 1;
20816 }
20817 
20818 // The base of elements of list in a map clause have to be either:
20819 //  - a reference to variable or field.
20820 //  - a member expression.
20821 //  - an array expression.
20822 //
20823 // E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
20824 // reference to 'r'.
20825 //
20826 // If we have:
20827 //
20828 // struct SS {
20829 //   Bla S;
20830 //   foo() {
20831 //     #pragma omp target map (S.Arr[:12]);
20832 //   }
20833 // }
20834 //
20835 // We want to retrieve the member expression 'this->S';
20836 
20837 // OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
20838 //  If a list item is an array section, it must specify contiguous storage.
20839 //
20840 // For this restriction it is sufficient that we make sure only references
20841 // to variables or fields and array expressions, and that no array sections
20842 // exist except in the rightmost expression (unless they cover the whole
20843 // dimension of the array). E.g. these would be invalid:
20844 //
20845 //   r.ArrS[3:5].Arr[6:7]
20846 //
20847 //   r.ArrS[3:5].x
20848 //
20849 // but these would be valid:
20850 //   r.ArrS[3].Arr[6:7]
20851 //
20852 //   r.ArrS[3].x
20853 namespace {
20854 class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
20855   Sema &SemaRef;
20856   OpenMPClauseKind CKind = OMPC_unknown;
20857   OpenMPDirectiveKind DKind = OMPD_unknown;
20858   OMPClauseMappableExprCommon::MappableExprComponentList &Components;
20859   bool IsNonContiguous = false;
20860   bool NoDiagnose = false;
20861   const Expr *RelevantExpr = nullptr;
20862   bool AllowUnitySizeArraySection = true;
20863   bool AllowWholeSizeArraySection = true;
20864   bool AllowAnotherPtr = true;
20865   SourceLocation ELoc;
20866   SourceRange ERange;
20867 
emitErrorMsg()20868   void emitErrorMsg() {
20869     // If nothing else worked, this is not a valid map clause expression.
20870     if (SemaRef.getLangOpts().OpenMP < 50) {
20871       SemaRef.Diag(ELoc,
20872                    diag::err_omp_expected_named_var_member_or_array_expression)
20873           << ERange;
20874     } else {
20875       SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20876           << getOpenMPClauseNameForDiag(CKind) << ERange;
20877     }
20878   }
20879 
20880 public:
VisitDeclRefExpr(DeclRefExpr * DRE)20881   bool VisitDeclRefExpr(DeclRefExpr *DRE) {
20882     if (!isa<VarDecl>(DRE->getDecl())) {
20883       emitErrorMsg();
20884       return false;
20885     }
20886     assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20887     RelevantExpr = DRE;
20888     // Record the component.
20889     Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
20890     return true;
20891   }
20892 
VisitMemberExpr(MemberExpr * ME)20893   bool VisitMemberExpr(MemberExpr *ME) {
20894     Expr *E = ME;
20895     Expr *BaseE = ME->getBase()->IgnoreParenCasts();
20896 
20897     if (isa<CXXThisExpr>(BaseE)) {
20898       assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20899       // We found a base expression: this->Val.
20900       RelevantExpr = ME;
20901     } else {
20902       E = BaseE;
20903     }
20904 
20905     if (!isa<FieldDecl>(ME->getMemberDecl())) {
20906       if (!NoDiagnose) {
20907         SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
20908             << ME->getSourceRange();
20909         return false;
20910       }
20911       if (RelevantExpr)
20912         return false;
20913       return Visit(E);
20914     }
20915 
20916     auto *FD = cast<FieldDecl>(ME->getMemberDecl());
20917 
20918     // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
20919     //  A bit-field cannot appear in a map clause.
20920     //
20921     if (FD->isBitField()) {
20922       if (!NoDiagnose) {
20923         SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
20924             << ME->getSourceRange() << getOpenMPClauseNameForDiag(CKind);
20925         return false;
20926       }
20927       if (RelevantExpr)
20928         return false;
20929       return Visit(E);
20930     }
20931 
20932     // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20933     //  If the type of a list item is a reference to a type T then the type
20934     //  will be considered to be T for all purposes of this clause.
20935     QualType CurType = BaseE->getType().getNonReferenceType();
20936 
20937     // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
20938     //  A list item cannot be a variable that is a member of a structure with
20939     //  a union type.
20940     //
20941     if (CurType->isUnionType()) {
20942       if (!NoDiagnose) {
20943         SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
20944             << ME->getSourceRange();
20945         return false;
20946       }
20947       return RelevantExpr || Visit(E);
20948     }
20949 
20950     // If we got a member expression, we should not expect any array section
20951     // before that:
20952     //
20953     // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
20954     //  If a list item is an element of a structure, only the rightmost symbol
20955     //  of the variable reference can be an array section.
20956     //
20957     AllowUnitySizeArraySection = false;
20958     AllowWholeSizeArraySection = false;
20959 
20960     // Record the component.
20961     Components.emplace_back(ME, FD, IsNonContiguous);
20962     return RelevantExpr || Visit(E);
20963   }
20964 
VisitArraySubscriptExpr(ArraySubscriptExpr * AE)20965   bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
20966     Expr *E = AE->getBase()->IgnoreParenImpCasts();
20967 
20968     if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
20969       if (!NoDiagnose) {
20970         SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20971             << 0 << AE->getSourceRange();
20972         return false;
20973       }
20974       return RelevantExpr || Visit(E);
20975     }
20976 
20977     // If we got an array subscript that express the whole dimension we
20978     // can have any array expressions before. If it only expressing part of
20979     // the dimension, we can only have unitary-size array expressions.
20980     if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef, AE, E->getType()))
20981       AllowWholeSizeArraySection = false;
20982 
20983     if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
20984       Expr::EvalResult Result;
20985       if (!AE->getIdx()->isValueDependent() &&
20986           AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
20987           !Result.Val.getInt().isZero()) {
20988         SemaRef.Diag(AE->getIdx()->getExprLoc(),
20989                      diag::err_omp_invalid_map_this_expr);
20990         SemaRef.Diag(AE->getIdx()->getExprLoc(),
20991                      diag::note_omp_invalid_subscript_on_this_ptr_map);
20992       }
20993       assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20994       RelevantExpr = TE;
20995     }
20996 
20997     // Record the component - we don't have any declaration associated.
20998     Components.emplace_back(AE, nullptr, IsNonContiguous);
20999 
21000     return RelevantExpr || Visit(E);
21001   }
21002 
VisitArraySectionExpr(ArraySectionExpr * OASE)21003   bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
21004     // After OMP 5.0  Array section in reduction clause will be implicitly
21005     // mapped
21006     assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
21007            "Array sections cannot be implicitly mapped.");
21008     Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21009     QualType CurType =
21010         ArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
21011 
21012     // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21013     //  If the type of a list item is a reference to a type T then the type
21014     //  will be considered to be T for all purposes of this clause.
21015     if (CurType->isReferenceType())
21016       CurType = CurType->getPointeeType();
21017 
21018     bool IsPointer = CurType->isAnyPointerType();
21019 
21020     if (!IsPointer && !CurType->isArrayType()) {
21021       SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21022           << 0 << OASE->getSourceRange();
21023       return false;
21024     }
21025 
21026     bool NotWhole =
21027         checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
21028     bool NotUnity =
21029         checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
21030 
21031     if (AllowWholeSizeArraySection) {
21032       // Any array section is currently allowed. Allowing a whole size array
21033       // section implies allowing a unity array section as well.
21034       //
21035       // If this array section refers to the whole dimension we can still
21036       // accept other array sections before this one, except if the base is a
21037       // pointer. Otherwise, only unitary sections are accepted.
21038       if (NotWhole || IsPointer)
21039         AllowWholeSizeArraySection = false;
21040     } else if (DKind == OMPD_target_update &&
21041                SemaRef.getLangOpts().OpenMP >= 50) {
21042       if (IsPointer && !AllowAnotherPtr)
21043         SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
21044             << /*array of unknown bound */ 1;
21045       else
21046         IsNonContiguous = true;
21047     } else if (AllowUnitySizeArraySection && NotUnity) {
21048       // A unity or whole array section is not allowed and that is not
21049       // compatible with the properties of the current array section.
21050       if (NoDiagnose)
21051         return false;
21052       SemaRef.Diag(ELoc,
21053                    diag::err_array_section_does_not_specify_contiguous_storage)
21054           << OASE->getSourceRange();
21055       return false;
21056     }
21057 
21058     if (IsPointer)
21059       AllowAnotherPtr = false;
21060 
21061     if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
21062       Expr::EvalResult ResultR;
21063       Expr::EvalResult ResultL;
21064       if (!OASE->getLength()->isValueDependent() &&
21065           OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
21066           !ResultR.Val.getInt().isOne()) {
21067         SemaRef.Diag(OASE->getLength()->getExprLoc(),
21068                      diag::err_omp_invalid_map_this_expr);
21069         SemaRef.Diag(OASE->getLength()->getExprLoc(),
21070                      diag::note_omp_invalid_length_on_this_ptr_mapping);
21071       }
21072       if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
21073           OASE->getLowerBound()->EvaluateAsInt(ResultL,
21074                                                SemaRef.getASTContext()) &&
21075           !ResultL.Val.getInt().isZero()) {
21076         SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21077                      diag::err_omp_invalid_map_this_expr);
21078         SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21079                      diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
21080       }
21081       assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21082       RelevantExpr = TE;
21083     }
21084 
21085     // Record the component - we don't have any declaration associated.
21086     Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
21087     return RelevantExpr || Visit(E);
21088   }
VisitOMPArrayShapingExpr(OMPArrayShapingExpr * E)21089   bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
21090     Expr *Base = E->getBase();
21091 
21092     // Record the component - we don't have any declaration associated.
21093     Components.emplace_back(E, nullptr, IsNonContiguous);
21094 
21095     return Visit(Base->IgnoreParenImpCasts());
21096   }
21097 
VisitUnaryOperator(UnaryOperator * UO)21098   bool VisitUnaryOperator(UnaryOperator *UO) {
21099     if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
21100         UO->getOpcode() != UO_Deref) {
21101       emitErrorMsg();
21102       return false;
21103     }
21104     if (!RelevantExpr) {
21105       // Record the component if haven't found base decl.
21106       Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
21107     }
21108     return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
21109   }
VisitBinaryOperator(BinaryOperator * BO)21110   bool VisitBinaryOperator(BinaryOperator *BO) {
21111     if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
21112       emitErrorMsg();
21113       return false;
21114     }
21115 
21116     // Pointer arithmetic is the only thing we expect to happen here so after we
21117     // make sure the binary operator is a pointer type, the only thing we need
21118     // to do is to visit the subtree that has the same type as root (so that we
21119     // know the other subtree is just an offset)
21120     Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
21121     Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
21122     Components.emplace_back(BO, nullptr, false);
21123     assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
21124             RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
21125            "Either LHS or RHS have base decl inside");
21126     if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
21127       return RelevantExpr || Visit(LE);
21128     return RelevantExpr || Visit(RE);
21129   }
VisitCXXThisExpr(CXXThisExpr * CTE)21130   bool VisitCXXThisExpr(CXXThisExpr *CTE) {
21131     assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21132     RelevantExpr = CTE;
21133     Components.emplace_back(CTE, nullptr, IsNonContiguous);
21134     return true;
21135   }
VisitCXXOperatorCallExpr(CXXOperatorCallExpr * COCE)21136   bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
21137     assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21138     Components.emplace_back(COCE, nullptr, IsNonContiguous);
21139     return true;
21140   }
VisitOpaqueValueExpr(OpaqueValueExpr * E)21141   bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
21142     Expr *Source = E->getSourceExpr();
21143     if (!Source) {
21144       emitErrorMsg();
21145       return false;
21146     }
21147     return Visit(Source);
21148   }
VisitStmt(Stmt *)21149   bool VisitStmt(Stmt *) {
21150     emitErrorMsg();
21151     return false;
21152   }
getFoundBase() const21153   const Expr *getFoundBase() const { return RelevantExpr; }
MapBaseChecker(Sema & SemaRef,OpenMPClauseKind CKind,OpenMPDirectiveKind DKind,OMPClauseMappableExprCommon::MappableExprComponentList & Components,bool NoDiagnose,SourceLocation & ELoc,SourceRange & ERange)21154   explicit MapBaseChecker(
21155       Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
21156       OMPClauseMappableExprCommon::MappableExprComponentList &Components,
21157       bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
21158       : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
21159         NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
21160 };
21161 } // namespace
21162 
21163 /// Return the expression of the base of the mappable expression or null if it
21164 /// cannot be determined and do all the necessary checks to see if the
21165 /// expression is valid as a standalone mappable expression. In the process,
21166 /// record all the components of the expression.
checkMapClauseExpressionBase(Sema & SemaRef,Expr * E,OMPClauseMappableExprCommon::MappableExprComponentList & CurComponents,OpenMPClauseKind CKind,OpenMPDirectiveKind DKind,bool NoDiagnose)21167 static const Expr *checkMapClauseExpressionBase(
21168     Sema &SemaRef, Expr *E,
21169     OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
21170     OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
21171   SourceLocation ELoc = E->getExprLoc();
21172   SourceRange ERange = E->getSourceRange();
21173   MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
21174                          ERange);
21175   if (Checker.Visit(E->IgnoreParens())) {
21176     // Check if the highest dimension array section has length specified
21177     if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
21178         (CKind == OMPC_to || CKind == OMPC_from)) {
21179       auto CI = CurComponents.rbegin();
21180       auto CE = CurComponents.rend();
21181       for (; CI != CE; ++CI) {
21182         const auto *OASE =
21183             dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
21184         if (!OASE)
21185           continue;
21186         if (OASE && OASE->getLength())
21187           break;
21188         SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
21189             << ERange;
21190       }
21191     }
21192     return Checker.getFoundBase();
21193   }
21194   return nullptr;
21195 }
21196 
21197 // Return true if expression E associated with value VD has conflicts with other
21198 // map information.
checkMapConflicts(Sema & SemaRef,DSAStackTy * DSAS,const ValueDecl * VD,const Expr * E,bool CurrentRegionOnly,OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents,OpenMPClauseKind CKind)21199 static bool checkMapConflicts(
21200     Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
21201     bool CurrentRegionOnly,
21202     OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents,
21203     OpenMPClauseKind CKind) {
21204   assert(VD && E);
21205   SourceLocation ELoc = E->getExprLoc();
21206   SourceRange ERange = E->getSourceRange();
21207 
21208   // In order to easily check the conflicts we need to match each component of
21209   // the expression under test with the components of the expressions that are
21210   // already in the stack.
21211 
21212   assert(!CurComponents.empty() && "Map clause expression with no components!");
21213   assert(CurComponents.back().getAssociatedDeclaration() == VD &&
21214          "Map clause expression with unexpected base!");
21215 
21216   // Variables to help detecting enclosing problems in data environment nests.
21217   bool IsEnclosedByDataEnvironmentExpr = false;
21218   const Expr *EnclosingExpr = nullptr;
21219 
21220   bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
21221       VD, CurrentRegionOnly,
21222       [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
21223        ERange, CKind, &EnclosingExpr,
21224        CurComponents](OMPClauseMappableExprCommon::MappableExprComponentListRef
21225                           StackComponents,
21226                       OpenMPClauseKind Kind) {
21227         if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
21228           return false;
21229         assert(!StackComponents.empty() &&
21230                "Map clause expression with no components!");
21231         assert(StackComponents.back().getAssociatedDeclaration() == VD &&
21232                "Map clause expression with unexpected base!");
21233         (void)VD;
21234 
21235         // The whole expression in the stack.
21236         const Expr *RE = StackComponents.front().getAssociatedExpression();
21237 
21238         // Expressions must start from the same base. Here we detect at which
21239         // point both expressions diverge from each other and see if we can
21240         // detect if the memory referred to both expressions is contiguous and
21241         // do not overlap.
21242         auto CI = CurComponents.rbegin();
21243         auto CE = CurComponents.rend();
21244         auto SI = StackComponents.rbegin();
21245         auto SE = StackComponents.rend();
21246         for (; CI != CE && SI != SE; ++CI, ++SI) {
21247 
21248           // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
21249           //  At most one list item can be an array item derived from a given
21250           //  variable in map clauses of the same construct.
21251           if (CurrentRegionOnly &&
21252               (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
21253                isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
21254                isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
21255               (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
21256                isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
21257                isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
21258             SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
21259                          diag::err_omp_multiple_array_items_in_map_clause)
21260                 << CI->getAssociatedExpression()->getSourceRange();
21261             SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
21262                          diag::note_used_here)
21263                 << SI->getAssociatedExpression()->getSourceRange();
21264             return true;
21265           }
21266 
21267           // Do both expressions have the same kind?
21268           if (CI->getAssociatedExpression()->getStmtClass() !=
21269               SI->getAssociatedExpression()->getStmtClass())
21270             break;
21271 
21272           // Are we dealing with different variables/fields?
21273           if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
21274             break;
21275         }
21276         // Check if the extra components of the expressions in the enclosing
21277         // data environment are redundant for the current base declaration.
21278         // If they are, the maps completely overlap, which is legal.
21279         for (; SI != SE; ++SI) {
21280           QualType Type;
21281           if (const auto *ASE =
21282                   dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
21283             Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
21284           } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
21285                          SI->getAssociatedExpression())) {
21286             const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21287             Type = ArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
21288           } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
21289                          SI->getAssociatedExpression())) {
21290             Type = OASE->getBase()->getType()->getPointeeType();
21291           }
21292           if (Type.isNull() || Type->isAnyPointerType() ||
21293               checkArrayExpressionDoesNotReferToWholeSize(
21294                   SemaRef, SI->getAssociatedExpression(), Type))
21295             break;
21296         }
21297 
21298         // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21299         //  List items of map clauses in the same construct must not share
21300         //  original storage.
21301         //
21302         // If the expressions are exactly the same or one is a subset of the
21303         // other, it means they are sharing storage.
21304         if (CI == CE && SI == SE) {
21305           if (CurrentRegionOnly) {
21306             if (CKind == OMPC_map) {
21307               SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21308             } else {
21309               assert(CKind == OMPC_to || CKind == OMPC_from);
21310               SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21311                   << ERange;
21312             }
21313             SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21314                 << RE->getSourceRange();
21315             return true;
21316           }
21317           // If we find the same expression in the enclosing data environment,
21318           // that is legal.
21319           IsEnclosedByDataEnvironmentExpr = true;
21320           return false;
21321         }
21322 
21323         QualType DerivedType =
21324             std::prev(CI)->getAssociatedDeclaration()->getType();
21325         SourceLocation DerivedLoc =
21326             std::prev(CI)->getAssociatedExpression()->getExprLoc();
21327 
21328         // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21329         //  If the type of a list item is a reference to a type T then the type
21330         //  will be considered to be T for all purposes of this clause.
21331         DerivedType = DerivedType.getNonReferenceType();
21332 
21333         // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
21334         //  A variable for which the type is pointer and an array section
21335         //  derived from that variable must not appear as list items of map
21336         //  clauses of the same construct.
21337         //
21338         // Also, cover one of the cases in:
21339         // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21340         //  If any part of the original storage of a list item has corresponding
21341         //  storage in the device data environment, all of the original storage
21342         //  must have corresponding storage in the device data environment.
21343         //
21344         if (DerivedType->isAnyPointerType()) {
21345           if (CI == CE || SI == SE) {
21346             SemaRef.Diag(
21347                 DerivedLoc,
21348                 diag::err_omp_pointer_mapped_along_with_derived_section)
21349                 << DerivedLoc;
21350             SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21351                 << RE->getSourceRange();
21352             return true;
21353           }
21354           if (CI->getAssociatedExpression()->getStmtClass() !=
21355                   SI->getAssociatedExpression()->getStmtClass() ||
21356               CI->getAssociatedDeclaration()->getCanonicalDecl() ==
21357                   SI->getAssociatedDeclaration()->getCanonicalDecl()) {
21358             assert(CI != CE && SI != SE);
21359             SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
21360                 << DerivedLoc;
21361             SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21362                 << RE->getSourceRange();
21363             return true;
21364           }
21365         }
21366 
21367         // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21368         //  List items of map clauses in the same construct must not share
21369         //  original storage.
21370         //
21371         // An expression is a subset of the other.
21372         if (CurrentRegionOnly && (CI == CE || SI == SE)) {
21373           if (CKind == OMPC_map) {
21374             if (CI != CE || SI != SE) {
21375               // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
21376               // a pointer.
21377               auto Begin =
21378                   CI != CE ? CurComponents.begin() : StackComponents.begin();
21379               auto End = CI != CE ? CurComponents.end() : StackComponents.end();
21380               auto It = Begin;
21381               while (It != End && !It->getAssociatedDeclaration())
21382                 std::advance(It, 1);
21383               assert(It != End &&
21384                      "Expected at least one component with the declaration.");
21385               if (It != Begin && It->getAssociatedDeclaration()
21386                                      ->getType()
21387                                      .getCanonicalType()
21388                                      ->isAnyPointerType()) {
21389                 IsEnclosedByDataEnvironmentExpr = false;
21390                 EnclosingExpr = nullptr;
21391                 return false;
21392               }
21393             }
21394             SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21395           } else {
21396             assert(CKind == OMPC_to || CKind == OMPC_from);
21397             SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21398                 << ERange;
21399           }
21400           SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21401               << RE->getSourceRange();
21402           return true;
21403         }
21404 
21405         // The current expression uses the same base as other expression in the
21406         // data environment but does not contain it completely.
21407         if (!CurrentRegionOnly && SI != SE)
21408           EnclosingExpr = RE;
21409 
21410         // The current expression is a subset of the expression in the data
21411         // environment.
21412         IsEnclosedByDataEnvironmentExpr |=
21413             (!CurrentRegionOnly && CI != CE && SI == SE);
21414 
21415         return false;
21416       });
21417 
21418   if (CurrentRegionOnly)
21419     return FoundError;
21420 
21421   // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21422   //  If any part of the original storage of a list item has corresponding
21423   //  storage in the device data environment, all of the original storage must
21424   //  have corresponding storage in the device data environment.
21425   // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
21426   //  If a list item is an element of a structure, and a different element of
21427   //  the structure has a corresponding list item in the device data environment
21428   //  prior to a task encountering the construct associated with the map clause,
21429   //  then the list item must also have a corresponding list item in the device
21430   //  data environment prior to the task encountering the construct.
21431   //
21432   if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
21433     SemaRef.Diag(ELoc,
21434                  diag::err_omp_original_storage_is_shared_and_does_not_contain)
21435         << ERange;
21436     SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
21437         << EnclosingExpr->getSourceRange();
21438     return true;
21439   }
21440 
21441   return FoundError;
21442 }
21443 
21444 // Look up the user-defined mapper given the mapper name and mapped type, and
21445 // build a reference to it.
buildUserDefinedMapperRef(Sema & SemaRef,Scope * S,CXXScopeSpec & MapperIdScopeSpec,const DeclarationNameInfo & MapperId,QualType Type,Expr * UnresolvedMapper)21446 static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
21447                                             CXXScopeSpec &MapperIdScopeSpec,
21448                                             const DeclarationNameInfo &MapperId,
21449                                             QualType Type,
21450                                             Expr *UnresolvedMapper) {
21451   if (MapperIdScopeSpec.isInvalid())
21452     return ExprError();
21453   // Get the actual type for the array type.
21454   if (Type->isArrayType()) {
21455     assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
21456     Type = Type->getAsArrayTypeUnsafe()->getElementType().getCanonicalType();
21457   }
21458   // Find all user-defined mappers with the given MapperId.
21459   SmallVector<UnresolvedSet<8>, 4> Lookups;
21460   LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
21461   Lookup.suppressDiagnostics();
21462   if (S) {
21463     while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
21464                                          /*ObjectType=*/QualType())) {
21465       NamedDecl *D = Lookup.getRepresentativeDecl();
21466       while (S && !S->isDeclScope(D))
21467         S = S->getParent();
21468       if (S)
21469         S = S->getParent();
21470       Lookups.emplace_back();
21471       Lookups.back().append(Lookup.begin(), Lookup.end());
21472       Lookup.clear();
21473     }
21474   } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
21475     // Extract the user-defined mappers with the given MapperId.
21476     Lookups.push_back(UnresolvedSet<8>());
21477     for (NamedDecl *D : ULE->decls()) {
21478       auto *DMD = cast<OMPDeclareMapperDecl>(D);
21479       assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
21480       Lookups.back().addDecl(DMD);
21481     }
21482   }
21483   // Defer the lookup for dependent types. The results will be passed through
21484   // UnresolvedMapper on instantiation.
21485   if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21486       Type->isInstantiationDependentType() ||
21487       Type->containsUnexpandedParameterPack() ||
21488       filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
21489         return !D->isInvalidDecl() &&
21490                (D->getType()->isDependentType() ||
21491                 D->getType()->isInstantiationDependentType() ||
21492                 D->getType()->containsUnexpandedParameterPack());
21493       })) {
21494     UnresolvedSet<8> URS;
21495     for (const UnresolvedSet<8> &Set : Lookups) {
21496       if (Set.empty())
21497         continue;
21498       URS.append(Set.begin(), Set.end());
21499     }
21500     return UnresolvedLookupExpr::Create(
21501         SemaRef.Context, /*NamingClass=*/nullptr,
21502         MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
21503         /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false,
21504         /*KnownInstantiationDependent=*/false);
21505   }
21506   SourceLocation Loc = MapperId.getLoc();
21507   // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21508   //  The type must be of struct, union or class type in C and C++
21509   if (!Type->isStructureOrClassType() && !Type->isUnionType() &&
21510       (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
21511     SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
21512     return ExprError();
21513   }
21514   // Perform argument dependent lookup.
21515   if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21516     argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
21517   // Return the first user-defined mapper with the desired type.
21518   if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21519           Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21520             if (!D->isInvalidDecl() &&
21521                 SemaRef.Context.hasSameType(D->getType(), Type))
21522               return D;
21523             return nullptr;
21524           }))
21525     return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21526   // Find the first user-defined mapper with a type derived from the desired
21527   // type.
21528   if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21529           Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21530             if (!D->isInvalidDecl() &&
21531                 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
21532                 !Type.isMoreQualifiedThan(D->getType(),
21533                                           SemaRef.getASTContext()))
21534               return D;
21535             return nullptr;
21536           })) {
21537     CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21538                        /*DetectVirtual=*/false);
21539     if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
21540       if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
21541               VD->getType().getUnqualifiedType()))) {
21542         if (SemaRef.CheckBaseClassAccess(
21543                 Loc, VD->getType(), Type, Paths.front(),
21544                 /*DiagID=*/0) != Sema::AR_inaccessible) {
21545           return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21546         }
21547       }
21548     }
21549   }
21550   // Report error if a mapper is specified, but cannot be found.
21551   if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
21552     SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
21553         << Type << MapperId.getName();
21554     return ExprError();
21555   }
21556   return ExprEmpty();
21557 }
21558 
21559 namespace {
21560 // Utility struct that gathers all the related lists associated with a mappable
21561 // expression.
21562 struct MappableVarListInfo {
21563   // The list of expressions.
21564   ArrayRef<Expr *> VarList;
21565   // The list of processed expressions.
21566   SmallVector<Expr *, 16> ProcessedVarList;
21567   // The mappble components for each expression.
21568   OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents;
21569   // The base declaration of the variable.
21570   SmallVector<ValueDecl *, 16> VarBaseDeclarations;
21571   // The reference to the user-defined mapper associated with every expression.
21572   SmallVector<Expr *, 16> UDMapperList;
21573 
MappableVarListInfo__anon1dd12e447b11::MappableVarListInfo21574   MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
21575     // We have a list of components and base declarations for each entry in the
21576     // variable list.
21577     VarComponents.reserve(VarList.size());
21578     VarBaseDeclarations.reserve(VarList.size());
21579   }
21580 };
21581 } // namespace
21582 
buildImplicitMap(Sema & S,QualType BaseType,DSAStackTy * Stack,SmallVectorImpl<OMPClause * > & Maps)21583 static DeclRefExpr *buildImplicitMap(Sema &S, QualType BaseType,
21584                                      DSAStackTy *Stack,
21585                                      SmallVectorImpl<OMPClause *> &Maps) {
21586 
21587   const RecordDecl *RD = BaseType->getAsRecordDecl();
21588   SourceRange Range = RD->getSourceRange();
21589   DeclarationNameInfo ImplicitName;
21590   // Dummy variable _s for Mapper.
21591   VarDecl *VD = buildVarDecl(S, Range.getEnd(), BaseType, "_s");
21592   DeclRefExpr *MapperVarRef =
21593       buildDeclRefExpr(S, VD, BaseType, SourceLocation());
21594 
21595   // Create implicit map clause for mapper.
21596   SmallVector<Expr *, 4> SExprs;
21597   for (auto *FD : RD->fields()) {
21598     Expr *BE = S.BuildMemberExpr(
21599         MapperVarRef, /*IsArrow=*/false, Range.getBegin(),
21600         NestedNameSpecifierLoc(), Range.getBegin(), FD,
21601         DeclAccessPair::make(FD, FD->getAccess()),
21602         /*HadMultipleCandidates=*/false,
21603         DeclarationNameInfo(FD->getDeclName(), FD->getSourceRange().getBegin()),
21604         FD->getType(), VK_LValue, OK_Ordinary);
21605     SExprs.push_back(BE);
21606   }
21607   CXXScopeSpec MapperIdScopeSpec;
21608   DeclarationNameInfo MapperId;
21609   OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
21610 
21611   OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
21612       nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec,
21613       MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
21614       /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), SExprs,
21615       OMPVarListLocTy());
21616   Maps.push_back(MapClause);
21617   return MapperVarRef;
21618 }
21619 
buildImplicitMapper(Sema & S,QualType BaseType,DSAStackTy * Stack)21620 static ExprResult buildImplicitMapper(Sema &S, QualType BaseType,
21621                                       DSAStackTy *Stack) {
21622 
21623   // Build impilicit map for mapper
21624   SmallVector<OMPClause *, 4> Maps;
21625   DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
21626 
21627   const RecordDecl *RD = BaseType->getAsRecordDecl();
21628   // AST context is RD's ParentASTContext().
21629   ASTContext &Ctx = RD->getParentASTContext();
21630   // DeclContext is RD's DeclContext.
21631   DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
21632 
21633   // Create implicit default mapper for "RD".
21634   DeclarationName MapperId;
21635   auto &DeclNames = Ctx.DeclarationNames;
21636   MapperId = DeclNames.getIdentifier(&Ctx.Idents.get("default"));
21637   auto *DMD = OMPDeclareMapperDecl::Create(Ctx, DCT, SourceLocation(), MapperId,
21638                                            BaseType, MapperId, Maps, nullptr);
21639   Scope *Scope = S.getScopeForContext(DCT);
21640   if (Scope)
21641     S.PushOnScopeChains(DMD, Scope, /*AddToContext=*/false);
21642   DCT->addDecl(DMD);
21643   DMD->setAccess(clang::AS_none);
21644   auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
21645   VD->setDeclContext(DMD);
21646   VD->setLexicalDeclContext(DMD);
21647   DMD->addDecl(VD);
21648   DMD->setMapperVarRef(MapperVarRef);
21649   FieldDecl *FD = *RD->field_begin();
21650   // create mapper refence.
21651   return DeclRefExpr::Create(Ctx, NestedNameSpecifierLoc{}, FD->getLocation(),
21652                              DMD, false, SourceLocation(), BaseType, VK_LValue);
21653 }
21654 
21655 // Look up the user-defined mapper given the mapper name and mapper type,
21656 // return true if found one.
hasUserDefinedMapper(Sema & SemaRef,Scope * S,CXXScopeSpec & MapperIdScopeSpec,const DeclarationNameInfo & MapperId,QualType Type)21657 static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
21658                                  CXXScopeSpec &MapperIdScopeSpec,
21659                                  const DeclarationNameInfo &MapperId,
21660                                  QualType Type) {
21661   // Find all user-defined mappers with the given MapperId.
21662   SmallVector<UnresolvedSet<8>, 4> Lookups;
21663   LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
21664   Lookup.suppressDiagnostics();
21665   while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
21666                                        /*ObjectType=*/QualType())) {
21667     NamedDecl *D = Lookup.getRepresentativeDecl();
21668     while (S && !S->isDeclScope(D))
21669       S = S->getParent();
21670     if (S)
21671       S = S->getParent();
21672     Lookups.emplace_back();
21673     Lookups.back().append(Lookup.begin(), Lookup.end());
21674     Lookup.clear();
21675   }
21676   if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21677       Type->isInstantiationDependentType() ||
21678       Type->containsUnexpandedParameterPack() ||
21679       filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
21680         return !D->isInvalidDecl() &&
21681                (D->getType()->isDependentType() ||
21682                 D->getType()->isInstantiationDependentType() ||
21683                 D->getType()->containsUnexpandedParameterPack());
21684       }))
21685     return false;
21686   // Perform argument dependent lookup.
21687   SourceLocation Loc = MapperId.getLoc();
21688   if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21689     argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
21690   if (filterLookupForUDReductionAndMapper<ValueDecl *>(
21691           Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21692             if (!D->isInvalidDecl() &&
21693                 SemaRef.Context.hasSameType(D->getType(), Type))
21694               return D;
21695             return nullptr;
21696           }))
21697     return true;
21698   // Find the first user-defined mapper with a type derived from the desired
21699   // type.
21700   auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21701       Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21702         if (!D->isInvalidDecl() &&
21703             SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
21704             !Type.isMoreQualifiedThan(D->getType(), SemaRef.getASTContext()))
21705           return D;
21706         return nullptr;
21707       });
21708   if (!VD)
21709     return false;
21710   CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21711                      /*DetectVirtual=*/false);
21712   if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
21713     bool IsAmbiguous = !Paths.isAmbiguous(
21714         SemaRef.Context.getCanonicalType(VD->getType().getUnqualifiedType()));
21715     if (IsAmbiguous)
21716       return false;
21717     if (SemaRef.CheckBaseClassAccess(Loc, VD->getType(), Type, Paths.front(),
21718                                      /*DiagID=*/0) != Sema::AR_inaccessible)
21719       return true;
21720   }
21721   return false;
21722 }
21723 
isImplicitMapperNeeded(Sema & S,DSAStackTy * Stack,QualType CanonType,const Expr * E)21724 static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
21725                                    QualType CanonType, const Expr *E) {
21726 
21727   // DFS over data members in structures/classes.
21728   SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(1,
21729                                                          {CanonType, nullptr});
21730   llvm::DenseMap<const Type *, bool> Visited;
21731   SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
21732   while (!Types.empty()) {
21733     auto [BaseType, CurFD] = Types.pop_back_val();
21734     while (ParentChain.back().second == 0)
21735       ParentChain.pop_back();
21736     --ParentChain.back().second;
21737     if (BaseType.isNull())
21738       continue;
21739     // Only structs/classes are allowed to have mappers.
21740     const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
21741     if (!RD)
21742       continue;
21743     auto It = Visited.find(BaseType.getTypePtr());
21744     if (It == Visited.end()) {
21745       // Try to find the associated user-defined mapper.
21746       CXXScopeSpec MapperIdScopeSpec;
21747       DeclarationNameInfo DefaultMapperId;
21748       DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
21749           &S.Context.Idents.get("default")));
21750       DefaultMapperId.setLoc(E->getExprLoc());
21751       bool HasUDMapper =
21752           hasUserDefinedMapper(S, Stack->getCurScope(), MapperIdScopeSpec,
21753                                DefaultMapperId, BaseType);
21754       It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
21755     }
21756     // Found default mapper.
21757     if (It->second)
21758       return true;
21759     // Check for the "default" mapper for data members.
21760     bool FirstIter = true;
21761     for (FieldDecl *FD : RD->fields()) {
21762       if (!FD)
21763         continue;
21764       QualType FieldTy = FD->getType();
21765       if (FieldTy.isNull() ||
21766           !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
21767         continue;
21768       if (FirstIter) {
21769         FirstIter = false;
21770         ParentChain.emplace_back(CurFD, 1);
21771       } else {
21772         ++ParentChain.back().second;
21773       }
21774       Types.emplace_back(FieldTy, FD);
21775     }
21776   }
21777   return false;
21778 }
21779 
21780 // Check the validity of the provided variable list for the provided clause kind
21781 // \a CKind. In the check process the valid expressions, mappable expression
21782 // components, variables, and user-defined mappers are extracted and used to
21783 // fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
21784 // UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
21785 // and \a MapperId are expected to be valid if the clause kind is 'map'.
checkMappableExpressionList(Sema & SemaRef,DSAStackTy * DSAS,OpenMPClauseKind CKind,MappableVarListInfo & MVLI,SourceLocation StartLoc,CXXScopeSpec & MapperIdScopeSpec,DeclarationNameInfo MapperId,ArrayRef<Expr * > UnresolvedMappers,OpenMPMapClauseKind MapType=OMPC_MAP_unknown,ArrayRef<OpenMPMapModifierKind> Modifiers={},bool IsMapTypeImplicit=false,bool NoDiagnose=false)21786 static void checkMappableExpressionList(
21787     Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
21788     MappableVarListInfo &MVLI, SourceLocation StartLoc,
21789     CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
21790     ArrayRef<Expr *> UnresolvedMappers,
21791     OpenMPMapClauseKind MapType = OMPC_MAP_unknown,
21792     ArrayRef<OpenMPMapModifierKind> Modifiers = {},
21793     bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
21794   // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
21795   assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
21796          "Unexpected clause kind with mappable expressions!");
21797   unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
21798 
21799   // If the identifier of user-defined mapper is not specified, it is "default".
21800   // We do not change the actual name in this clause to distinguish whether a
21801   // mapper is specified explicitly, i.e., it is not explicitly specified when
21802   // MapperId.getName() is empty.
21803   if (!MapperId.getName() || MapperId.getName().isEmpty()) {
21804     auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
21805     MapperId.setName(DeclNames.getIdentifier(
21806         &SemaRef.getASTContext().Idents.get("default")));
21807     MapperId.setLoc(StartLoc);
21808   }
21809 
21810   // Iterators to find the current unresolved mapper expression.
21811   auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
21812   bool UpdateUMIt = false;
21813   Expr *UnresolvedMapper = nullptr;
21814 
21815   bool HasHoldModifier =
21816       llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
21817 
21818   // Keep track of the mappable components and base declarations in this clause.
21819   // Each entry in the list is going to have a list of components associated. We
21820   // record each set of the components so that we can build the clause later on.
21821   // In the end we should have the same amount of declarations and component
21822   // lists.
21823 
21824   for (Expr *RE : MVLI.VarList) {
21825     assert(RE && "Null expr in omp to/from/map clause");
21826     SourceLocation ELoc = RE->getExprLoc();
21827 
21828     // Find the current unresolved mapper expression.
21829     if (UpdateUMIt && UMIt != UMEnd) {
21830       UMIt++;
21831       assert(
21832           UMIt != UMEnd &&
21833           "Expect the size of UnresolvedMappers to match with that of VarList");
21834     }
21835     UpdateUMIt = true;
21836     if (UMIt != UMEnd)
21837       UnresolvedMapper = *UMIt;
21838 
21839     const Expr *VE = RE->IgnoreParenLValueCasts();
21840 
21841     if (VE->isValueDependent() || VE->isTypeDependent() ||
21842         VE->isInstantiationDependent() ||
21843         VE->containsUnexpandedParameterPack()) {
21844       // Try to find the associated user-defined mapper.
21845       ExprResult ER = buildUserDefinedMapperRef(
21846           SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21847           VE->getType().getCanonicalType(), UnresolvedMapper);
21848       if (ER.isInvalid())
21849         continue;
21850       MVLI.UDMapperList.push_back(ER.get());
21851       // We can only analyze this information once the missing information is
21852       // resolved.
21853       MVLI.ProcessedVarList.push_back(RE);
21854       continue;
21855     }
21856 
21857     Expr *SimpleExpr = RE->IgnoreParenCasts();
21858 
21859     if (!RE->isLValue()) {
21860       if (SemaRef.getLangOpts().OpenMP < 50) {
21861         SemaRef.Diag(
21862             ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
21863             << RE->getSourceRange();
21864       } else {
21865         SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21866             << getOpenMPClauseNameForDiag(CKind) << RE->getSourceRange();
21867       }
21868       continue;
21869     }
21870 
21871     OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
21872     ValueDecl *CurDeclaration = nullptr;
21873 
21874     // Obtain the array or member expression bases if required. Also, fill the
21875     // components array with all the components identified in the process.
21876     const Expr *BE =
21877         checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
21878                                      DSAS->getCurrentDirective(), NoDiagnose);
21879     if (!BE)
21880       continue;
21881 
21882     assert(!CurComponents.empty() &&
21883            "Invalid mappable expression information.");
21884 
21885     if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
21886       // Add store "this" pointer to class in DSAStackTy for future checking
21887       DSAS->addMappedClassesQualTypes(TE->getType());
21888       // Try to find the associated user-defined mapper.
21889       ExprResult ER = buildUserDefinedMapperRef(
21890           SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21891           VE->getType().getCanonicalType(), UnresolvedMapper);
21892       if (ER.isInvalid())
21893         continue;
21894       MVLI.UDMapperList.push_back(ER.get());
21895       // Skip restriction checking for variable or field declarations
21896       MVLI.ProcessedVarList.push_back(RE);
21897       MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21898       MVLI.VarComponents.back().append(CurComponents.begin(),
21899                                        CurComponents.end());
21900       MVLI.VarBaseDeclarations.push_back(nullptr);
21901       continue;
21902     }
21903 
21904     // For the following checks, we rely on the base declaration which is
21905     // expected to be associated with the last component. The declaration is
21906     // expected to be a variable or a field (if 'this' is being mapped).
21907     CurDeclaration = CurComponents.back().getAssociatedDeclaration();
21908     assert(CurDeclaration && "Null decl on map clause.");
21909     assert(
21910         CurDeclaration->isCanonicalDecl() &&
21911         "Expecting components to have associated only canonical declarations.");
21912 
21913     auto *VD = dyn_cast<VarDecl>(CurDeclaration);
21914     const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
21915 
21916     assert((VD || FD) && "Only variables or fields are expected here!");
21917     (void)FD;
21918 
21919     // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
21920     // threadprivate variables cannot appear in a map clause.
21921     // OpenMP 4.5 [2.10.5, target update Construct]
21922     // threadprivate variables cannot appear in a from clause.
21923     if (VD && DSAS->isThreadPrivate(VD)) {
21924       if (NoDiagnose)
21925         continue;
21926       DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21927       SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
21928           << getOpenMPClauseNameForDiag(CKind);
21929       reportOriginalDsa(SemaRef, DSAS, VD, DVar);
21930       continue;
21931     }
21932 
21933     // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21934     //  A list item cannot appear in both a map clause and a data-sharing
21935     //  attribute clause on the same construct.
21936 
21937     // Check conflicts with other map clause expressions. We check the conflicts
21938     // with the current construct separately from the enclosing data
21939     // environment, because the restrictions are different. We only have to
21940     // check conflicts across regions for the map clauses.
21941     if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21942                           /*CurrentRegionOnly=*/true, CurComponents, CKind))
21943       break;
21944     if (CKind == OMPC_map &&
21945         (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
21946         checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21947                           /*CurrentRegionOnly=*/false, CurComponents, CKind))
21948       break;
21949 
21950     // OpenMP 4.5 [2.10.5, target update Construct]
21951     // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21952     //  If the type of a list item is a reference to a type T then the type will
21953     //  be considered to be T for all purposes of this clause.
21954     auto I = llvm::find_if(
21955         CurComponents,
__anon1dd12e447f02(const OMPClauseMappableExprCommon::MappableComponent &MC) 21956         [](const OMPClauseMappableExprCommon::MappableComponent &MC) {
21957           return MC.getAssociatedDeclaration();
21958         });
21959     assert(I != CurComponents.end() && "Null decl on map clause.");
21960     (void)I;
21961     QualType Type;
21962     auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
21963     auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens());
21964     auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
21965     if (ASE) {
21966       Type = ASE->getType().getNonReferenceType();
21967     } else if (OASE) {
21968       QualType BaseType =
21969           ArraySectionExpr::getBaseOriginalType(OASE->getBase());
21970       if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21971         Type = ATy->getElementType();
21972       else
21973         Type = BaseType->getPointeeType();
21974       Type = Type.getNonReferenceType();
21975     } else if (OAShE) {
21976       Type = OAShE->getBase()->getType()->getPointeeType();
21977     } else {
21978       Type = VE->getType();
21979     }
21980 
21981     // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
21982     // A list item in a to or from clause must have a mappable type.
21983     // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21984     //  A list item must have a mappable type.
21985     if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
21986                            DSAS, Type, /*FullCheck=*/true))
21987       continue;
21988 
21989     if (CKind == OMPC_map) {
21990       // target enter data
21991       // OpenMP [2.10.2, Restrictions, p. 99]
21992       // A map-type must be specified in all map clauses and must be either
21993       // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
21994       // no map type is present.
21995       OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
21996       if (DKind == OMPD_target_enter_data &&
21997           !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
21998             SemaRef.getLangOpts().OpenMP >= 52)) {
21999         SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22000             << (IsMapTypeImplicit ? 1 : 0)
22001             << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22002             << getOpenMPDirectiveName(DKind, OMPVersion);
22003         continue;
22004       }
22005 
22006       // target exit_data
22007       // OpenMP [2.10.3, Restrictions, p. 102]
22008       // A map-type must be specified in all map clauses and must be either
22009       // from, release, or delete. Starting with OpenMP 5.2 the default map
22010       // type is `from` if no map type is present.
22011       if (DKind == OMPD_target_exit_data &&
22012           !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
22013             MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
22014         SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22015             << (IsMapTypeImplicit ? 1 : 0)
22016             << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22017             << getOpenMPDirectiveName(DKind, OMPVersion);
22018         continue;
22019       }
22020 
22021       // The 'ompx_hold' modifier is specifically intended to be used on a
22022       // 'target' or 'target data' directive to prevent data from being unmapped
22023       // during the associated statement.  It is not permitted on a 'target
22024       // enter data' or 'target exit data' directive, which have no associated
22025       // statement.
22026       if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
22027           HasHoldModifier) {
22028         SemaRef.Diag(StartLoc,
22029                      diag::err_omp_invalid_map_type_modifier_for_directive)
22030             << getOpenMPSimpleClauseTypeName(OMPC_map,
22031                                              OMPC_MAP_MODIFIER_ompx_hold)
22032             << getOpenMPDirectiveName(DKind, OMPVersion);
22033         continue;
22034       }
22035 
22036       // target, target data
22037       // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
22038       // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
22039       // A map-type in a map clause must be to, from, tofrom or alloc
22040       if ((DKind == OMPD_target_data ||
22041            isOpenMPTargetExecutionDirective(DKind)) &&
22042           !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
22043             MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
22044         SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22045             << (IsMapTypeImplicit ? 1 : 0)
22046             << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22047             << getOpenMPDirectiveName(DKind, OMPVersion);
22048         continue;
22049       }
22050 
22051       // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
22052       // A list item cannot appear in both a map clause and a data-sharing
22053       // attribute clause on the same construct
22054       //
22055       // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
22056       // A list item cannot appear in both a map clause and a data-sharing
22057       // attribute clause on the same construct unless the construct is a
22058       // combined construct.
22059       if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
22060                   isOpenMPTargetExecutionDirective(DKind)) ||
22061                  DKind == OMPD_target)) {
22062         DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
22063         if (isOpenMPPrivate(DVar.CKind)) {
22064           SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22065               << getOpenMPClauseNameForDiag(DVar.CKind)
22066               << getOpenMPClauseNameForDiag(OMPC_map)
22067               << getOpenMPDirectiveName(DSAS->getCurrentDirective(),
22068                                         OMPVersion);
22069           reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
22070           continue;
22071         }
22072       }
22073     }
22074 
22075     // Try to find the associated user-defined mapper.
22076     ExprResult ER = buildUserDefinedMapperRef(
22077         SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22078         Type.getCanonicalType(), UnresolvedMapper);
22079     if (ER.isInvalid())
22080       continue;
22081 
22082     // If no user-defined mapper is found, we need to create an implicit one for
22083     // arrays/array-sections on structs that have members that have
22084     // user-defined mappers. This is needed to ensure that the mapper for the
22085     // member is invoked when mapping each element of the array/array-section.
22086     if (!ER.get()) {
22087       QualType BaseType;
22088 
22089       if (isa<ArraySectionExpr>(VE)) {
22090         BaseType = VE->getType().getCanonicalType();
22091         if (BaseType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
22092           const auto *OASE = cast<ArraySectionExpr>(VE->IgnoreParenImpCasts());
22093           QualType BType =
22094               ArraySectionExpr::getBaseOriginalType(OASE->getBase());
22095           QualType ElemType;
22096           if (const auto *ATy = BType->getAsArrayTypeUnsafe())
22097             ElemType = ATy->getElementType();
22098           else
22099             ElemType = BType->getPointeeType();
22100           BaseType = ElemType.getCanonicalType();
22101         }
22102       } else if (VE->getType()->isArrayType()) {
22103         const ArrayType *AT = VE->getType()->getAsArrayTypeUnsafe();
22104         const QualType ElemType = AT->getElementType();
22105         BaseType = ElemType.getCanonicalType();
22106       }
22107 
22108       if (!BaseType.isNull() && BaseType->getAsRecordDecl() &&
22109           isImplicitMapperNeeded(SemaRef, DSAS, BaseType, VE)) {
22110         ER = buildImplicitMapper(SemaRef, BaseType, DSAS);
22111       }
22112     }
22113     MVLI.UDMapperList.push_back(ER.get());
22114 
22115     // Save the current expression.
22116     MVLI.ProcessedVarList.push_back(RE);
22117 
22118     // Store the components in the stack so that they can be used to check
22119     // against other clauses later on.
22120     DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
22121                                           /*WhereFoundClauseKind=*/OMPC_map);
22122 
22123     // Save the components and declaration to create the clause. For purposes of
22124     // the clause creation, any component list that has base 'this' uses
22125     // null as base declaration.
22126     MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22127     MVLI.VarComponents.back().append(CurComponents.begin(),
22128                                      CurComponents.end());
22129     MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
22130                                                            : CurDeclaration);
22131   }
22132 }
22133 
ActOnOpenMPMapClause(Expr * IteratorModifier,ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,ArrayRef<SourceLocation> MapTypeModifiersLoc,CXXScopeSpec & MapperIdScopeSpec,DeclarationNameInfo & MapperId,OpenMPMapClauseKind MapType,bool IsMapTypeImplicit,SourceLocation MapLoc,SourceLocation ColonLoc,ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs,bool NoDiagnose,ArrayRef<Expr * > UnresolvedMappers)22134 OMPClause *SemaOpenMP::ActOnOpenMPMapClause(
22135     Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
22136     ArrayRef<SourceLocation> MapTypeModifiersLoc,
22137     CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22138     OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
22139     SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22140     const OMPVarListLocTy &Locs, bool NoDiagnose,
22141     ArrayRef<Expr *> UnresolvedMappers) {
22142   OpenMPMapModifierKind Modifiers[] = {
22143       OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
22144       OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
22145       OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
22146       OMPC_MAP_MODIFIER_unknown};
22147   SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers];
22148 
22149   if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
22150                               BuiltinType::OMPIterator))
22151     Diag(IteratorModifier->getExprLoc(),
22152          diag::err_omp_map_modifier_not_iterator);
22153 
22154   // Process map-type-modifiers, flag errors for duplicate modifiers.
22155   unsigned Count = 0;
22156   for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
22157     if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
22158         llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
22159       Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
22160       continue;
22161     }
22162     assert(Count < NumberOfOMPMapClauseModifiers &&
22163            "Modifiers exceed the allowed number of map type modifiers");
22164     Modifiers[Count] = MapTypeModifiers[I];
22165     ModifiersLoc[Count] = MapTypeModifiersLoc[I];
22166     ++Count;
22167   }
22168 
22169   MappableVarListInfo MVLI(VarList);
22170   checkMappableExpressionList(SemaRef, DSAStack, OMPC_map, MVLI, Locs.StartLoc,
22171                               MapperIdScopeSpec, MapperId, UnresolvedMappers,
22172                               MapType, Modifiers, IsMapTypeImplicit,
22173                               NoDiagnose);
22174 
22175   // We need to produce a map clause even if we don't have variables so that
22176   // other diagnostics related with non-existing map clauses are accurate.
22177   return OMPMapClause::Create(
22178       getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22179       MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
22180       ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
22181       MapperId, MapType, IsMapTypeImplicit, MapLoc);
22182 }
22183 
ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,TypeResult ParsedType)22184 QualType SemaOpenMP::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
22185                                                      TypeResult ParsedType) {
22186   assert(ParsedType.isUsable());
22187 
22188   QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get());
22189   if (ReductionType.isNull())
22190     return QualType();
22191 
22192   // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
22193   // A type name in a declare reduction directive cannot be a function type, an
22194   // array type, a reference type, or a type qualified with const, volatile or
22195   // restrict.
22196   if (ReductionType.hasQualifiers()) {
22197     Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
22198     return QualType();
22199   }
22200 
22201   if (ReductionType->isFunctionType()) {
22202     Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
22203     return QualType();
22204   }
22205   if (ReductionType->isReferenceType()) {
22206     Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
22207     return QualType();
22208   }
22209   if (ReductionType->isArrayType()) {
22210     Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
22211     return QualType();
22212   }
22213   return ReductionType;
22214 }
22215 
22216 SemaOpenMP::DeclGroupPtrTy
ActOnOpenMPDeclareReductionDirectiveStart(Scope * S,DeclContext * DC,DeclarationName Name,ArrayRef<std::pair<QualType,SourceLocation>> ReductionTypes,AccessSpecifier AS,Decl * PrevDeclInScope)22217 SemaOpenMP::ActOnOpenMPDeclareReductionDirectiveStart(
22218     Scope *S, DeclContext *DC, DeclarationName Name,
22219     ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
22220     AccessSpecifier AS, Decl *PrevDeclInScope) {
22221   SmallVector<Decl *, 8> Decls;
22222   Decls.reserve(ReductionTypes.size());
22223 
22224   LookupResult Lookup(SemaRef, Name, SourceLocation(),
22225                       Sema::LookupOMPReductionName,
22226                       SemaRef.forRedeclarationInCurContext());
22227   // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
22228   // A reduction-identifier may not be re-declared in the current scope for the
22229   // same type or for a type that is compatible according to the base language
22230   // rules.
22231   llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22232   OMPDeclareReductionDecl *PrevDRD = nullptr;
22233   bool InCompoundScope = true;
22234   if (S != nullptr) {
22235     // Find previous declaration with the same name not referenced in other
22236     // declarations.
22237     FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
22238     InCompoundScope =
22239         (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22240     SemaRef.LookupName(Lookup, S);
22241     SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22242                                  /*AllowInlineNamespace=*/false);
22243     llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
22244     LookupResult::Filter Filter = Lookup.makeFilter();
22245     while (Filter.hasNext()) {
22246       auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
22247       if (InCompoundScope) {
22248         UsedAsPrevious.try_emplace(PrevDecl, false);
22249         if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
22250           UsedAsPrevious[D] = true;
22251       }
22252       PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22253           PrevDecl->getLocation();
22254     }
22255     Filter.done();
22256     if (InCompoundScope) {
22257       for (const auto &PrevData : UsedAsPrevious) {
22258         if (!PrevData.second) {
22259           PrevDRD = PrevData.first;
22260           break;
22261         }
22262       }
22263     }
22264   } else if (PrevDeclInScope != nullptr) {
22265     auto *PrevDRDInScope = PrevDRD =
22266         cast<OMPDeclareReductionDecl>(PrevDeclInScope);
22267     do {
22268       PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
22269           PrevDRDInScope->getLocation();
22270       PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
22271     } while (PrevDRDInScope != nullptr);
22272   }
22273   for (const auto &TyData : ReductionTypes) {
22274     const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
22275     bool Invalid = false;
22276     if (I != PreviousRedeclTypes.end()) {
22277       Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
22278           << TyData.first;
22279       Diag(I->second, diag::note_previous_definition);
22280       Invalid = true;
22281     }
22282     PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
22283     auto *DRD = OMPDeclareReductionDecl::Create(
22284         getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
22285     DC->addDecl(DRD);
22286     DRD->setAccess(AS);
22287     Decls.push_back(DRD);
22288     if (Invalid)
22289       DRD->setInvalidDecl();
22290     else
22291       PrevDRD = DRD;
22292   }
22293 
22294   return DeclGroupPtrTy::make(
22295       DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size()));
22296 }
22297 
ActOnOpenMPDeclareReductionCombinerStart(Scope * S,Decl * D)22298 void SemaOpenMP::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
22299   auto *DRD = cast<OMPDeclareReductionDecl>(D);
22300 
22301   // Enter new function scope.
22302   SemaRef.PushFunctionScope();
22303   SemaRef.setFunctionHasBranchProtectedScope();
22304   SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
22305 
22306   if (S != nullptr)
22307     SemaRef.PushDeclContext(S, DRD);
22308   else
22309     SemaRef.CurContext = DRD;
22310 
22311   SemaRef.PushExpressionEvaluationContext(
22312       Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
22313 
22314   QualType ReductionType = DRD->getType();
22315   // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
22316   // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
22317   // uses semantics of argument handles by value, but it should be passed by
22318   // reference. C lang does not support references, so pass all parameters as
22319   // pointers.
22320   // Create 'T omp_in;' variable.
22321   VarDecl *OmpInParm =
22322       buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in");
22323   // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
22324   // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
22325   // uses semantics of argument handles by value, but it should be passed by
22326   // reference. C lang does not support references, so pass all parameters as
22327   // pointers.
22328   // Create 'T omp_out;' variable.
22329   VarDecl *OmpOutParm =
22330       buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out");
22331   if (S != nullptr) {
22332     SemaRef.PushOnScopeChains(OmpInParm, S);
22333     SemaRef.PushOnScopeChains(OmpOutParm, S);
22334   } else {
22335     DRD->addDecl(OmpInParm);
22336     DRD->addDecl(OmpOutParm);
22337   }
22338   Expr *InE =
22339       ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation());
22340   Expr *OutE =
22341       ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation());
22342   DRD->setCombinerData(InE, OutE);
22343 }
22344 
ActOnOpenMPDeclareReductionCombinerEnd(Decl * D,Expr * Combiner)22345 void SemaOpenMP::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D,
22346                                                         Expr *Combiner) {
22347   auto *DRD = cast<OMPDeclareReductionDecl>(D);
22348   SemaRef.DiscardCleanupsInEvaluationContext();
22349   SemaRef.PopExpressionEvaluationContext();
22350 
22351   SemaRef.PopDeclContext();
22352   SemaRef.PopFunctionScopeInfo();
22353 
22354   if (Combiner != nullptr)
22355     DRD->setCombiner(Combiner);
22356   else
22357     DRD->setInvalidDecl();
22358 }
22359 
ActOnOpenMPDeclareReductionInitializerStart(Scope * S,Decl * D)22360 VarDecl *SemaOpenMP::ActOnOpenMPDeclareReductionInitializerStart(Scope *S,
22361                                                                  Decl *D) {
22362   auto *DRD = cast<OMPDeclareReductionDecl>(D);
22363 
22364   // Enter new function scope.
22365   SemaRef.PushFunctionScope();
22366   SemaRef.setFunctionHasBranchProtectedScope();
22367 
22368   if (S != nullptr)
22369     SemaRef.PushDeclContext(S, DRD);
22370   else
22371     SemaRef.CurContext = DRD;
22372 
22373   SemaRef.PushExpressionEvaluationContext(
22374       Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
22375 
22376   QualType ReductionType = DRD->getType();
22377   // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
22378   // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
22379   // uses semantics of argument handles by value, but it should be passed by
22380   // reference. C lang does not support references, so pass all parameters as
22381   // pointers.
22382   // Create 'T omp_priv;' variable.
22383   VarDecl *OmpPrivParm =
22384       buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv");
22385   // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
22386   // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
22387   // uses semantics of argument handles by value, but it should be passed by
22388   // reference. C lang does not support references, so pass all parameters as
22389   // pointers.
22390   // Create 'T omp_orig;' variable.
22391   VarDecl *OmpOrigParm =
22392       buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig");
22393   if (S != nullptr) {
22394     SemaRef.PushOnScopeChains(OmpPrivParm, S);
22395     SemaRef.PushOnScopeChains(OmpOrigParm, S);
22396   } else {
22397     DRD->addDecl(OmpPrivParm);
22398     DRD->addDecl(OmpOrigParm);
22399   }
22400   Expr *OrigE =
22401       ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation());
22402   Expr *PrivE =
22403       ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation());
22404   DRD->setInitializerData(OrigE, PrivE);
22405   return OmpPrivParm;
22406 }
22407 
ActOnOpenMPDeclareReductionInitializerEnd(Decl * D,Expr * Initializer,VarDecl * OmpPrivParm)22408 void SemaOpenMP::ActOnOpenMPDeclareReductionInitializerEnd(
22409     Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
22410   auto *DRD = cast<OMPDeclareReductionDecl>(D);
22411   SemaRef.DiscardCleanupsInEvaluationContext();
22412   SemaRef.PopExpressionEvaluationContext();
22413 
22414   SemaRef.PopDeclContext();
22415   SemaRef.PopFunctionScopeInfo();
22416 
22417   if (Initializer != nullptr) {
22418     DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
22419   } else if (OmpPrivParm->hasInit()) {
22420     DRD->setInitializer(OmpPrivParm->getInit(),
22421                         OmpPrivParm->isDirectInit()
22422                             ? OMPDeclareReductionInitKind::Direct
22423                             : OMPDeclareReductionInitKind::Copy);
22424   } else {
22425     DRD->setInvalidDecl();
22426   }
22427 }
22428 
ActOnOpenMPDeclareReductionDirectiveEnd(Scope * S,DeclGroupPtrTy DeclReductions,bool IsValid)22429 SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareReductionDirectiveEnd(
22430     Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
22431   for (Decl *D : DeclReductions.get()) {
22432     if (IsValid) {
22433       if (S)
22434         SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
22435                                   /*AddToContext=*/false);
22436     } else {
22437       D->setInvalidDecl();
22438     }
22439   }
22440   return DeclReductions;
22441 }
22442 
ActOnOpenMPDeclareMapperVarDecl(Scope * S,Declarator & D)22443 TypeResult SemaOpenMP::ActOnOpenMPDeclareMapperVarDecl(Scope *S,
22444                                                        Declarator &D) {
22445   TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
22446   QualType T = TInfo->getType();
22447   if (D.isInvalidType())
22448     return true;
22449 
22450   if (getLangOpts().CPlusPlus) {
22451     // Check that there are no default arguments (C++ only).
22452     SemaRef.CheckExtraCXXDefaultArguments(D);
22453   }
22454 
22455   return SemaRef.CreateParsedType(T, TInfo);
22456 }
22457 
ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,TypeResult ParsedType)22458 QualType SemaOpenMP::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
22459                                                   TypeResult ParsedType) {
22460   assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
22461 
22462   QualType MapperType = SemaRef.GetTypeFromParser(ParsedType.get());
22463   assert(!MapperType.isNull() && "Expect valid mapper type");
22464 
22465   // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22466   //  The type must be of struct, union or class type in C and C++
22467   if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
22468     Diag(TyLoc, diag::err_omp_mapper_wrong_type);
22469     return QualType();
22470   }
22471   return MapperType;
22472 }
22473 
ActOnOpenMPDeclareMapperDirective(Scope * S,DeclContext * DC,DeclarationName Name,QualType MapperType,SourceLocation StartLoc,DeclarationName VN,AccessSpecifier AS,Expr * MapperVarRef,ArrayRef<OMPClause * > Clauses,Decl * PrevDeclInScope)22474 SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareMapperDirective(
22475     Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
22476     SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
22477     Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
22478   LookupResult Lookup(SemaRef, Name, SourceLocation(),
22479                       Sema::LookupOMPMapperName,
22480                       SemaRef.forRedeclarationInCurContext());
22481   // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22482   //  A mapper-identifier may not be redeclared in the current scope for the
22483   //  same type or for a type that is compatible according to the base language
22484   //  rules.
22485   llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22486   OMPDeclareMapperDecl *PrevDMD = nullptr;
22487   bool InCompoundScope = true;
22488   if (S != nullptr) {
22489     // Find previous declaration with the same name not referenced in other
22490     // declarations.
22491     FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
22492     InCompoundScope =
22493         (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22494     SemaRef.LookupName(Lookup, S);
22495     SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22496                                  /*AllowInlineNamespace=*/false);
22497     llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
22498     LookupResult::Filter Filter = Lookup.makeFilter();
22499     while (Filter.hasNext()) {
22500       auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
22501       if (InCompoundScope) {
22502         UsedAsPrevious.try_emplace(PrevDecl, false);
22503         if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
22504           UsedAsPrevious[D] = true;
22505       }
22506       PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22507           PrevDecl->getLocation();
22508     }
22509     Filter.done();
22510     if (InCompoundScope) {
22511       for (const auto &PrevData : UsedAsPrevious) {
22512         if (!PrevData.second) {
22513           PrevDMD = PrevData.first;
22514           break;
22515         }
22516       }
22517     }
22518   } else if (PrevDeclInScope) {
22519     auto *PrevDMDInScope = PrevDMD =
22520         cast<OMPDeclareMapperDecl>(PrevDeclInScope);
22521     do {
22522       PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
22523           PrevDMDInScope->getLocation();
22524       PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
22525     } while (PrevDMDInScope != nullptr);
22526   }
22527   const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
22528   bool Invalid = false;
22529   if (I != PreviousRedeclTypes.end()) {
22530     Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
22531         << MapperType << Name;
22532     Diag(I->second, diag::note_previous_definition);
22533     Invalid = true;
22534   }
22535   // Build expressions for implicit maps of data members with 'default'
22536   // mappers.
22537   SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
22538   if (getLangOpts().OpenMP >= 50)
22539     processImplicitMapsWithDefaultMappers(SemaRef, DSAStack,
22540                                           ClausesWithImplicit);
22541   auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name,
22542                                            MapperType, VN, ClausesWithImplicit,
22543                                            PrevDMD);
22544   if (S)
22545     SemaRef.PushOnScopeChains(DMD, S);
22546   else
22547     DC->addDecl(DMD);
22548   DMD->setAccess(AS);
22549   if (Invalid)
22550     DMD->setInvalidDecl();
22551 
22552   auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22553   VD->setDeclContext(DMD);
22554   VD->setLexicalDeclContext(DMD);
22555   DMD->addDecl(VD);
22556   DMD->setMapperVarRef(MapperVarRef);
22557 
22558   return DeclGroupPtrTy::make(DeclGroupRef(DMD));
22559 }
22560 
ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope * S,QualType MapperType,SourceLocation StartLoc,DeclarationName VN)22561 ExprResult SemaOpenMP::ActOnOpenMPDeclareMapperDirectiveVarDecl(
22562     Scope *S, QualType MapperType, SourceLocation StartLoc,
22563     DeclarationName VN) {
22564   TypeSourceInfo *TInfo =
22565       getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc);
22566   auto *VD = VarDecl::Create(
22567       getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc,
22568       StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None);
22569   if (S)
22570     SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false);
22571   Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc);
22572   DSAStack->addDeclareMapperVarRef(E);
22573   return E;
22574 }
22575 
ActOnOpenMPIteratorVarDecl(VarDecl * VD)22576 void SemaOpenMP::ActOnOpenMPIteratorVarDecl(VarDecl *VD) {
22577   if (DSAStack->getDeclareMapperVarRef())
22578     DSAStack->addIteratorVarDecl(VD);
22579 }
22580 
isOpenMPDeclareMapperVarDeclAllowed(const VarDecl * VD) const22581 bool SemaOpenMP::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const {
22582   assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
22583   const Expr *Ref = DSAStack->getDeclareMapperVarRef();
22584   if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
22585     if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
22586       return true;
22587     if (VD->isUsableInConstantExpressions(getASTContext()))
22588       return true;
22589     if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
22590       return true;
22591     return false;
22592   }
22593   return true;
22594 }
22595 
getOpenMPDeclareMapperVarName() const22596 const ValueDecl *SemaOpenMP::getOpenMPDeclareMapperVarName() const {
22597   assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
22598   return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
22599 }
22600 
ActOnOpenMPNumTeamsClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)22601 OMPClause *SemaOpenMP::ActOnOpenMPNumTeamsClause(ArrayRef<Expr *> VarList,
22602                                                  SourceLocation StartLoc,
22603                                                  SourceLocation LParenLoc,
22604                                                  SourceLocation EndLoc) {
22605   if (VarList.empty())
22606     return nullptr;
22607 
22608   for (Expr *ValExpr : VarList) {
22609     // OpenMP [teams Constrcut, Restrictions]
22610     // The num_teams expression must evaluate to a positive integer value.
22611     if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams,
22612                                    /*StrictlyPositive=*/true))
22613       return nullptr;
22614   }
22615 
22616   OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22617   OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
22618       DKind, OMPC_num_teams, getLangOpts().OpenMP);
22619   if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
22620     return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
22621                                      LParenLoc, EndLoc, VarList,
22622                                      /*PreInit=*/nullptr);
22623 
22624   llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22625   SmallVector<Expr *, 3> Vars;
22626   for (Expr *ValExpr : VarList) {
22627     ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22628     ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22629     Vars.push_back(ValExpr);
22630   }
22631 
22632   Stmt *PreInit = buildPreInits(getASTContext(), Captures);
22633   return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
22634                                    LParenLoc, EndLoc, Vars, PreInit);
22635 }
22636 
ActOnOpenMPThreadLimitClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)22637 OMPClause *SemaOpenMP::ActOnOpenMPThreadLimitClause(ArrayRef<Expr *> VarList,
22638                                                     SourceLocation StartLoc,
22639                                                     SourceLocation LParenLoc,
22640                                                     SourceLocation EndLoc) {
22641   if (VarList.empty())
22642     return nullptr;
22643 
22644   for (Expr *ValExpr : VarList) {
22645     // OpenMP [teams Constrcut, Restrictions]
22646     // The thread_limit expression must evaluate to a positive integer value.
22647     if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit,
22648                                    /*StrictlyPositive=*/true))
22649       return nullptr;
22650   }
22651 
22652   OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22653   OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
22654       DKind, OMPC_thread_limit, getLangOpts().OpenMP);
22655   if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
22656     return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion,
22657                                         StartLoc, LParenLoc, EndLoc, VarList,
22658                                         /*PreInit=*/nullptr);
22659 
22660   llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22661   SmallVector<Expr *, 3> Vars;
22662   for (Expr *ValExpr : VarList) {
22663     ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22664     ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22665     Vars.push_back(ValExpr);
22666   }
22667 
22668   Stmt *PreInit = buildPreInits(getASTContext(), Captures);
22669   return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion, StartLoc,
22670                                       LParenLoc, EndLoc, Vars, PreInit);
22671 }
22672 
ActOnOpenMPPriorityClause(Expr * Priority,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)22673 OMPClause *SemaOpenMP::ActOnOpenMPPriorityClause(Expr *Priority,
22674                                                  SourceLocation StartLoc,
22675                                                  SourceLocation LParenLoc,
22676                                                  SourceLocation EndLoc) {
22677   Expr *ValExpr = Priority;
22678   Stmt *HelperValStmt = nullptr;
22679   OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22680 
22681   // OpenMP [2.9.1, task Constrcut]
22682   // The priority-value is a non-negative numerical scalar expression.
22683   if (!isNonNegativeIntegerValue(
22684           ValExpr, SemaRef, OMPC_priority,
22685           /*StrictlyPositive=*/false, /*BuildCapture=*/true,
22686           DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22687     return nullptr;
22688 
22689   return new (getASTContext()) OMPPriorityClause(
22690       ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22691 }
22692 
ActOnOpenMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier,Expr * Grainsize,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ModifierLoc,SourceLocation EndLoc)22693 OMPClause *SemaOpenMP::ActOnOpenMPGrainsizeClause(
22694     OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
22695     SourceLocation StartLoc, SourceLocation LParenLoc,
22696     SourceLocation ModifierLoc, SourceLocation EndLoc) {
22697   assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
22698          "Unexpected grainsize modifier in OpenMP < 51.");
22699 
22700   if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
22701     std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
22702                                                  OMPC_GRAINSIZE_unknown);
22703     Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22704         << Values << getOpenMPClauseNameForDiag(OMPC_grainsize);
22705     return nullptr;
22706   }
22707 
22708   Expr *ValExpr = Grainsize;
22709   Stmt *HelperValStmt = nullptr;
22710   OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22711 
22712   // OpenMP [2.9.2, taskloop Constrcut]
22713   // The parameter of the grainsize clause must be a positive integer
22714   // expression.
22715   if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize,
22716                                  /*StrictlyPositive=*/true,
22717                                  /*BuildCapture=*/true,
22718                                  DSAStack->getCurrentDirective(),
22719                                  &CaptureRegion, &HelperValStmt))
22720     return nullptr;
22721 
22722   return new (getASTContext())
22723       OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22724                          StartLoc, LParenLoc, ModifierLoc, EndLoc);
22725 }
22726 
ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier,Expr * NumTasks,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ModifierLoc,SourceLocation EndLoc)22727 OMPClause *SemaOpenMP::ActOnOpenMPNumTasksClause(
22728     OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
22729     SourceLocation StartLoc, SourceLocation LParenLoc,
22730     SourceLocation ModifierLoc, SourceLocation EndLoc) {
22731   assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
22732          "Unexpected num_tasks modifier in OpenMP < 51.");
22733 
22734   if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
22735     std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
22736                                                  OMPC_NUMTASKS_unknown);
22737     Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22738         << Values << getOpenMPClauseNameForDiag(OMPC_num_tasks);
22739     return nullptr;
22740   }
22741 
22742   Expr *ValExpr = NumTasks;
22743   Stmt *HelperValStmt = nullptr;
22744   OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22745 
22746   // OpenMP [2.9.2, taskloop Constrcut]
22747   // The parameter of the num_tasks clause must be a positive integer
22748   // expression.
22749   if (!isNonNegativeIntegerValue(
22750           ValExpr, SemaRef, OMPC_num_tasks,
22751           /*StrictlyPositive=*/true, /*BuildCapture=*/true,
22752           DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22753     return nullptr;
22754 
22755   return new (getASTContext())
22756       OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22757                         StartLoc, LParenLoc, ModifierLoc, EndLoc);
22758 }
22759 
ActOnOpenMPHintClause(Expr * Hint,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)22760 OMPClause *SemaOpenMP::ActOnOpenMPHintClause(Expr *Hint,
22761                                              SourceLocation StartLoc,
22762                                              SourceLocation LParenLoc,
22763                                              SourceLocation EndLoc) {
22764   // OpenMP [2.13.2, critical construct, Description]
22765   // ... where hint-expression is an integer constant expression that evaluates
22766   // to a valid lock hint.
22767   ExprResult HintExpr =
22768       VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
22769   if (HintExpr.isInvalid())
22770     return nullptr;
22771   return new (getASTContext())
22772       OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
22773 }
22774 
22775 /// Tries to find omp_event_handle_t type.
findOMPEventHandleT(Sema & S,SourceLocation Loc,DSAStackTy * Stack)22776 static bool findOMPEventHandleT(Sema &S, SourceLocation Loc,
22777                                 DSAStackTy *Stack) {
22778   QualType OMPEventHandleT = Stack->getOMPEventHandleT();
22779   if (!OMPEventHandleT.isNull())
22780     return true;
22781   IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
22782   ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
22783   if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
22784     S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
22785     return false;
22786   }
22787   Stack->setOMPEventHandleT(PT.get());
22788   return true;
22789 }
22790 
ActOnOpenMPDetachClause(Expr * Evt,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)22791 OMPClause *SemaOpenMP::ActOnOpenMPDetachClause(Expr *Evt,
22792                                                SourceLocation StartLoc,
22793                                                SourceLocation LParenLoc,
22794                                                SourceLocation EndLoc) {
22795   if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
22796       !Evt->isInstantiationDependent() &&
22797       !Evt->containsUnexpandedParameterPack()) {
22798     if (!findOMPEventHandleT(SemaRef, Evt->getExprLoc(), DSAStack))
22799       return nullptr;
22800     // OpenMP 5.0, 2.10.1 task Construct.
22801     // event-handle is a variable of the omp_event_handle_t type.
22802     auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
22803     if (!Ref) {
22804       Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22805           << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22806       return nullptr;
22807     }
22808     auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
22809     if (!VD) {
22810       Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22811           << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22812       return nullptr;
22813     }
22814     if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
22815                                                 VD->getType()) ||
22816         VD->getType().isConstant(getASTContext())) {
22817       Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22818           << "omp_event_handle_t" << 1 << VD->getType()
22819           << Evt->getSourceRange();
22820       return nullptr;
22821     }
22822     // OpenMP 5.0, 2.10.1 task Construct
22823     // [detach clause]... The event-handle will be considered as if it was
22824     // specified on a firstprivate clause.
22825     DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
22826     if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
22827         DVar.RefExpr) {
22828       Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
22829           << getOpenMPClauseNameForDiag(DVar.CKind)
22830           << getOpenMPClauseNameForDiag(OMPC_firstprivate);
22831       reportOriginalDsa(SemaRef, DSAStack, VD, DVar);
22832       return nullptr;
22833     }
22834   }
22835 
22836   return new (getASTContext())
22837       OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
22838 }
22839 
ActOnOpenMPDistScheduleClause(OpenMPDistScheduleClauseKind Kind,Expr * ChunkSize,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation KindLoc,SourceLocation CommaLoc,SourceLocation EndLoc)22840 OMPClause *SemaOpenMP::ActOnOpenMPDistScheduleClause(
22841     OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
22842     SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
22843     SourceLocation EndLoc) {
22844   if (Kind == OMPC_DIST_SCHEDULE_unknown) {
22845     std::string Values;
22846     Values += "'";
22847     Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
22848     Values += "'";
22849     Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22850         << Values << getOpenMPClauseNameForDiag(OMPC_dist_schedule);
22851     return nullptr;
22852   }
22853   Expr *ValExpr = ChunkSize;
22854   Stmt *HelperValStmt = nullptr;
22855   if (ChunkSize) {
22856     if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
22857         !ChunkSize->isInstantiationDependent() &&
22858         !ChunkSize->containsUnexpandedParameterPack()) {
22859       SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
22860       ExprResult Val =
22861           PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
22862       if (Val.isInvalid())
22863         return nullptr;
22864 
22865       ValExpr = Val.get();
22866 
22867       // OpenMP [2.7.1, Restrictions]
22868       //  chunk_size must be a loop invariant integer expression with a positive
22869       //  value.
22870       if (std::optional<llvm::APSInt> Result =
22871               ValExpr->getIntegerConstantExpr(getASTContext())) {
22872         if (Result->isSigned() && !Result->isStrictlyPositive()) {
22873           Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
22874               << "dist_schedule" << /*strictly positive*/ 1
22875               << ChunkSize->getSourceRange();
22876           return nullptr;
22877         }
22878       } else if (getOpenMPCaptureRegionForClause(
22879                      DSAStack->getCurrentDirective(), OMPC_dist_schedule,
22880                      getLangOpts().OpenMP) != OMPD_unknown &&
22881                  !SemaRef.CurContext->isDependentContext()) {
22882         ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22883         llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22884         ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22885         HelperValStmt = buildPreInits(getASTContext(), Captures);
22886       }
22887     }
22888   }
22889 
22890   return new (getASTContext())
22891       OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
22892                             Kind, ValExpr, HelperValStmt);
22893 }
22894 
ActOnOpenMPDefaultmapClause(OpenMPDefaultmapClauseModifier M,OpenMPDefaultmapClauseKind Kind,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation MLoc,SourceLocation KindLoc,SourceLocation EndLoc)22895 OMPClause *SemaOpenMP::ActOnOpenMPDefaultmapClause(
22896     OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind,
22897     SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
22898     SourceLocation KindLoc, SourceLocation EndLoc) {
22899   if (getLangOpts().OpenMP < 50) {
22900     if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
22901         Kind != OMPC_DEFAULTMAP_scalar) {
22902       std::string Value;
22903       SourceLocation Loc;
22904       Value += "'";
22905       if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
22906         Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22907                                                OMPC_DEFAULTMAP_MODIFIER_tofrom);
22908         Loc = MLoc;
22909       } else {
22910         Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22911                                                OMPC_DEFAULTMAP_scalar);
22912         Loc = KindLoc;
22913       }
22914       Value += "'";
22915       Diag(Loc, diag::err_omp_unexpected_clause_value)
22916           << Value << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22917       return nullptr;
22918     }
22919   } else {
22920     bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
22921     bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
22922                             (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
22923     if (!isDefaultmapKind || !isDefaultmapModifier) {
22924       StringRef KindValue = getLangOpts().OpenMP < 52
22925                                 ? "'scalar', 'aggregate', 'pointer'"
22926                                 : "'scalar', 'aggregate', 'pointer', 'all'";
22927       if (getLangOpts().OpenMP == 50) {
22928         StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
22929                                   "'firstprivate', 'none', 'default'";
22930         if (!isDefaultmapKind && isDefaultmapModifier) {
22931           Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22932               << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22933         } else if (isDefaultmapKind && !isDefaultmapModifier) {
22934           Diag(MLoc, diag::err_omp_unexpected_clause_value)
22935               << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22936         } else {
22937           Diag(MLoc, diag::err_omp_unexpected_clause_value)
22938               << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22939           Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22940               << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22941         }
22942       } else {
22943         StringRef ModifierValue =
22944             "'alloc', 'from', 'to', 'tofrom', "
22945             "'firstprivate', 'none', 'default', 'present'";
22946         if (!isDefaultmapKind && isDefaultmapModifier) {
22947           Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22948               << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22949         } else if (isDefaultmapKind && !isDefaultmapModifier) {
22950           Diag(MLoc, diag::err_omp_unexpected_clause_value)
22951               << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22952         } else {
22953           Diag(MLoc, diag::err_omp_unexpected_clause_value)
22954               << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22955           Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22956               << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22957         }
22958       }
22959       return nullptr;
22960     }
22961 
22962     // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
22963     //  At most one defaultmap clause for each category can appear on the
22964     //  directive.
22965     if (DSAStack->checkDefaultmapCategory(Kind)) {
22966       Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
22967       return nullptr;
22968     }
22969   }
22970   if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
22971     // Variable category is not specified - mark all categories.
22972     DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
22973     DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
22974     DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
22975   } else {
22976     DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
22977   }
22978 
22979   return new (getASTContext())
22980       OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
22981 }
22982 
ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo & DTCI)22983 bool SemaOpenMP::ActOnStartOpenMPDeclareTargetContext(
22984     DeclareTargetContextInfo &DTCI) {
22985   DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
22986   if (!CurLexicalContext->isFileContext() &&
22987       !CurLexicalContext->isExternCContext() &&
22988       !CurLexicalContext->isExternCXXContext() &&
22989       !isa<CXXRecordDecl>(CurLexicalContext) &&
22990       !isa<ClassTemplateDecl>(CurLexicalContext) &&
22991       !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
22992       !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
22993     Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
22994     return false;
22995   }
22996 
22997   // Report affected OpenMP target offloading behavior when in HIP lang-mode.
22998   if (getLangOpts().HIP)
22999     Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
23000 
23001   DeclareTargetNesting.push_back(DTCI);
23002   return true;
23003 }
23004 
23005 const SemaOpenMP::DeclareTargetContextInfo
ActOnOpenMPEndDeclareTargetDirective()23006 SemaOpenMP::ActOnOpenMPEndDeclareTargetDirective() {
23007   assert(!DeclareTargetNesting.empty() &&
23008          "check isInOpenMPDeclareTargetContext() first!");
23009   return DeclareTargetNesting.pop_back_val();
23010 }
23011 
ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo & DTCI)23012 void SemaOpenMP::ActOnFinishedOpenMPDeclareTargetContext(
23013     DeclareTargetContextInfo &DTCI) {
23014   for (auto &It : DTCI.ExplicitlyMapped)
23015     ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
23016 }
23017 
DiagnoseUnterminatedOpenMPDeclareTarget()23018 void SemaOpenMP::DiagnoseUnterminatedOpenMPDeclareTarget() {
23019   if (DeclareTargetNesting.empty())
23020     return;
23021   DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23022   unsigned OMPVersion = getLangOpts().OpenMP;
23023   Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
23024       << getOpenMPDirectiveName(DTCI.Kind, OMPVersion);
23025 }
23026 
lookupOpenMPDeclareTargetName(Scope * CurScope,CXXScopeSpec & ScopeSpec,const DeclarationNameInfo & Id)23027 NamedDecl *SemaOpenMP::lookupOpenMPDeclareTargetName(
23028     Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
23029   LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName);
23030   SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
23031                            /*ObjectType=*/QualType(),
23032                            /*AllowBuiltinCreation=*/true);
23033 
23034   if (Lookup.isAmbiguous())
23035     return nullptr;
23036   Lookup.suppressDiagnostics();
23037 
23038   if (!Lookup.isSingleResult()) {
23039     VarOrFuncDeclFilterCCC CCC(SemaRef);
23040     if (TypoCorrection Corrected =
23041             SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
23042                                 CCC, CorrectTypoKind::ErrorRecovery)) {
23043       SemaRef.diagnoseTypo(Corrected,
23044                            SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
23045                                << Id.getName());
23046       checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
23047       return nullptr;
23048     }
23049 
23050     Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
23051     return nullptr;
23052   }
23053 
23054   NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
23055   if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
23056       !isa<FunctionTemplateDecl>(ND)) {
23057     Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
23058     return nullptr;
23059   }
23060   return ND;
23061 }
23062 
ActOnOpenMPDeclareTargetName(NamedDecl * ND,SourceLocation Loc,OMPDeclareTargetDeclAttr::MapTypeTy MT,DeclareTargetContextInfo & DTCI)23063 void SemaOpenMP::ActOnOpenMPDeclareTargetName(
23064     NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
23065     DeclareTargetContextInfo &DTCI) {
23066   assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
23067           isa<FunctionTemplateDecl>(ND)) &&
23068          "Expected variable, function or function template.");
23069 
23070   if (auto *VD = dyn_cast<VarDecl>(ND)) {
23071     // Only global variables can be marked as declare target.
23072     if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23073         !VD->isStaticDataMember()) {
23074       Diag(Loc, diag::err_omp_declare_target_has_local_vars)
23075           << VD->getNameAsString();
23076       return;
23077     }
23078   }
23079   // Diagnose marking after use as it may lead to incorrect diagnosis and
23080   // codegen.
23081   if (getLangOpts().OpenMP >= 50 &&
23082       (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
23083     Diag(Loc, diag::warn_omp_declare_target_after_first_use);
23084 
23085   // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23086   if (getLangOpts().HIP)
23087     Diag(Loc, diag::warn_hip_omp_target_directives);
23088 
23089   // Explicit declare target lists have precedence.
23090   const unsigned Level = -1;
23091 
23092   auto *VD = cast<ValueDecl>(ND);
23093   std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23094       OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23095   if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
23096       (*ActiveAttr)->getLevel() == Level) {
23097     Diag(Loc, diag::err_omp_device_type_mismatch)
23098         << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
23099         << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
23100                (*ActiveAttr)->getDevType());
23101     return;
23102   }
23103   if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
23104       (*ActiveAttr)->getLevel() == Level) {
23105     Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
23106     return;
23107   }
23108 
23109   if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
23110     return;
23111 
23112   Expr *IndirectE = nullptr;
23113   bool IsIndirect = false;
23114   if (DTCI.Indirect) {
23115     IndirectE = *DTCI.Indirect;
23116     if (!IndirectE)
23117       IsIndirect = true;
23118   }
23119   auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23120       getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level,
23121       SourceRange(Loc, Loc));
23122   ND->addAttr(A);
23123   if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
23124     ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
23125   checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
23126   if (auto *VD = dyn_cast<VarDecl>(ND);
23127       getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
23128       VD->hasGlobalStorage())
23129     ActOnOpenMPDeclareTargetInitializer(ND);
23130 }
23131 
checkDeclInTargetContext(SourceLocation SL,SourceRange SR,Sema & SemaRef,Decl * D)23132 static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
23133                                      Sema &SemaRef, Decl *D) {
23134   if (!D || !isa<VarDecl>(D))
23135     return;
23136   auto *VD = cast<VarDecl>(D);
23137   std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
23138       OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
23139   if (SemaRef.LangOpts.OpenMP >= 50 &&
23140       (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
23141        SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
23142       VD->hasGlobalStorage()) {
23143     if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
23144                    *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
23145       // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
23146       // If a lambda declaration and definition appears between a
23147       // declare target directive and the matching end declare target
23148       // directive, all variables that are captured by the lambda
23149       // expression must also appear in a to clause.
23150       SemaRef.Diag(VD->getLocation(),
23151                    diag::err_omp_lambda_capture_in_declare_target_not_to);
23152       SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
23153           << VD << 0 << SR;
23154       return;
23155     }
23156   }
23157   if (MapTy)
23158     return;
23159   SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
23160   SemaRef.Diag(SL, diag::note_used_here) << SR;
23161 }
23162 
checkValueDeclInTarget(SourceLocation SL,SourceRange SR,Sema & SemaRef,DSAStackTy * Stack,ValueDecl * VD)23163 static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR,
23164                                    Sema &SemaRef, DSAStackTy *Stack,
23165                                    ValueDecl *VD) {
23166   return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
23167          checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
23168                            /*FullCheck=*/false);
23169 }
23170 
checkDeclIsAllowedInOpenMPTarget(Expr * E,Decl * D,SourceLocation IdLoc)23171 void SemaOpenMP::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
23172                                                   SourceLocation IdLoc) {
23173   if (!D || D->isInvalidDecl())
23174     return;
23175   SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
23176   SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
23177   if (auto *VD = dyn_cast<VarDecl>(D)) {
23178     // Only global variables can be marked as declare target.
23179     if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23180         !VD->isStaticDataMember())
23181       return;
23182     // 2.10.6: threadprivate variable cannot appear in a declare target
23183     // directive.
23184     if (DSAStack->isThreadPrivate(VD)) {
23185       Diag(SL, diag::err_omp_threadprivate_in_target);
23186       reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false));
23187       return;
23188     }
23189   }
23190   if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
23191     D = FTD->getTemplatedDecl();
23192   if (auto *FD = dyn_cast<FunctionDecl>(D)) {
23193     std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
23194         OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
23195     if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
23196       Diag(IdLoc, diag::err_omp_function_in_link_clause);
23197       Diag(FD->getLocation(), diag::note_defined_here) << FD;
23198       return;
23199     }
23200   }
23201   if (auto *VD = dyn_cast<ValueDecl>(D)) {
23202     // Problem if any with var declared with incomplete type will be reported
23203     // as normal, so no need to check it here.
23204     if ((E || !VD->getType()->isIncompleteType()) &&
23205         !checkValueDeclInTarget(SL, SR, SemaRef, DSAStack, VD))
23206       return;
23207     if (!E && isInOpenMPDeclareTargetContext()) {
23208       // Checking declaration inside declare target region.
23209       if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
23210           isa<FunctionTemplateDecl>(D)) {
23211         std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23212             OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23213         unsigned Level = DeclareTargetNesting.size();
23214         if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
23215           return;
23216         DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23217         Expr *IndirectE = nullptr;
23218         bool IsIndirect = false;
23219         if (DTCI.Indirect) {
23220           IndirectE = *DTCI.Indirect;
23221           if (!IndirectE)
23222             IsIndirect = true;
23223         }
23224         auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23225             getASTContext(),
23226             getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
23227                                        : OMPDeclareTargetDeclAttr::MT_To,
23228             DTCI.DT, IndirectE, IsIndirect, Level,
23229             SourceRange(DTCI.Loc, DTCI.Loc));
23230         D->addAttr(A);
23231         if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
23232           ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
23233       }
23234       return;
23235     }
23236   }
23237   if (!E)
23238     return;
23239   checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), SemaRef, D);
23240 }
23241 
23242 /// This class visits every VarDecl that the initializer references and adds
23243 /// OMPDeclareTargetDeclAttr to each of them.
23244 class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
23245   SmallVector<VarDecl *> DeclVector;
23246   Attr *A;
23247 
23248 public:
23249   /// A StmtVisitor class function that visits all DeclRefExpr and adds
23250   /// OMPDeclareTargetDeclAttr to them.
VisitDeclRefExpr(DeclRefExpr * Node)23251   void VisitDeclRefExpr(DeclRefExpr *Node) {
23252     if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
23253       VD->addAttr(A);
23254       DeclVector.push_back(VD);
23255     }
23256   }
23257   /// A function that iterates across each of the Expr's children.
VisitExpr(Expr * Ex)23258   void VisitExpr(Expr *Ex) {
23259     for (auto *Child : Ex->children()) {
23260       Visit(Child);
23261     }
23262   }
23263   /// A function that keeps a record of all the Decls that are variables, has
23264   /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
23265   /// each Decl one at a time and use the inherited 'visit' functions to look
23266   /// for DeclRefExpr.
declareTargetInitializer(Decl * TD)23267   void declareTargetInitializer(Decl *TD) {
23268     A = TD->getAttr<OMPDeclareTargetDeclAttr>();
23269     DeclVector.push_back(cast<VarDecl>(TD));
23270     llvm::SmallDenseSet<Decl *> Visited;
23271     while (!DeclVector.empty()) {
23272       VarDecl *TargetVarDecl = DeclVector.pop_back_val();
23273       if (!Visited.insert(TargetVarDecl).second)
23274         continue;
23275 
23276       if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
23277           TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
23278         if (Expr *Ex = TargetVarDecl->getInit())
23279           Visit(Ex);
23280       }
23281     }
23282   }
23283 };
23284 
23285 /// Adding OMPDeclareTargetDeclAttr to variables with static storage
23286 /// duration that are referenced in the initializer expression list of
23287 /// variables with static storage duration in declare target directive.
ActOnOpenMPDeclareTargetInitializer(Decl * TargetDecl)23288 void SemaOpenMP::ActOnOpenMPDeclareTargetInitializer(Decl *TargetDecl) {
23289   GlobalDeclRefChecker Checker;
23290   if (isa<VarDecl>(TargetDecl))
23291     Checker.declareTargetInitializer(TargetDecl);
23292 }
23293 
ActOnOpenMPToClause(ArrayRef<OpenMPMotionModifierKind> MotionModifiers,ArrayRef<SourceLocation> MotionModifiersLoc,CXXScopeSpec & MapperIdScopeSpec,DeclarationNameInfo & MapperId,SourceLocation ColonLoc,ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs,ArrayRef<Expr * > UnresolvedMappers)23294 OMPClause *SemaOpenMP::ActOnOpenMPToClause(
23295     ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23296     ArrayRef<SourceLocation> MotionModifiersLoc,
23297     CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23298     SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23299     const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23300   OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
23301                                           OMPC_MOTION_MODIFIER_unknown};
23302   SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
23303 
23304   // Process motion-modifiers, flag errors for duplicate modifiers.
23305   unsigned Count = 0;
23306   for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23307     if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23308         llvm::is_contained(Modifiers, MotionModifiers[I])) {
23309       Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23310       continue;
23311     }
23312     assert(Count < NumberOfOMPMotionModifiers &&
23313            "Modifiers exceed the allowed number of motion modifiers");
23314     Modifiers[Count] = MotionModifiers[I];
23315     ModifiersLoc[Count] = MotionModifiersLoc[I];
23316     ++Count;
23317   }
23318 
23319   MappableVarListInfo MVLI(VarList);
23320   checkMappableExpressionList(SemaRef, DSAStack, OMPC_to, MVLI, Locs.StartLoc,
23321                               MapperIdScopeSpec, MapperId, UnresolvedMappers);
23322   if (MVLI.ProcessedVarList.empty())
23323     return nullptr;
23324 
23325   return OMPToClause::Create(
23326       getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23327       MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23328       MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
23329 }
23330 
ActOnOpenMPFromClause(ArrayRef<OpenMPMotionModifierKind> MotionModifiers,ArrayRef<SourceLocation> MotionModifiersLoc,CXXScopeSpec & MapperIdScopeSpec,DeclarationNameInfo & MapperId,SourceLocation ColonLoc,ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs,ArrayRef<Expr * > UnresolvedMappers)23331 OMPClause *SemaOpenMP::ActOnOpenMPFromClause(
23332     ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23333     ArrayRef<SourceLocation> MotionModifiersLoc,
23334     CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23335     SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23336     const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23337   OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
23338                                           OMPC_MOTION_MODIFIER_unknown};
23339   SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
23340 
23341   // Process motion-modifiers, flag errors for duplicate modifiers.
23342   unsigned Count = 0;
23343   for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23344     if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23345         llvm::is_contained(Modifiers, MotionModifiers[I])) {
23346       Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23347       continue;
23348     }
23349     assert(Count < NumberOfOMPMotionModifiers &&
23350            "Modifiers exceed the allowed number of motion modifiers");
23351     Modifiers[Count] = MotionModifiers[I];
23352     ModifiersLoc[Count] = MotionModifiersLoc[I];
23353     ++Count;
23354   }
23355 
23356   MappableVarListInfo MVLI(VarList);
23357   checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
23358                               MapperIdScopeSpec, MapperId, UnresolvedMappers);
23359   if (MVLI.ProcessedVarList.empty())
23360     return nullptr;
23361 
23362   return OMPFromClause::Create(
23363       getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23364       MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23365       MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
23366 }
23367 
23368 OMPClause *
ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs)23369 SemaOpenMP::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
23370                                           const OMPVarListLocTy &Locs) {
23371   MappableVarListInfo MVLI(VarList);
23372   SmallVector<Expr *, 8> PrivateCopies;
23373   SmallVector<Expr *, 8> Inits;
23374 
23375   for (Expr *RefExpr : VarList) {
23376     assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
23377     SourceLocation ELoc;
23378     SourceRange ERange;
23379     Expr *SimpleRefExpr = RefExpr;
23380     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23381     if (Res.second) {
23382       // It will be analyzed later.
23383       MVLI.ProcessedVarList.push_back(RefExpr);
23384       PrivateCopies.push_back(nullptr);
23385       Inits.push_back(nullptr);
23386     }
23387     ValueDecl *D = Res.first;
23388     if (!D)
23389       continue;
23390 
23391     QualType Type = D->getType();
23392     Type = Type.getNonReferenceType().getUnqualifiedType();
23393 
23394     auto *VD = dyn_cast<VarDecl>(D);
23395 
23396     // Item should be a pointer or reference to pointer.
23397     if (!Type->isPointerType()) {
23398       Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
23399           << 0 << RefExpr->getSourceRange();
23400       continue;
23401     }
23402 
23403     // Build the private variable and the expression that refers to it.
23404     auto VDPrivate =
23405         buildVarDecl(SemaRef, ELoc, Type, D->getName(),
23406                      D->hasAttrs() ? &D->getAttrs() : nullptr,
23407                      VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
23408     if (VDPrivate->isInvalidDecl())
23409       continue;
23410 
23411     SemaRef.CurContext->addDecl(VDPrivate);
23412     DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
23413         SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
23414 
23415     // Add temporary variable to initialize the private copy of the pointer.
23416     VarDecl *VDInit =
23417         buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp");
23418     DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
23419         SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
23420     SemaRef.AddInitializerToDecl(
23421         VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
23422         /*DirectInit=*/false);
23423 
23424     // If required, build a capture to implement the privatization initialized
23425     // with the current list item value.
23426     DeclRefExpr *Ref = nullptr;
23427     if (!VD)
23428       Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
23429     MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23430     PrivateCopies.push_back(VDPrivateRefExpr);
23431     Inits.push_back(VDInitRefExpr);
23432 
23433     // We need to add a data sharing attribute for this variable to make sure it
23434     // is correctly captured. A variable that shows up in a use_device_ptr has
23435     // similar properties of a first private variable.
23436     DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23437 
23438     // Create a mappable component for the list item. List items in this clause
23439     // only need a component.
23440     MVLI.VarBaseDeclarations.push_back(D);
23441     MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23442     MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
23443                                            /*IsNonContiguous=*/false);
23444   }
23445 
23446   if (MVLI.ProcessedVarList.empty())
23447     return nullptr;
23448 
23449   return OMPUseDevicePtrClause::Create(
23450       getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
23451       MVLI.VarBaseDeclarations, MVLI.VarComponents);
23452 }
23453 
23454 OMPClause *
ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs)23455 SemaOpenMP::ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList,
23456                                            const OMPVarListLocTy &Locs) {
23457   MappableVarListInfo MVLI(VarList);
23458 
23459   for (Expr *RefExpr : VarList) {
23460     assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
23461     SourceLocation ELoc;
23462     SourceRange ERange;
23463     Expr *SimpleRefExpr = RefExpr;
23464     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23465                               /*AllowArraySection=*/true);
23466     if (Res.second) {
23467       // It will be analyzed later.
23468       MVLI.ProcessedVarList.push_back(RefExpr);
23469     }
23470     ValueDecl *D = Res.first;
23471     if (!D)
23472       continue;
23473     auto *VD = dyn_cast<VarDecl>(D);
23474 
23475     // If required, build a capture to implement the privatization initialized
23476     // with the current list item value.
23477     DeclRefExpr *Ref = nullptr;
23478     if (!VD)
23479       Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
23480     MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23481 
23482     // We need to add a data sharing attribute for this variable to make sure it
23483     // is correctly captured. A variable that shows up in a use_device_addr has
23484     // similar properties of a first private variable.
23485     DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23486 
23487     // Create a mappable component for the list item. List items in this clause
23488     // only need a component.
23489     MVLI.VarBaseDeclarations.push_back(D);
23490     MVLI.VarComponents.emplace_back();
23491     Expr *Component = SimpleRefExpr;
23492     if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23493                isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23494       Component =
23495           SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
23496     MVLI.VarComponents.back().emplace_back(Component, D,
23497                                            /*IsNonContiguous=*/false);
23498   }
23499 
23500   if (MVLI.ProcessedVarList.empty())
23501     return nullptr;
23502 
23503   return OMPUseDeviceAddrClause::Create(
23504       getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23505       MVLI.VarComponents);
23506 }
23507 
23508 OMPClause *
ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs)23509 SemaOpenMP::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
23510                                          const OMPVarListLocTy &Locs) {
23511   MappableVarListInfo MVLI(VarList);
23512   for (Expr *RefExpr : VarList) {
23513     assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
23514     SourceLocation ELoc;
23515     SourceRange ERange;
23516     Expr *SimpleRefExpr = RefExpr;
23517     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23518     if (Res.second) {
23519       // It will be analyzed later.
23520       MVLI.ProcessedVarList.push_back(RefExpr);
23521     }
23522     ValueDecl *D = Res.first;
23523     if (!D)
23524       continue;
23525 
23526     QualType Type = D->getType();
23527     // item should be a pointer or array or reference to pointer or array
23528     if (!Type.getNonReferenceType()->isPointerType() &&
23529         !Type.getNonReferenceType()->isArrayType()) {
23530       Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
23531           << 0 << RefExpr->getSourceRange();
23532       continue;
23533     }
23534 
23535     // Check if the declaration in the clause does not show up in any data
23536     // sharing attribute.
23537     DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23538     if (isOpenMPPrivate(DVar.CKind)) {
23539       unsigned OMPVersion = getLangOpts().OpenMP;
23540       Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23541           << getOpenMPClauseNameForDiag(DVar.CKind)
23542           << getOpenMPClauseNameForDiag(OMPC_is_device_ptr)
23543           << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
23544                                     OMPVersion);
23545       reportOriginalDsa(SemaRef, DSAStack, D, DVar);
23546       continue;
23547     }
23548 
23549     const Expr *ConflictExpr;
23550     if (DSAStack->checkMappableExprComponentListsForDecl(
23551             D, /*CurrentRegionOnly=*/true,
23552             [&ConflictExpr](
23553                 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
23554                 OpenMPClauseKind) -> bool {
23555               ConflictExpr = R.front().getAssociatedExpression();
23556               return true;
23557             })) {
23558       Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23559       Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23560           << ConflictExpr->getSourceRange();
23561       continue;
23562     }
23563 
23564     // Store the components in the stack so that they can be used to check
23565     // against other clauses later on.
23566     OMPClauseMappableExprCommon::MappableComponent MC(
23567         SimpleRefExpr, D, /*IsNonContiguous=*/false);
23568     DSAStack->addMappableExpressionComponents(
23569         D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
23570 
23571     // Record the expression we've just processed.
23572     MVLI.ProcessedVarList.push_back(SimpleRefExpr);
23573 
23574     // Create a mappable component for the list item. List items in this clause
23575     // only need a component. We use a null declaration to signal fields in
23576     // 'this'.
23577     assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23578             isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23579            "Unexpected device pointer expression!");
23580     MVLI.VarBaseDeclarations.push_back(
23581         isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23582     MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23583     MVLI.VarComponents.back().push_back(MC);
23584   }
23585 
23586   if (MVLI.ProcessedVarList.empty())
23587     return nullptr;
23588 
23589   return OMPIsDevicePtrClause::Create(
23590       getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23591       MVLI.VarComponents);
23592 }
23593 
23594 OMPClause *
ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs)23595 SemaOpenMP::ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr *> VarList,
23596                                            const OMPVarListLocTy &Locs) {
23597   MappableVarListInfo MVLI(VarList);
23598   for (Expr *RefExpr : VarList) {
23599     assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
23600     SourceLocation ELoc;
23601     SourceRange ERange;
23602     Expr *SimpleRefExpr = RefExpr;
23603     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23604                               /*AllowArraySection=*/true);
23605     if (Res.second) {
23606       // It will be analyzed later.
23607       MVLI.ProcessedVarList.push_back(RefExpr);
23608     }
23609     ValueDecl *D = Res.first;
23610     if (!D)
23611       continue;
23612 
23613     // Check if the declaration in the clause does not show up in any data
23614     // sharing attribute.
23615     DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23616     if (isOpenMPPrivate(DVar.CKind)) {
23617       unsigned OMPVersion = getLangOpts().OpenMP;
23618       Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23619           << getOpenMPClauseNameForDiag(DVar.CKind)
23620           << getOpenMPClauseNameForDiag(OMPC_has_device_addr)
23621           << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
23622                                     OMPVersion);
23623       reportOriginalDsa(SemaRef, DSAStack, D, DVar);
23624       continue;
23625     }
23626 
23627     const Expr *ConflictExpr;
23628     if (DSAStack->checkMappableExprComponentListsForDecl(
23629             D, /*CurrentRegionOnly=*/true,
23630             [&ConflictExpr](
23631                 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
23632                 OpenMPClauseKind) -> bool {
23633               ConflictExpr = R.front().getAssociatedExpression();
23634               return true;
23635             })) {
23636       Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23637       Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23638           << ConflictExpr->getSourceRange();
23639       continue;
23640     }
23641 
23642     // Store the components in the stack so that they can be used to check
23643     // against other clauses later on.
23644     Expr *Component = SimpleRefExpr;
23645     auto *VD = dyn_cast<VarDecl>(D);
23646     if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23647                isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23648       Component =
23649           SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
23650     OMPClauseMappableExprCommon::MappableComponent MC(
23651         Component, D, /*IsNonContiguous=*/false);
23652     DSAStack->addMappableExpressionComponents(
23653         D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
23654 
23655     // Record the expression we've just processed.
23656     if (!VD && !SemaRef.CurContext->isDependentContext()) {
23657       DeclRefExpr *Ref =
23658           buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
23659       assert(Ref && "has_device_addr capture failed");
23660       MVLI.ProcessedVarList.push_back(Ref);
23661     } else
23662       MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
23663 
23664     // Create a mappable component for the list item. List items in this clause
23665     // only need a component. We use a null declaration to signal fields in
23666     // 'this'.
23667     assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23668             isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23669            "Unexpected device pointer expression!");
23670     MVLI.VarBaseDeclarations.push_back(
23671         isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23672     MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23673     MVLI.VarComponents.back().push_back(MC);
23674   }
23675 
23676   if (MVLI.ProcessedVarList.empty())
23677     return nullptr;
23678 
23679   return OMPHasDeviceAddrClause::Create(
23680       getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23681       MVLI.VarComponents);
23682 }
23683 
ActOnOpenMPAllocateClause(Expr * Allocator,Expr * Alignment,OpenMPAllocateClauseModifier FirstAllocateModifier,SourceLocation FirstAllocateModifierLoc,OpenMPAllocateClauseModifier SecondAllocateModifier,SourceLocation SecondAllocateModifierLoc,ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ColonLoc,SourceLocation EndLoc)23684 OMPClause *SemaOpenMP::ActOnOpenMPAllocateClause(
23685     Expr *Allocator, Expr *Alignment,
23686     OpenMPAllocateClauseModifier FirstAllocateModifier,
23687     SourceLocation FirstAllocateModifierLoc,
23688     OpenMPAllocateClauseModifier SecondAllocateModifier,
23689     SourceLocation SecondAllocateModifierLoc, ArrayRef<Expr *> VarList,
23690     SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
23691     SourceLocation EndLoc) {
23692   if (Allocator) {
23693     // Allocator expression is dependent - skip it for now and build the
23694     // allocator when instantiated.
23695     bool AllocDependent =
23696         (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
23697          Allocator->isInstantiationDependent() ||
23698          Allocator->containsUnexpandedParameterPack());
23699     if (!AllocDependent) {
23700       // OpenMP [2.11.4 allocate Clause, Description]
23701       // allocator is an expression of omp_allocator_handle_t type.
23702       if (!findOMPAllocatorHandleT(SemaRef, Allocator->getExprLoc(), DSAStack))
23703         return nullptr;
23704 
23705       ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
23706       if (AllocatorRes.isInvalid())
23707         return nullptr;
23708       AllocatorRes = SemaRef.PerformImplicitConversion(
23709           AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
23710           AssignmentAction::Initializing,
23711           /*AllowExplicit=*/true);
23712       if (AllocatorRes.isInvalid())
23713         return nullptr;
23714       Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr;
23715     }
23716   } else {
23717     // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
23718     // allocate clauses that appear on a target construct or on constructs in a
23719     // target region must specify an allocator expression unless a requires
23720     // directive with the dynamic_allocators clause is present in the same
23721     // compilation unit.
23722     if (getLangOpts().OpenMPIsTargetDevice &&
23723         !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
23724       SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
23725   }
23726   if (Alignment) {
23727     bool AlignmentDependent = Alignment->isTypeDependent() ||
23728                               Alignment->isValueDependent() ||
23729                               Alignment->isInstantiationDependent() ||
23730                               Alignment->containsUnexpandedParameterPack();
23731     if (!AlignmentDependent) {
23732       ExprResult AlignResult =
23733           VerifyPositiveIntegerConstantInClause(Alignment, OMPC_allocate);
23734       Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr;
23735     }
23736   }
23737   // Analyze and build list of variables.
23738   SmallVector<Expr *, 8> Vars;
23739   for (Expr *RefExpr : VarList) {
23740     assert(RefExpr && "NULL expr in OpenMP private clause.");
23741     SourceLocation ELoc;
23742     SourceRange ERange;
23743     Expr *SimpleRefExpr = RefExpr;
23744     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23745     if (Res.second) {
23746       // It will be analyzed later.
23747       Vars.push_back(RefExpr);
23748     }
23749     ValueDecl *D = Res.first;
23750     if (!D)
23751       continue;
23752 
23753     auto *VD = dyn_cast<VarDecl>(D);
23754     DeclRefExpr *Ref = nullptr;
23755     if (!VD && !SemaRef.CurContext->isDependentContext())
23756       Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
23757     Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
23758                        ? RefExpr->IgnoreParens()
23759                        : Ref);
23760   }
23761 
23762   if (Vars.empty())
23763     return nullptr;
23764 
23765   if (Allocator)
23766     DSAStack->addInnerAllocatorExpr(Allocator);
23767 
23768   return OMPAllocateClause::Create(
23769       getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
23770       FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
23771       SecondAllocateModifierLoc, EndLoc, Vars);
23772 }
23773 
ActOnOpenMPNontemporalClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)23774 OMPClause *SemaOpenMP::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList,
23775                                                     SourceLocation StartLoc,
23776                                                     SourceLocation LParenLoc,
23777                                                     SourceLocation EndLoc) {
23778   SmallVector<Expr *, 8> Vars;
23779   for (Expr *RefExpr : VarList) {
23780     assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23781     SourceLocation ELoc;
23782     SourceRange ERange;
23783     Expr *SimpleRefExpr = RefExpr;
23784     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23785     if (Res.second)
23786       // It will be analyzed later.
23787       Vars.push_back(RefExpr);
23788     ValueDecl *D = Res.first;
23789     if (!D)
23790       continue;
23791 
23792     // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
23793     // A list-item cannot appear in more than one nontemporal clause.
23794     if (const Expr *PrevRef =
23795             DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
23796       Diag(ELoc, diag::err_omp_used_in_clause_twice)
23797           << 0 << getOpenMPClauseNameForDiag(OMPC_nontemporal) << ERange;
23798       Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23799           << getOpenMPClauseNameForDiag(OMPC_nontemporal);
23800       continue;
23801     }
23802 
23803     Vars.push_back(RefExpr);
23804   }
23805 
23806   if (Vars.empty())
23807     return nullptr;
23808 
23809   return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc,
23810                                       EndLoc, Vars);
23811 }
23812 
ActOnOpenMPScopeDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)23813 StmtResult SemaOpenMP::ActOnOpenMPScopeDirective(ArrayRef<OMPClause *> Clauses,
23814                                                  Stmt *AStmt,
23815                                                  SourceLocation StartLoc,
23816                                                  SourceLocation EndLoc) {
23817   if (!AStmt)
23818     return StmtError();
23819 
23820   SemaRef.setFunctionHasBranchProtectedScope();
23821 
23822   return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
23823                                    AStmt);
23824 }
23825 
ActOnOpenMPInclusiveClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)23826 OMPClause *SemaOpenMP::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
23827                                                   SourceLocation StartLoc,
23828                                                   SourceLocation LParenLoc,
23829                                                   SourceLocation EndLoc) {
23830   SmallVector<Expr *, 8> Vars;
23831   for (Expr *RefExpr : VarList) {
23832     assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23833     SourceLocation ELoc;
23834     SourceRange ERange;
23835     Expr *SimpleRefExpr = RefExpr;
23836     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23837                               /*AllowArraySection=*/true);
23838     if (Res.second)
23839       // It will be analyzed later.
23840       Vars.push_back(RefExpr);
23841     ValueDecl *D = Res.first;
23842     if (!D)
23843       continue;
23844 
23845     const DSAStackTy::DSAVarData DVar =
23846         DSAStack->getTopDSA(D, /*FromParent=*/true);
23847     // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23848     // A list item that appears in the inclusive or exclusive clause must appear
23849     // in a reduction clause with the inscan modifier on the enclosing
23850     // worksharing-loop, worksharing-loop SIMD, or simd construct.
23851     if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
23852       Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23853           << RefExpr->getSourceRange();
23854 
23855     if (DSAStack->getParentDirective() != OMPD_unknown)
23856       DSAStack->markDeclAsUsedInScanDirective(D);
23857     Vars.push_back(RefExpr);
23858   }
23859 
23860   if (Vars.empty())
23861     return nullptr;
23862 
23863   return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
23864                                     EndLoc, Vars);
23865 }
23866 
ActOnOpenMPExclusiveClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)23867 OMPClause *SemaOpenMP::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
23868                                                   SourceLocation StartLoc,
23869                                                   SourceLocation LParenLoc,
23870                                                   SourceLocation EndLoc) {
23871   SmallVector<Expr *, 8> Vars;
23872   for (Expr *RefExpr : VarList) {
23873     assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23874     SourceLocation ELoc;
23875     SourceRange ERange;
23876     Expr *SimpleRefExpr = RefExpr;
23877     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23878                               /*AllowArraySection=*/true);
23879     if (Res.second)
23880       // It will be analyzed later.
23881       Vars.push_back(RefExpr);
23882     ValueDecl *D = Res.first;
23883     if (!D)
23884       continue;
23885 
23886     OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
23887     DSAStackTy::DSAVarData DVar;
23888     if (ParentDirective != OMPD_unknown)
23889       DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
23890     // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23891     // A list item that appears in the inclusive or exclusive clause must appear
23892     // in a reduction clause with the inscan modifier on the enclosing
23893     // worksharing-loop, worksharing-loop SIMD, or simd construct.
23894     if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
23895         DVar.Modifier != OMPC_REDUCTION_inscan) {
23896       Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23897           << RefExpr->getSourceRange();
23898     } else {
23899       DSAStack->markDeclAsUsedInScanDirective(D);
23900     }
23901     Vars.push_back(RefExpr);
23902   }
23903 
23904   if (Vars.empty())
23905     return nullptr;
23906 
23907   return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
23908                                     EndLoc, Vars);
23909 }
23910 
23911 /// Tries to find omp_alloctrait_t type.
findOMPAlloctraitT(Sema & S,SourceLocation Loc,DSAStackTy * Stack)23912 static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
23913   QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
23914   if (!OMPAlloctraitT.isNull())
23915     return true;
23916   IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
23917   ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
23918   if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23919     S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
23920     return false;
23921   }
23922   Stack->setOMPAlloctraitT(PT.get());
23923   return true;
23924 }
23925 
ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc,ArrayRef<UsesAllocatorsData> Data)23926 OMPClause *SemaOpenMP::ActOnOpenMPUsesAllocatorClause(
23927     SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
23928     ArrayRef<UsesAllocatorsData> Data) {
23929   ASTContext &Context = getASTContext();
23930   // OpenMP [2.12.5, target Construct]
23931   // allocator is an identifier of omp_allocator_handle_t type.
23932   if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack))
23933     return nullptr;
23934   // OpenMP [2.12.5, target Construct]
23935   // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
23936   if (llvm::any_of(
23937           Data,
23938           [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
23939       !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack))
23940     return nullptr;
23941   llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
23942   for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
23943     auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
23944     StringRef Allocator =
23945         OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
23946     DeclarationName AllocatorName = &Context.Idents.get(Allocator);
23947     PredefinedAllocators.insert(SemaRef.LookupSingleName(
23948         SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
23949   }
23950 
23951   SmallVector<OMPUsesAllocatorsClause::Data, 4> NewData;
23952   for (const UsesAllocatorsData &D : Data) {
23953     Expr *AllocatorExpr = nullptr;
23954     // Check allocator expression.
23955     if (D.Allocator->isTypeDependent()) {
23956       AllocatorExpr = D.Allocator;
23957     } else {
23958       // Traits were specified - need to assign new allocator to the specified
23959       // allocator, so it must be an lvalue.
23960       AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
23961       auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
23962       bool IsPredefinedAllocator = false;
23963       if (DRE) {
23964         OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
23965             getAllocatorKind(SemaRef, DSAStack, AllocatorExpr);
23966         IsPredefinedAllocator =
23967             AllocatorTy !=
23968             OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
23969       }
23970       QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
23971       QualType AllocatorExprType = AllocatorExpr->getType();
23972       bool IsTypeCompatible = IsPredefinedAllocator;
23973       IsTypeCompatible = IsTypeCompatible ||
23974                          Context.hasSameUnqualifiedType(AllocatorExprType,
23975                                                         OMPAllocatorHandleT);
23976       IsTypeCompatible =
23977           IsTypeCompatible ||
23978           Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
23979       bool IsNonConstantLValue =
23980           !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
23981       if (!DRE || !IsTypeCompatible ||
23982           (!IsPredefinedAllocator && !IsNonConstantLValue)) {
23983         Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
23984             << "omp_allocator_handle_t" << (DRE ? 1 : 0)
23985             << AllocatorExpr->getType() << D.Allocator->getSourceRange();
23986         continue;
23987       }
23988       // OpenMP [2.12.5, target Construct]
23989       // Predefined allocators appearing in a uses_allocators clause cannot have
23990       // traits specified.
23991       if (IsPredefinedAllocator && D.AllocatorTraits) {
23992         Diag(D.AllocatorTraits->getExprLoc(),
23993              diag::err_omp_predefined_allocator_with_traits)
23994             << D.AllocatorTraits->getSourceRange();
23995         Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
23996             << cast<NamedDecl>(DRE->getDecl())->getName()
23997             << D.Allocator->getSourceRange();
23998         continue;
23999       }
24000       // OpenMP [2.12.5, target Construct]
24001       // Non-predefined allocators appearing in a uses_allocators clause must
24002       // have traits specified.
24003       if (!IsPredefinedAllocator && !D.AllocatorTraits) {
24004         Diag(D.Allocator->getExprLoc(),
24005              diag::err_omp_nonpredefined_allocator_without_traits);
24006         continue;
24007       }
24008       // No allocator traits - just convert it to rvalue.
24009       if (!D.AllocatorTraits)
24010         AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
24011       DSAStack->addUsesAllocatorsDecl(
24012           DRE->getDecl(),
24013           IsPredefinedAllocator
24014               ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
24015               : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
24016     }
24017     Expr *AllocatorTraitsExpr = nullptr;
24018     if (D.AllocatorTraits) {
24019       if (D.AllocatorTraits->isTypeDependent()) {
24020         AllocatorTraitsExpr = D.AllocatorTraits;
24021       } else {
24022         // OpenMP [2.12.5, target Construct]
24023         // Arrays that contain allocator traits that appear in a uses_allocators
24024         // clause must be constant arrays, have constant values and be defined
24025         // in the same scope as the construct in which the clause appears.
24026         AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
24027         // Check that traits expr is a constant array.
24028         QualType TraitTy;
24029         if (const ArrayType *Ty =
24030                 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
24031           if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
24032             TraitTy = ConstArrayTy->getElementType();
24033         if (TraitTy.isNull() ||
24034             !(Context.hasSameUnqualifiedType(TraitTy,
24035                                              DSAStack->getOMPAlloctraitT()) ||
24036               Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
24037                                          /*CompareUnqualified=*/true))) {
24038           Diag(D.AllocatorTraits->getExprLoc(),
24039                diag::err_omp_expected_array_alloctraits)
24040               << AllocatorTraitsExpr->getType();
24041           continue;
24042         }
24043         // Do not map by default allocator traits if it is a standalone
24044         // variable.
24045         if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
24046           DSAStack->addUsesAllocatorsDecl(
24047               DRE->getDecl(),
24048               DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
24049       }
24050     }
24051     OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
24052     NewD.Allocator = AllocatorExpr;
24053     NewD.AllocatorTraits = AllocatorTraitsExpr;
24054     NewD.LParenLoc = D.LParenLoc;
24055     NewD.RParenLoc = D.RParenLoc;
24056   }
24057   return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc,
24058                                          EndLoc, NewData);
24059 }
24060 
ActOnOpenMPAffinityClause(SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ColonLoc,SourceLocation EndLoc,Expr * Modifier,ArrayRef<Expr * > Locators)24061 OMPClause *SemaOpenMP::ActOnOpenMPAffinityClause(
24062     SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
24063     SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
24064   SmallVector<Expr *, 8> Vars;
24065   for (Expr *RefExpr : Locators) {
24066     assert(RefExpr && "NULL expr in OpenMP shared clause.");
24067     if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
24068       // It will be analyzed later.
24069       Vars.push_back(RefExpr);
24070       continue;
24071     }
24072 
24073     SourceLocation ELoc = RefExpr->getExprLoc();
24074     Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
24075 
24076     if (!SimpleExpr->isLValue()) {
24077       Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24078           << 1 << 0 << RefExpr->getSourceRange();
24079       continue;
24080     }
24081 
24082     ExprResult Res;
24083     {
24084       Sema::TentativeAnalysisScope Trap(SemaRef);
24085       Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
24086     }
24087     if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
24088         !isa<OMPArrayShapingExpr>(SimpleExpr)) {
24089       Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24090           << 1 << 0 << RefExpr->getSourceRange();
24091       continue;
24092     }
24093     Vars.push_back(SimpleExpr);
24094   }
24095 
24096   return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc,
24097                                    ColonLoc, EndLoc, Modifier, Vars);
24098 }
24099 
ActOnOpenMPBindClause(OpenMPBindClauseKind Kind,SourceLocation KindLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)24100 OMPClause *SemaOpenMP::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind,
24101                                              SourceLocation KindLoc,
24102                                              SourceLocation StartLoc,
24103                                              SourceLocation LParenLoc,
24104                                              SourceLocation EndLoc) {
24105   if (Kind == OMPC_BIND_unknown) {
24106     Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24107         << getListOfPossibleValues(OMPC_bind, /*First=*/0,
24108                                    /*Last=*/unsigned(OMPC_BIND_unknown))
24109         << getOpenMPClauseNameForDiag(OMPC_bind);
24110     return nullptr;
24111   }
24112 
24113   return OMPBindClause::Create(getASTContext(), Kind, KindLoc, StartLoc,
24114                                LParenLoc, EndLoc);
24115 }
24116 
ActOnOpenMPXDynCGroupMemClause(Expr * Size,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)24117 OMPClause *SemaOpenMP::ActOnOpenMPXDynCGroupMemClause(Expr *Size,
24118                                                       SourceLocation StartLoc,
24119                                                       SourceLocation LParenLoc,
24120                                                       SourceLocation EndLoc) {
24121   Expr *ValExpr = Size;
24122   Stmt *HelperValStmt = nullptr;
24123 
24124   // OpenMP [2.5, Restrictions]
24125   //  The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
24126   //  value.
24127   if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem,
24128                                  /*StrictlyPositive=*/false))
24129     return nullptr;
24130 
24131   OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24132   OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
24133       DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP);
24134   if (CaptureRegion != OMPD_unknown &&
24135       !SemaRef.CurContext->isDependentContext()) {
24136     ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
24137     llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24138     ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
24139     HelperValStmt = buildPreInits(getASTContext(), Captures);
24140   }
24141 
24142   return new (getASTContext()) OMPXDynCGroupMemClause(
24143       ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
24144 }
24145 
ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType,SourceLocation DepLoc,SourceLocation ColonLoc,ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)24146 OMPClause *SemaOpenMP::ActOnOpenMPDoacrossClause(
24147     OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc,
24148     SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
24149     SourceLocation LParenLoc, SourceLocation EndLoc) {
24150 
24151   if (DSAStack->getCurrentDirective() == OMPD_ordered &&
24152       DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
24153       DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
24154       DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
24155     Diag(DepLoc, diag::err_omp_unexpected_clause_value)
24156         << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_doacross);
24157     return nullptr;
24158   }
24159 
24160   SmallVector<Expr *, 8> Vars;
24161   DSAStackTy::OperatorOffsetTy OpsOffs;
24162   llvm::APSInt TotalDepCount(/*BitWidth=*/32);
24163   DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
24164       SemaRef,
24165       DepType == OMPC_DOACROSS_source ||
24166           DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
24167           DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
24168       VarList, DSAStack, EndLoc);
24169   Vars = VarOffset.Vars;
24170   OpsOffs = VarOffset.OpsOffs;
24171   TotalDepCount = VarOffset.TotalDepCount;
24172   auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc,
24173                                       EndLoc, DepType, DepLoc, ColonLoc, Vars,
24174                                       TotalDepCount.getZExtValue());
24175   if (DSAStack->isParentOrderedRegion())
24176     DSAStack->addDoacrossDependClause(C, OpsOffs);
24177   return C;
24178 }
24179 
ActOnOpenMPXAttributeClause(ArrayRef<const Attr * > Attrs,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)24180 OMPClause *SemaOpenMP::ActOnOpenMPXAttributeClause(ArrayRef<const Attr *> Attrs,
24181                                                    SourceLocation StartLoc,
24182                                                    SourceLocation LParenLoc,
24183                                                    SourceLocation EndLoc) {
24184   return new (getASTContext())
24185       OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
24186 }
24187 
ActOnOpenMPXBareClause(SourceLocation StartLoc,SourceLocation EndLoc)24188 OMPClause *SemaOpenMP::ActOnOpenMPXBareClause(SourceLocation StartLoc,
24189                                               SourceLocation EndLoc) {
24190   return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
24191 }
24192 
ActOnOpenMPHoldsClause(Expr * E,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)24193 OMPClause *SemaOpenMP::ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc,
24194                                               SourceLocation LParenLoc,
24195                                               SourceLocation EndLoc) {
24196   return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
24197 }
24198 
ActOnOpenMPDirectivePresenceClause(OpenMPClauseKind CK,llvm::ArrayRef<OpenMPDirectiveKind> DKVec,SourceLocation Loc,SourceLocation LLoc,SourceLocation RLoc)24199 OMPClause *SemaOpenMP::ActOnOpenMPDirectivePresenceClause(
24200     OpenMPClauseKind CK, llvm::ArrayRef<OpenMPDirectiveKind> DKVec,
24201     SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc) {
24202   switch (CK) {
24203   case OMPC_absent:
24204     return OMPAbsentClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
24205   case OMPC_contains:
24206     return OMPContainsClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
24207   default:
24208     llvm_unreachable("Unexpected OpenMP clause");
24209   }
24210 }
24211 
ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK,SourceLocation Loc,SourceLocation RLoc)24212 OMPClause *SemaOpenMP::ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK,
24213                                                           SourceLocation Loc,
24214                                                           SourceLocation RLoc) {
24215   switch (CK) {
24216   case OMPC_no_openmp:
24217     return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
24218   case OMPC_no_openmp_routines:
24219     return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
24220   case OMPC_no_parallelism:
24221     return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
24222   case OMPC_no_openmp_constructs:
24223     return new (getASTContext()) OMPNoOpenMPConstructsClause(Loc, RLoc);
24224   default:
24225     llvm_unreachable("Unexpected OpenMP clause");
24226   }
24227 }
24228 
ActOnOMPArraySectionExpr(Expr * Base,SourceLocation LBLoc,Expr * LowerBound,SourceLocation ColonLocFirst,SourceLocation ColonLocSecond,Expr * Length,Expr * Stride,SourceLocation RBLoc)24229 ExprResult SemaOpenMP::ActOnOMPArraySectionExpr(
24230     Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
24231     SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
24232     Expr *Stride, SourceLocation RBLoc) {
24233   ASTContext &Context = getASTContext();
24234   if (Base->hasPlaceholderType() &&
24235       !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
24236     ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
24237     if (Result.isInvalid())
24238       return ExprError();
24239     Base = Result.get();
24240   }
24241   if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
24242     ExprResult Result = SemaRef.CheckPlaceholderExpr(LowerBound);
24243     if (Result.isInvalid())
24244       return ExprError();
24245     Result = SemaRef.DefaultLvalueConversion(Result.get());
24246     if (Result.isInvalid())
24247       return ExprError();
24248     LowerBound = Result.get();
24249   }
24250   if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
24251     ExprResult Result = SemaRef.CheckPlaceholderExpr(Length);
24252     if (Result.isInvalid())
24253       return ExprError();
24254     Result = SemaRef.DefaultLvalueConversion(Result.get());
24255     if (Result.isInvalid())
24256       return ExprError();
24257     Length = Result.get();
24258   }
24259   if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
24260     ExprResult Result = SemaRef.CheckPlaceholderExpr(Stride);
24261     if (Result.isInvalid())
24262       return ExprError();
24263     Result = SemaRef.DefaultLvalueConversion(Result.get());
24264     if (Result.isInvalid())
24265       return ExprError();
24266     Stride = Result.get();
24267   }
24268 
24269   // Build an unanalyzed expression if either operand is type-dependent.
24270   if (Base->isTypeDependent() ||
24271       (LowerBound &&
24272        (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
24273       (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
24274       (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
24275     return new (Context) ArraySectionExpr(
24276         Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
24277         OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
24278   }
24279 
24280   // Perform default conversions.
24281   QualType OriginalTy = ArraySectionExpr::getBaseOriginalType(Base);
24282   QualType ResultTy;
24283   if (OriginalTy->isAnyPointerType()) {
24284     ResultTy = OriginalTy->getPointeeType();
24285   } else if (OriginalTy->isArrayType()) {
24286     ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
24287   } else {
24288     return ExprError(
24289         Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
24290         << Base->getSourceRange());
24291   }
24292   // C99 6.5.2.1p1
24293   if (LowerBound) {
24294     auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
24295                                                       LowerBound);
24296     if (Res.isInvalid())
24297       return ExprError(Diag(LowerBound->getExprLoc(),
24298                             diag::err_omp_typecheck_section_not_integer)
24299                        << 0 << LowerBound->getSourceRange());
24300     LowerBound = Res.get();
24301 
24302     if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
24303         LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
24304       Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
24305           << 0 << LowerBound->getSourceRange();
24306   }
24307   if (Length) {
24308     auto Res =
24309         PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
24310     if (Res.isInvalid())
24311       return ExprError(Diag(Length->getExprLoc(),
24312                             diag::err_omp_typecheck_section_not_integer)
24313                        << 1 << Length->getSourceRange());
24314     Length = Res.get();
24315 
24316     if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
24317         Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
24318       Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
24319           << 1 << Length->getSourceRange();
24320   }
24321   if (Stride) {
24322     ExprResult Res =
24323         PerformOpenMPImplicitIntegerConversion(Stride->getExprLoc(), Stride);
24324     if (Res.isInvalid())
24325       return ExprError(Diag(Stride->getExprLoc(),
24326                             diag::err_omp_typecheck_section_not_integer)
24327                        << 1 << Stride->getSourceRange());
24328     Stride = Res.get();
24329 
24330     if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
24331         Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
24332       Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
24333           << 1 << Stride->getSourceRange();
24334   }
24335 
24336   // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
24337   // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
24338   // type. Note that functions are not objects, and that (in C99 parlance)
24339   // incomplete types are not object types.
24340   if (ResultTy->isFunctionType()) {
24341     Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
24342         << ResultTy << Base->getSourceRange();
24343     return ExprError();
24344   }
24345 
24346   if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
24347                                   diag::err_omp_section_incomplete_type, Base))
24348     return ExprError();
24349 
24350   if (LowerBound && !OriginalTy->isAnyPointerType()) {
24351     Expr::EvalResult Result;
24352     if (LowerBound->EvaluateAsInt(Result, Context)) {
24353       // OpenMP 5.0, [2.1.5 Array Sections]
24354       // The array section must be a subset of the original array.
24355       llvm::APSInt LowerBoundValue = Result.Val.getInt();
24356       if (LowerBoundValue.isNegative()) {
24357         Diag(LowerBound->getExprLoc(),
24358              diag::err_omp_section_not_subset_of_array)
24359             << LowerBound->getSourceRange();
24360         return ExprError();
24361       }
24362     }
24363   }
24364 
24365   if (Length) {
24366     Expr::EvalResult Result;
24367     if (Length->EvaluateAsInt(Result, Context)) {
24368       // OpenMP 5.0, [2.1.5 Array Sections]
24369       // The length must evaluate to non-negative integers.
24370       llvm::APSInt LengthValue = Result.Val.getInt();
24371       if (LengthValue.isNegative()) {
24372         Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
24373             << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
24374             << Length->getSourceRange();
24375         return ExprError();
24376       }
24377     }
24378   } else if (ColonLocFirst.isValid() &&
24379              (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
24380                                       !OriginalTy->isVariableArrayType()))) {
24381     // OpenMP 5.0, [2.1.5 Array Sections]
24382     // When the size of the array dimension is not known, the length must be
24383     // specified explicitly.
24384     Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
24385         << (!OriginalTy.isNull() && OriginalTy->isArrayType());
24386     return ExprError();
24387   }
24388 
24389   if (Stride) {
24390     Expr::EvalResult Result;
24391     if (Stride->EvaluateAsInt(Result, Context)) {
24392       // OpenMP 5.0, [2.1.5 Array Sections]
24393       // The stride must evaluate to a positive integer.
24394       llvm::APSInt StrideValue = Result.Val.getInt();
24395       if (!StrideValue.isStrictlyPositive()) {
24396         Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
24397             << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
24398             << Stride->getSourceRange();
24399         return ExprError();
24400       }
24401     }
24402   }
24403 
24404   if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
24405     ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(Base);
24406     if (Result.isInvalid())
24407       return ExprError();
24408     Base = Result.get();
24409   }
24410   return new (Context) ArraySectionExpr(
24411       Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
24412       OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
24413 }
24414 
ActOnOMPArrayShapingExpr(Expr * Base,SourceLocation LParenLoc,SourceLocation RParenLoc,ArrayRef<Expr * > Dims,ArrayRef<SourceRange> Brackets)24415 ExprResult SemaOpenMP::ActOnOMPArrayShapingExpr(
24416     Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
24417     ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
24418   ASTContext &Context = getASTContext();
24419   if (Base->hasPlaceholderType()) {
24420     ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
24421     if (Result.isInvalid())
24422       return ExprError();
24423     Result = SemaRef.DefaultLvalueConversion(Result.get());
24424     if (Result.isInvalid())
24425       return ExprError();
24426     Base = Result.get();
24427   }
24428   QualType BaseTy = Base->getType();
24429   // Delay analysis of the types/expressions if instantiation/specialization is
24430   // required.
24431   if (!BaseTy->isPointerType() && Base->isTypeDependent())
24432     return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
24433                                        LParenLoc, RParenLoc, Dims, Brackets);
24434   if (!BaseTy->isPointerType() ||
24435       (!Base->isTypeDependent() &&
24436        BaseTy->getPointeeType()->isIncompleteType()))
24437     return ExprError(Diag(Base->getExprLoc(),
24438                           diag::err_omp_non_pointer_type_array_shaping_base)
24439                      << Base->getSourceRange());
24440 
24441   SmallVector<Expr *, 4> NewDims;
24442   bool ErrorFound = false;
24443   for (Expr *Dim : Dims) {
24444     if (Dim->hasPlaceholderType()) {
24445       ExprResult Result = SemaRef.CheckPlaceholderExpr(Dim);
24446       if (Result.isInvalid()) {
24447         ErrorFound = true;
24448         continue;
24449       }
24450       Result = SemaRef.DefaultLvalueConversion(Result.get());
24451       if (Result.isInvalid()) {
24452         ErrorFound = true;
24453         continue;
24454       }
24455       Dim = Result.get();
24456     }
24457     if (!Dim->isTypeDependent()) {
24458       ExprResult Result =
24459           PerformOpenMPImplicitIntegerConversion(Dim->getExprLoc(), Dim);
24460       if (Result.isInvalid()) {
24461         ErrorFound = true;
24462         Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
24463             << Dim->getSourceRange();
24464         continue;
24465       }
24466       Dim = Result.get();
24467       Expr::EvalResult EvResult;
24468       if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
24469         // OpenMP 5.0, [2.1.4 Array Shaping]
24470         // Each si is an integral type expression that must evaluate to a
24471         // positive integer.
24472         llvm::APSInt Value = EvResult.Val.getInt();
24473         if (!Value.isStrictlyPositive()) {
24474           Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
24475               << toString(Value, /*Radix=*/10, /*Signed=*/true)
24476               << Dim->getSourceRange();
24477           ErrorFound = true;
24478           continue;
24479         }
24480       }
24481     }
24482     NewDims.push_back(Dim);
24483   }
24484   if (ErrorFound)
24485     return ExprError();
24486   return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
24487                                      LParenLoc, RParenLoc, NewDims, Brackets);
24488 }
24489 
ActOnOMPIteratorExpr(Scope * S,SourceLocation IteratorKwLoc,SourceLocation LLoc,SourceLocation RLoc,ArrayRef<OMPIteratorData> Data)24490 ExprResult SemaOpenMP::ActOnOMPIteratorExpr(Scope *S,
24491                                             SourceLocation IteratorKwLoc,
24492                                             SourceLocation LLoc,
24493                                             SourceLocation RLoc,
24494                                             ArrayRef<OMPIteratorData> Data) {
24495   ASTContext &Context = getASTContext();
24496   SmallVector<OMPIteratorExpr::IteratorDefinition, 4> ID;
24497   bool IsCorrect = true;
24498   for (const OMPIteratorData &D : Data) {
24499     TypeSourceInfo *TInfo = nullptr;
24500     SourceLocation StartLoc;
24501     QualType DeclTy;
24502     if (!D.Type.getAsOpaquePtr()) {
24503       // OpenMP 5.0, 2.1.6 Iterators
24504       // In an iterator-specifier, if the iterator-type is not specified then
24505       // the type of that iterator is of int type.
24506       DeclTy = Context.IntTy;
24507       StartLoc = D.DeclIdentLoc;
24508     } else {
24509       DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo);
24510       StartLoc = TInfo->getTypeLoc().getBeginLoc();
24511     }
24512 
24513     bool IsDeclTyDependent = DeclTy->isDependentType() ||
24514                              DeclTy->containsUnexpandedParameterPack() ||
24515                              DeclTy->isInstantiationDependentType();
24516     if (!IsDeclTyDependent) {
24517       if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
24518         // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
24519         // The iterator-type must be an integral or pointer type.
24520         Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
24521             << DeclTy;
24522         IsCorrect = false;
24523         continue;
24524       }
24525       if (DeclTy.isConstant(Context)) {
24526         // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
24527         // The iterator-type must not be const qualified.
24528         Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
24529             << DeclTy;
24530         IsCorrect = false;
24531         continue;
24532       }
24533     }
24534 
24535     // Iterator declaration.
24536     assert(D.DeclIdent && "Identifier expected.");
24537     // Always try to create iterator declarator to avoid extra error messages
24538     // about unknown declarations use.
24539     auto *VD =
24540         VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc,
24541                         D.DeclIdent, DeclTy, TInfo, SC_None);
24542     VD->setImplicit();
24543     if (S) {
24544       // Check for conflicting previous declaration.
24545       DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
24546       LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName,
24547                             RedeclarationKind::ForVisibleRedeclaration);
24548       Previous.suppressDiagnostics();
24549       SemaRef.LookupName(Previous, S);
24550 
24551       SemaRef.FilterLookupForScope(Previous, SemaRef.CurContext, S,
24552                                    /*ConsiderLinkage=*/false,
24553                                    /*AllowInlineNamespace=*/false);
24554       if (!Previous.empty()) {
24555         NamedDecl *Old = Previous.getRepresentativeDecl();
24556         Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
24557         Diag(Old->getLocation(), diag::note_previous_definition);
24558       } else {
24559         SemaRef.PushOnScopeChains(VD, S);
24560       }
24561     } else {
24562       SemaRef.CurContext->addDecl(VD);
24563     }
24564 
24565     /// Act on the iterator variable declaration.
24566     ActOnOpenMPIteratorVarDecl(VD);
24567 
24568     Expr *Begin = D.Range.Begin;
24569     if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
24570       ExprResult BeginRes = SemaRef.PerformImplicitConversion(
24571           Begin, DeclTy, AssignmentAction::Converting);
24572       Begin = BeginRes.get();
24573     }
24574     Expr *End = D.Range.End;
24575     if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
24576       ExprResult EndRes = SemaRef.PerformImplicitConversion(
24577           End, DeclTy, AssignmentAction::Converting);
24578       End = EndRes.get();
24579     }
24580     Expr *Step = D.Range.Step;
24581     if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
24582       if (!Step->getType()->isIntegralType(Context)) {
24583         Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
24584             << Step << Step->getSourceRange();
24585         IsCorrect = false;
24586         continue;
24587       }
24588       std::optional<llvm::APSInt> Result =
24589           Step->getIntegerConstantExpr(Context);
24590       // OpenMP 5.0, 2.1.6 Iterators, Restrictions
24591       // If the step expression of a range-specification equals zero, the
24592       // behavior is unspecified.
24593       if (Result && Result->isZero()) {
24594         Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
24595             << Step << Step->getSourceRange();
24596         IsCorrect = false;
24597         continue;
24598       }
24599     }
24600     if (!Begin || !End || !IsCorrect) {
24601       IsCorrect = false;
24602       continue;
24603     }
24604     OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
24605     IDElem.IteratorDecl = VD;
24606     IDElem.AssignmentLoc = D.AssignLoc;
24607     IDElem.Range.Begin = Begin;
24608     IDElem.Range.End = End;
24609     IDElem.Range.Step = Step;
24610     IDElem.ColonLoc = D.ColonLoc;
24611     IDElem.SecondColonLoc = D.SecColonLoc;
24612   }
24613   if (!IsCorrect) {
24614     // Invalidate all created iterator declarations if error is found.
24615     for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
24616       if (Decl *ID = D.IteratorDecl)
24617         ID->setInvalidDecl();
24618     }
24619     return ExprError();
24620   }
24621   SmallVector<OMPIteratorHelperData, 4> Helpers;
24622   if (!SemaRef.CurContext->isDependentContext()) {
24623     // Build number of ityeration for each iteration range.
24624     // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
24625     // ((Begini-Stepi-1-Endi) / -Stepi);
24626     for (OMPIteratorExpr::IteratorDefinition &D : ID) {
24627       // (Endi - Begini)
24628       ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub,
24629                                                   D.Range.End, D.Range.Begin);
24630       if (!Res.isUsable()) {
24631         IsCorrect = false;
24632         continue;
24633       }
24634       ExprResult St, St1;
24635       if (D.Range.Step) {
24636         St = D.Range.Step;
24637         // (Endi - Begini) + Stepi
24638         Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(),
24639                                          St.get());
24640         if (!Res.isUsable()) {
24641           IsCorrect = false;
24642           continue;
24643         }
24644         // (Endi - Begini) + Stepi - 1
24645         Res = SemaRef.CreateBuiltinBinOp(
24646             D.AssignmentLoc, BO_Sub, Res.get(),
24647             SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
24648         if (!Res.isUsable()) {
24649           IsCorrect = false;
24650           continue;
24651         }
24652         // ((Endi - Begini) + Stepi - 1) / Stepi
24653         Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(),
24654                                          St.get());
24655         if (!Res.isUsable()) {
24656           IsCorrect = false;
24657           continue;
24658         }
24659         St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
24660                                            D.Range.Step);
24661         // (Begini - Endi)
24662         ExprResult Res1 = SemaRef.CreateBuiltinBinOp(
24663             D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
24664         if (!Res1.isUsable()) {
24665           IsCorrect = false;
24666           continue;
24667         }
24668         // (Begini - Endi) - Stepi
24669         Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(),
24670                                           St1.get());
24671         if (!Res1.isUsable()) {
24672           IsCorrect = false;
24673           continue;
24674         }
24675         // (Begini - Endi) - Stepi - 1
24676         Res1 = SemaRef.CreateBuiltinBinOp(
24677             D.AssignmentLoc, BO_Sub, Res1.get(),
24678             SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
24679         if (!Res1.isUsable()) {
24680           IsCorrect = false;
24681           continue;
24682         }
24683         // ((Begini - Endi) - Stepi - 1) / (-Stepi)
24684         Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(),
24685                                           St1.get());
24686         if (!Res1.isUsable()) {
24687           IsCorrect = false;
24688           continue;
24689         }
24690         // Stepi > 0.
24691         ExprResult CmpRes = SemaRef.CreateBuiltinBinOp(
24692             D.AssignmentLoc, BO_GT, D.Range.Step,
24693             SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
24694         if (!CmpRes.isUsable()) {
24695           IsCorrect = false;
24696           continue;
24697         }
24698         Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
24699                                          CmpRes.get(), Res.get(), Res1.get());
24700         if (!Res.isUsable()) {
24701           IsCorrect = false;
24702           continue;
24703         }
24704       }
24705       Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false);
24706       if (!Res.isUsable()) {
24707         IsCorrect = false;
24708         continue;
24709       }
24710 
24711       // Build counter update.
24712       // Build counter.
24713       auto *CounterVD = VarDecl::Create(Context, SemaRef.CurContext,
24714                                         D.IteratorDecl->getBeginLoc(),
24715                                         D.IteratorDecl->getBeginLoc(), nullptr,
24716                                         Res.get()->getType(), nullptr, SC_None);
24717       CounterVD->setImplicit();
24718       ExprResult RefRes =
24719           SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue,
24720                                    D.IteratorDecl->getBeginLoc());
24721       // Build counter update.
24722       // I = Begini + counter * Stepi;
24723       ExprResult UpdateRes;
24724       if (D.Range.Step) {
24725         UpdateRes = SemaRef.CreateBuiltinBinOp(
24726             D.AssignmentLoc, BO_Mul,
24727             SemaRef.DefaultLvalueConversion(RefRes.get()).get(), St.get());
24728       } else {
24729         UpdateRes = SemaRef.DefaultLvalueConversion(RefRes.get());
24730       }
24731       if (!UpdateRes.isUsable()) {
24732         IsCorrect = false;
24733         continue;
24734       }
24735       UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
24736                                              D.Range.Begin, UpdateRes.get());
24737       if (!UpdateRes.isUsable()) {
24738         IsCorrect = false;
24739         continue;
24740       }
24741       ExprResult VDRes =
24742           SemaRef.BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl),
24743                                    cast<VarDecl>(D.IteratorDecl)->getType(),
24744                                    VK_LValue, D.IteratorDecl->getBeginLoc());
24745       UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
24746                                              VDRes.get(), UpdateRes.get());
24747       if (!UpdateRes.isUsable()) {
24748         IsCorrect = false;
24749         continue;
24750       }
24751       UpdateRes =
24752           SemaRef.ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true);
24753       if (!UpdateRes.isUsable()) {
24754         IsCorrect = false;
24755         continue;
24756       }
24757       ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
24758           D.AssignmentLoc, UO_PreInc, RefRes.get());
24759       if (!CounterUpdateRes.isUsable()) {
24760         IsCorrect = false;
24761         continue;
24762       }
24763       CounterUpdateRes = SemaRef.ActOnFinishFullExpr(CounterUpdateRes.get(),
24764                                                      /*DiscardedValue=*/true);
24765       if (!CounterUpdateRes.isUsable()) {
24766         IsCorrect = false;
24767         continue;
24768       }
24769       OMPIteratorHelperData &HD = Helpers.emplace_back();
24770       HD.CounterVD = CounterVD;
24771       HD.Upper = Res.get();
24772       HD.Update = UpdateRes.get();
24773       HD.CounterUpdate = CounterUpdateRes.get();
24774     }
24775   } else {
24776     Helpers.assign(ID.size(), {});
24777   }
24778   if (!IsCorrect) {
24779     // Invalidate all created iterator declarations if error is found.
24780     for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
24781       if (Decl *ID = D.IteratorDecl)
24782         ID->setInvalidDecl();
24783     }
24784     return ExprError();
24785   }
24786   return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc,
24787                                  LLoc, RLoc, ID, Helpers);
24788 }
24789 
24790 /// Check if \p AssumptionStr is a known assumption and warn if not.
checkOMPAssumeAttr(Sema & S,SourceLocation Loc,StringRef AssumptionStr)24791 static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc,
24792                                StringRef AssumptionStr) {
24793   if (llvm::KnownAssumptionStrings.count(AssumptionStr))
24794     return;
24795 
24796   unsigned BestEditDistance = 3;
24797   StringRef Suggestion;
24798   for (const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) {
24799     unsigned EditDistance =
24800         AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
24801     if (EditDistance < BestEditDistance) {
24802       Suggestion = KnownAssumptionIt.getKey();
24803       BestEditDistance = EditDistance;
24804     }
24805   }
24806 
24807   if (!Suggestion.empty())
24808     S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
24809         << AssumptionStr << Suggestion;
24810   else
24811     S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
24812         << AssumptionStr;
24813 }
24814 
handleOMPAssumeAttr(Decl * D,const ParsedAttr & AL)24815 void SemaOpenMP::handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL) {
24816   // Handle the case where the attribute has a text message.
24817   StringRef Str;
24818   SourceLocation AttrStrLoc;
24819   if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
24820     return;
24821 
24822   checkOMPAssumeAttr(SemaRef, AttrStrLoc, Str);
24823 
24824   D->addAttr(::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
24825 }
24826 
SemaOpenMP(Sema & S)24827 SemaOpenMP::SemaOpenMP(Sema &S)
24828     : SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
24829