xref: /freebsd/contrib/llvm-project/clang/lib/Sema/SemaOpenMP.cpp (revision 62987288060ff68c817b7056815aa9fb8ba8ecd7)
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/OpenMPClause.h"
24 #include "clang/AST/StmtCXX.h"
25 #include "clang/AST/StmtOpenMP.h"
26 #include "clang/AST/StmtVisitor.h"
27 #include "clang/AST/TypeOrdering.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 "clang/Sema/SemaInternal.h"
40 #include "llvm/ADT/IndexedMap.h"
41 #include "llvm/ADT/PointerEmbeddedInt.h"
42 #include "llvm/ADT/STLExtras.h"
43 #include "llvm/ADT/Sequence.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 #include <set>
51 
52 using namespace clang;
53 using namespace llvm::omp;
54 
55 //===----------------------------------------------------------------------===//
56 // Stack of data-sharing attributes for variables
57 //===----------------------------------------------------------------------===//
58 
59 static const Expr *checkMapClauseExpressionBase(
60     Sema &SemaRef, Expr *E,
61     OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
62     OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
63 
64 namespace {
65 /// Default data sharing attributes, which can be applied to directive.
66 enum DefaultDataSharingAttributes {
67   DSA_unspecified = 0,       /// Data sharing attribute not specified.
68   DSA_none = 1 << 0,         /// Default data sharing attribute 'none'.
69   DSA_shared = 1 << 1,       /// Default data sharing attribute 'shared'.
70   DSA_private = 1 << 2,      /// Default data sharing attribute 'private'.
71   DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
72 };
73 
74 /// Stack for tracking declarations used in OpenMP directives and
75 /// clauses and their data-sharing attributes.
76 class DSAStackTy {
77 public:
78   struct DSAVarData {
79     OpenMPDirectiveKind DKind = OMPD_unknown;
80     OpenMPClauseKind CKind = OMPC_unknown;
81     unsigned Modifier = 0;
82     const Expr *RefExpr = nullptr;
83     DeclRefExpr *PrivateCopy = nullptr;
84     SourceLocation ImplicitDSALoc;
85     bool AppliedToPointee = false;
86     DSAVarData() = default;
DSAVarData__anon1dd12e440111::DSAStackTy::DSAVarData87     DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
88                const Expr *RefExpr, DeclRefExpr *PrivateCopy,
89                SourceLocation ImplicitDSALoc, unsigned Modifier,
90                bool AppliedToPointee)
91         : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
92           PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
93           AppliedToPointee(AppliedToPointee) {}
94   };
95   using OperatorOffsetTy =
96       llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
97   using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
98   /// Kind of the declaration used in the uses_allocators clauses.
99   enum class UsesAllocatorsDeclKind {
100     /// Predefined allocator
101     PredefinedAllocator,
102     /// User-defined allocator
103     UserDefinedAllocator,
104     /// The declaration that represent allocator trait
105     AllocatorTrait,
106   };
107 
108 private:
109   struct DSAInfo {
110     OpenMPClauseKind Attributes = OMPC_unknown;
111     unsigned Modifier = 0;
112     /// Pointer to a reference expression and a flag which shows that the
113     /// variable is marked as lastprivate(true) or not (false).
114     llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
115     DeclRefExpr *PrivateCopy = nullptr;
116     /// true if the attribute is applied to the pointee, not the variable
117     /// itself.
118     bool AppliedToPointee = false;
119   };
120   using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
121   using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
122   using LCDeclInfo = std::pair<unsigned, VarDecl *>;
123   using LoopControlVariablesMapTy =
124       llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
125   /// Struct that associates a component with the clause kind where they are
126   /// found.
127   struct MappedExprComponentTy {
128     OMPClauseMappableExprCommon::MappableExprComponentLists Components;
129     OpenMPClauseKind Kind = OMPC_unknown;
130   };
131   using MappedExprComponentsTy =
132       llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
133   using CriticalsWithHintsTy =
134       llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
135   struct ReductionData {
136     using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
137     SourceRange ReductionRange;
138     llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
139     ReductionData() = default;
set__anon1dd12e440111::DSAStackTy::ReductionData140     void set(BinaryOperatorKind BO, SourceRange RR) {
141       ReductionRange = RR;
142       ReductionOp = BO;
143     }
set__anon1dd12e440111::DSAStackTy::ReductionData144     void set(const Expr *RefExpr, SourceRange RR) {
145       ReductionRange = RR;
146       ReductionOp = RefExpr;
147     }
148   };
149   using DeclReductionMapTy =
150       llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
151   struct DefaultmapInfo {
152     OpenMPDefaultmapClauseModifier ImplicitBehavior =
153         OMPC_DEFAULTMAP_MODIFIER_unknown;
154     SourceLocation SLoc;
155     DefaultmapInfo() = default;
DefaultmapInfo__anon1dd12e440111::DSAStackTy::DefaultmapInfo156     DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc)
157         : ImplicitBehavior(M), SLoc(Loc) {}
158   };
159 
160   struct SharingMapTy {
161     DeclSAMapTy SharingMap;
162     DeclReductionMapTy ReductionMap;
163     UsedRefMapTy AlignedMap;
164     UsedRefMapTy NontemporalMap;
165     MappedExprComponentsTy MappedExprComponents;
166     LoopControlVariablesMapTy LCVMap;
167     DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
168     SourceLocation DefaultAttrLoc;
169     DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1];
170     OpenMPDirectiveKind Directive = OMPD_unknown;
171     /// GenericLoopDirective with bind clause is mapped to other directives,
172     /// like for, distribute and simd. Presently, set MappedDirective to
173     /// OMPLoop. This may also be used in a similar way for other constructs.
174     OpenMPDirectiveKind MappedDirective = OMPD_unknown;
175     DeclarationNameInfo DirectiveName;
176     Scope *CurScope = nullptr;
177     DeclContext *Context = nullptr;
178     SourceLocation ConstructLoc;
179     /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
180     /// get the data (loop counters etc.) about enclosing loop-based construct.
181     /// This data is required during codegen.
182     DoacrossClauseMapTy DoacrossDepends;
183     /// First argument (Expr *) contains optional argument of the
184     /// 'ordered' clause, the second one is true if the regions has 'ordered'
185     /// clause, false otherwise.
186     std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
187     bool RegionHasOrderConcurrent = false;
188     unsigned AssociatedLoops = 1;
189     bool HasMutipleLoops = false;
190     const Decl *PossiblyLoopCounter = nullptr;
191     bool NowaitRegion = false;
192     bool UntiedRegion = false;
193     bool CancelRegion = false;
194     bool LoopStart = false;
195     bool BodyComplete = false;
196     SourceLocation PrevScanLocation;
197     SourceLocation PrevOrderedLocation;
198     SourceLocation InnerTeamsRegionLoc;
199     /// Reference to the taskgroup task_reduction reference expression.
200     Expr *TaskgroupReductionRef = nullptr;
201     llvm::DenseSet<QualType> MappedClassesQualTypes;
202     SmallVector<Expr *, 4> InnerUsedAllocators;
203     llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
204     /// List of globals marked as declare target link in this target region
205     /// (isOpenMPTargetExecutionDirective(Directive) == true).
206     llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
207     /// List of decls used in inclusive/exclusive clauses of the scan directive.
208     llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
209     llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
210         UsesAllocatorsDecls;
211     /// Data is required on creating capture fields for implicit
212     /// default first|private clause.
213     struct ImplicitDefaultFDInfoTy {
214       /// Field decl.
215       const FieldDecl *FD = nullptr;
216       /// Nesting stack level
217       size_t StackLevel = 0;
218       /// Capture variable decl.
219       VarDecl *VD = nullptr;
ImplicitDefaultFDInfoTy__anon1dd12e440111::DSAStackTy::SharingMapTy::ImplicitDefaultFDInfoTy220       ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
221                               VarDecl *VD)
222           : FD(FD), StackLevel(StackLevel), VD(VD) {}
223     };
224     /// List of captured fields
225     llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
226         ImplicitDefaultFirstprivateFDs;
227     Expr *DeclareMapperVar = nullptr;
228     SmallVector<VarDecl *, 16> IteratorVarDecls;
SharingMapTy__anon1dd12e440111::DSAStackTy::SharingMapTy229     SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
230                  Scope *CurScope, SourceLocation Loc)
231         : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
232           ConstructLoc(Loc) {}
233     SharingMapTy() = default;
234   };
235 
236   using StackTy = SmallVector<SharingMapTy, 4>;
237 
238   /// Stack of used declaration and their data-sharing attributes.
239   DeclSAMapTy Threadprivates;
240   const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
241   SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
242   /// true, if check for DSA must be from parent directive, false, if
243   /// from current directive.
244   OpenMPClauseKind ClauseKindMode = OMPC_unknown;
245   Sema &SemaRef;
246   bool ForceCapturing = false;
247   /// true if all the variables in the target executable directives must be
248   /// captured by reference.
249   bool ForceCaptureByReferenceInTargetExecutable = false;
250   CriticalsWithHintsTy Criticals;
251   unsigned IgnoredStackElements = 0;
252 
253   /// Iterators over the stack iterate in order from innermost to outermost
254   /// directive.
255   using const_iterator = StackTy::const_reverse_iterator;
begin() const256   const_iterator begin() const {
257     return Stack.empty() ? const_iterator()
258                          : Stack.back().first.rbegin() + IgnoredStackElements;
259   }
end() const260   const_iterator end() const {
261     return Stack.empty() ? const_iterator() : Stack.back().first.rend();
262   }
263   using iterator = StackTy::reverse_iterator;
begin()264   iterator begin() {
265     return Stack.empty() ? iterator()
266                          : Stack.back().first.rbegin() + IgnoredStackElements;
267   }
end()268   iterator end() {
269     return Stack.empty() ? iterator() : Stack.back().first.rend();
270   }
271 
272   // Convenience operations to get at the elements of the stack.
273 
isStackEmpty() const274   bool isStackEmpty() const {
275     return Stack.empty() ||
276            Stack.back().second != CurrentNonCapturingFunctionScope ||
277            Stack.back().first.size() <= IgnoredStackElements;
278   }
getStackSize() const279   size_t getStackSize() const {
280     return isStackEmpty() ? 0
281                           : Stack.back().first.size() - IgnoredStackElements;
282   }
283 
getTopOfStackOrNull()284   SharingMapTy *getTopOfStackOrNull() {
285     size_t Size = getStackSize();
286     if (Size == 0)
287       return nullptr;
288     return &Stack.back().first[Size - 1];
289   }
getTopOfStackOrNull() const290   const SharingMapTy *getTopOfStackOrNull() const {
291     return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
292   }
getTopOfStack()293   SharingMapTy &getTopOfStack() {
294     assert(!isStackEmpty() && "no current directive");
295     return *getTopOfStackOrNull();
296   }
getTopOfStack() const297   const SharingMapTy &getTopOfStack() const {
298     return const_cast<DSAStackTy &>(*this).getTopOfStack();
299   }
300 
getSecondOnStackOrNull()301   SharingMapTy *getSecondOnStackOrNull() {
302     size_t Size = getStackSize();
303     if (Size <= 1)
304       return nullptr;
305     return &Stack.back().first[Size - 2];
306   }
getSecondOnStackOrNull() const307   const SharingMapTy *getSecondOnStackOrNull() const {
308     return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
309   }
310 
311   /// Get the stack element at a certain level (previously returned by
312   /// \c getNestingLevel).
313   ///
314   /// Note that nesting levels count from outermost to innermost, and this is
315   /// the reverse of our iteration order where new inner levels are pushed at
316   /// the front of the stack.
getStackElemAtLevel(unsigned Level)317   SharingMapTy &getStackElemAtLevel(unsigned Level) {
318     assert(Level < getStackSize() && "no such stack element");
319     return Stack.back().first[Level];
320   }
getStackElemAtLevel(unsigned Level) const321   const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
322     return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
323   }
324 
325   DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
326 
327   /// Checks if the variable is a local for OpenMP region.
328   bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
329 
330   /// Vector of previously declared requires directives
331   SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
332   /// omp_allocator_handle_t type.
333   QualType OMPAllocatorHandleT;
334   /// omp_depend_t type.
335   QualType OMPDependT;
336   /// omp_event_handle_t type.
337   QualType OMPEventHandleT;
338   /// omp_alloctrait_t type.
339   QualType OMPAlloctraitT;
340   /// Expression for the predefined allocators.
341   Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
342       nullptr};
343   /// Vector of previously encountered target directives
344   SmallVector<SourceLocation, 2> TargetLocations;
345   SourceLocation AtomicLocation;
346   /// Vector of declare variant construct traits.
347   SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
348 
349 public:
DSAStackTy(Sema & S)350   explicit DSAStackTy(Sema &S) : SemaRef(S) {}
351 
352   /// Sets omp_allocator_handle_t type.
setOMPAllocatorHandleT(QualType Ty)353   void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
354   /// Gets omp_allocator_handle_t type.
getOMPAllocatorHandleT() const355   QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
356   /// Sets omp_alloctrait_t type.
setOMPAlloctraitT(QualType Ty)357   void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
358   /// Gets omp_alloctrait_t type.
getOMPAlloctraitT() const359   QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
360   /// Sets the given default allocator.
setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,Expr * Allocator)361   void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
362                     Expr *Allocator) {
363     OMPPredefinedAllocators[AllocatorKind] = Allocator;
364   }
365   /// Returns the specified default allocator.
getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const366   Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
367     return OMPPredefinedAllocators[AllocatorKind];
368   }
369   /// Sets omp_depend_t type.
setOMPDependT(QualType Ty)370   void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
371   /// Gets omp_depend_t type.
getOMPDependT() const372   QualType getOMPDependT() const { return OMPDependT; }
373 
374   /// Sets omp_event_handle_t type.
setOMPEventHandleT(QualType Ty)375   void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
376   /// Gets omp_event_handle_t type.
getOMPEventHandleT() const377   QualType getOMPEventHandleT() const { return OMPEventHandleT; }
378 
isClauseParsingMode() const379   bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
getClauseParsingMode() const380   OpenMPClauseKind getClauseParsingMode() const {
381     assert(isClauseParsingMode() && "Must be in clause parsing mode.");
382     return ClauseKindMode;
383   }
setClauseParsingMode(OpenMPClauseKind K)384   void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
385 
isBodyComplete() const386   bool isBodyComplete() const {
387     const SharingMapTy *Top = getTopOfStackOrNull();
388     return Top && Top->BodyComplete;
389   }
setBodyComplete()390   void setBodyComplete() { getTopOfStack().BodyComplete = true; }
391 
isForceVarCapturing() const392   bool isForceVarCapturing() const { return ForceCapturing; }
setForceVarCapturing(bool V)393   void setForceVarCapturing(bool V) { ForceCapturing = V; }
394 
setForceCaptureByReferenceInTargetExecutable(bool V)395   void setForceCaptureByReferenceInTargetExecutable(bool V) {
396     ForceCaptureByReferenceInTargetExecutable = V;
397   }
isForceCaptureByReferenceInTargetExecutable() const398   bool isForceCaptureByReferenceInTargetExecutable() const {
399     return ForceCaptureByReferenceInTargetExecutable;
400   }
401 
push(OpenMPDirectiveKind DKind,const DeclarationNameInfo & DirName,Scope * CurScope,SourceLocation Loc)402   void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
403             Scope *CurScope, SourceLocation Loc) {
404     assert(!IgnoredStackElements &&
405            "cannot change stack while ignoring elements");
406     if (Stack.empty() ||
407         Stack.back().second != CurrentNonCapturingFunctionScope)
408       Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
409     Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
410     Stack.back().first.back().DefaultAttrLoc = Loc;
411   }
412 
pop()413   void pop() {
414     assert(!IgnoredStackElements &&
415            "cannot change stack while ignoring elements");
416     assert(!Stack.back().first.empty() &&
417            "Data-sharing attributes stack is empty!");
418     Stack.back().first.pop_back();
419   }
420 
421   /// RAII object to temporarily leave the scope of a directive when we want to
422   /// logically operate in its parent.
423   class ParentDirectiveScope {
424     DSAStackTy &Self;
425     bool Active;
426 
427   public:
ParentDirectiveScope(DSAStackTy & Self,bool Activate)428     ParentDirectiveScope(DSAStackTy &Self, bool Activate)
429         : Self(Self), Active(false) {
430       if (Activate)
431         enable();
432     }
~ParentDirectiveScope()433     ~ParentDirectiveScope() { disable(); }
disable()434     void disable() {
435       if (Active) {
436         --Self.IgnoredStackElements;
437         Active = false;
438       }
439     }
enable()440     void enable() {
441       if (!Active) {
442         ++Self.IgnoredStackElements;
443         Active = true;
444       }
445     }
446   };
447 
448   /// Marks that we're started loop parsing.
loopInit()449   void loopInit() {
450     assert(isOpenMPLoopDirective(getCurrentDirective()) &&
451            "Expected loop-based directive.");
452     getTopOfStack().LoopStart = true;
453   }
454   /// Start capturing of the variables in the loop context.
loopStart()455   void loopStart() {
456     assert(isOpenMPLoopDirective(getCurrentDirective()) &&
457            "Expected loop-based directive.");
458     getTopOfStack().LoopStart = false;
459   }
460   /// true, if variables are captured, false otherwise.
isLoopStarted() const461   bool isLoopStarted() const {
462     assert(isOpenMPLoopDirective(getCurrentDirective()) &&
463            "Expected loop-based directive.");
464     return !getTopOfStack().LoopStart;
465   }
466   /// Marks (or clears) declaration as possibly loop counter.
resetPossibleLoopCounter(const Decl * D=nullptr)467   void resetPossibleLoopCounter(const Decl *D = nullptr) {
468     getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
469   }
470   /// Gets the possible loop counter decl.
getPossiblyLoopCounter() const471   const Decl *getPossiblyLoopCounter() const {
472     return getTopOfStack().PossiblyLoopCounter;
473   }
474   /// Start new OpenMP region stack in new non-capturing function.
pushFunction()475   void pushFunction() {
476     assert(!IgnoredStackElements &&
477            "cannot change stack while ignoring elements");
478     const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
479     assert(!isa<CapturingScopeInfo>(CurFnScope));
480     CurrentNonCapturingFunctionScope = CurFnScope;
481   }
482   /// Pop region stack for non-capturing function.
popFunction(const FunctionScopeInfo * OldFSI)483   void popFunction(const FunctionScopeInfo *OldFSI) {
484     assert(!IgnoredStackElements &&
485            "cannot change stack while ignoring elements");
486     if (!Stack.empty() && Stack.back().second == OldFSI) {
487       assert(Stack.back().first.empty());
488       Stack.pop_back();
489     }
490     CurrentNonCapturingFunctionScope = nullptr;
491     for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
492       if (!isa<CapturingScopeInfo>(FSI)) {
493         CurrentNonCapturingFunctionScope = FSI;
494         break;
495       }
496     }
497   }
498 
addCriticalWithHint(const OMPCriticalDirective * D,llvm::APSInt Hint)499   void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
500     Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
501   }
502   const std::pair<const OMPCriticalDirective *, llvm::APSInt>
getCriticalWithHint(const DeclarationNameInfo & Name) const503   getCriticalWithHint(const DeclarationNameInfo &Name) const {
504     auto I = Criticals.find(Name.getAsString());
505     if (I != Criticals.end())
506       return I->second;
507     return std::make_pair(nullptr, llvm::APSInt());
508   }
509   /// If 'aligned' declaration for given variable \a D was not seen yet,
510   /// add it and return NULL; otherwise return previous occurrence's expression
511   /// for diagnostics.
512   const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
513   /// If 'nontemporal' declaration for given variable \a D was not seen yet,
514   /// add it and return NULL; otherwise return previous occurrence's expression
515   /// for diagnostics.
516   const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
517 
518   /// Register specified variable as loop control variable.
519   void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
520   /// Check if the specified variable is a loop control variable for
521   /// current region.
522   /// \return The index of the loop control variable in the list of associated
523   /// for-loops (from outer to inner).
524   const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
525   /// Check if the specified variable is a loop control variable for
526   /// parent region.
527   /// \return The index of the loop control variable in the list of associated
528   /// for-loops (from outer to inner).
529   const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
530   /// Check if the specified variable is a loop control variable for
531   /// current region.
532   /// \return The index of the loop control variable in the list of associated
533   /// for-loops (from outer to inner).
534   const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
535                                          unsigned Level) const;
536   /// Get the loop control variable for the I-th loop (or nullptr) in
537   /// parent directive.
538   const ValueDecl *getParentLoopControlVariable(unsigned I) const;
539 
540   /// Marks the specified decl \p D as used in scan directive.
markDeclAsUsedInScanDirective(ValueDecl * D)541   void markDeclAsUsedInScanDirective(ValueDecl *D) {
542     if (SharingMapTy *Stack = getSecondOnStackOrNull())
543       Stack->UsedInScanDirective.insert(D);
544   }
545 
546   /// Checks if the specified declaration was used in the inner scan directive.
isUsedInScanDirective(ValueDecl * D) const547   bool isUsedInScanDirective(ValueDecl *D) const {
548     if (const SharingMapTy *Stack = getTopOfStackOrNull())
549       return Stack->UsedInScanDirective.contains(D);
550     return false;
551   }
552 
553   /// Adds explicit data sharing attribute to the specified declaration.
554   void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
555               DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
556               bool AppliedToPointee = false);
557 
558   /// Adds additional information for the reduction items with the reduction id
559   /// represented as an operator.
560   void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
561                                  BinaryOperatorKind BOK);
562   /// Adds additional information for the reduction items with the reduction id
563   /// represented as reduction identifier.
564   void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
565                                  const Expr *ReductionRef);
566   /// Returns the location and reduction operation from the innermost parent
567   /// region for the given \p D.
568   const DSAVarData
569   getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
570                                    BinaryOperatorKind &BOK,
571                                    Expr *&TaskgroupDescriptor) const;
572   /// Returns the location and reduction operation from the innermost parent
573   /// region for the given \p D.
574   const DSAVarData
575   getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
576                                    const Expr *&ReductionRef,
577                                    Expr *&TaskgroupDescriptor) const;
578   /// Return reduction reference expression for the current taskgroup or
579   /// parallel/worksharing directives with task reductions.
getTaskgroupReductionRef() const580   Expr *getTaskgroupReductionRef() const {
581     assert((getTopOfStack().Directive == OMPD_taskgroup ||
582             ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
583               isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
584              !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
585            "taskgroup reference expression requested for non taskgroup or "
586            "parallel/worksharing directive.");
587     return getTopOfStack().TaskgroupReductionRef;
588   }
589   /// Checks if the given \p VD declaration is actually a taskgroup reduction
590   /// descriptor variable at the \p Level of OpenMP regions.
isTaskgroupReductionRef(const ValueDecl * VD,unsigned Level) const591   bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
592     return getStackElemAtLevel(Level).TaskgroupReductionRef &&
593            cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
594                    ->getDecl() == VD;
595   }
596 
597   /// Returns data sharing attributes from top of the stack for the
598   /// specified declaration.
599   const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
600   /// Returns data-sharing attributes for the specified declaration.
601   const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
602   /// Returns data-sharing attributes for the specified declaration.
603   const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
604   /// Checks if the specified variables has data-sharing attributes which
605   /// match specified \a CPred predicate in any directive which matches \a DPred
606   /// predicate.
607   const DSAVarData
608   hasDSA(ValueDecl *D,
609          const llvm::function_ref<bool(OpenMPClauseKind, bool,
610                                        DefaultDataSharingAttributes)>
611              CPred,
612          const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
613          bool FromParent) const;
614   /// Checks if the specified variables has data-sharing attributes which
615   /// match specified \a CPred predicate in any innermost directive which
616   /// matches \a DPred predicate.
617   const DSAVarData
618   hasInnermostDSA(ValueDecl *D,
619                   const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
620                   const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
621                   bool FromParent) const;
622   /// Checks if the specified variables has explicit data-sharing
623   /// attributes which match specified \a CPred predicate at the specified
624   /// OpenMP region.
625   bool
626   hasExplicitDSA(const ValueDecl *D,
627                  const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
628                  unsigned Level, bool NotLastprivate = false) const;
629 
630   /// Returns true if the directive at level \Level matches in the
631   /// specified \a DPred predicate.
632   bool hasExplicitDirective(
633       const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
634       unsigned Level) const;
635 
636   /// Finds a directive which matches specified \a DPred predicate.
637   bool hasDirective(
638       const llvm::function_ref<bool(
639           OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)>
640           DPred,
641       bool FromParent) const;
642 
643   /// Returns currently analyzed directive.
getCurrentDirective() const644   OpenMPDirectiveKind getCurrentDirective() const {
645     const SharingMapTy *Top = getTopOfStackOrNull();
646     return Top ? Top->Directive : OMPD_unknown;
647   }
getMappedDirective() const648   OpenMPDirectiveKind getMappedDirective() const {
649     const SharingMapTy *Top = getTopOfStackOrNull();
650     return Top ? Top->MappedDirective : OMPD_unknown;
651   }
setCurrentDirective(OpenMPDirectiveKind NewDK)652   void setCurrentDirective(OpenMPDirectiveKind NewDK) {
653     SharingMapTy *Top = getTopOfStackOrNull();
654     assert(Top &&
655            "Before calling setCurrentDirective Top of Stack not to be NULL.");
656     // Store the old into MappedDirective & assign argument NewDK to Directive.
657     Top->Directive = NewDK;
658   }
setMappedDirective(OpenMPDirectiveKind NewDK)659   void setMappedDirective(OpenMPDirectiveKind NewDK) {
660     SharingMapTy *Top = getTopOfStackOrNull();
661     assert(Top &&
662            "Before calling setMappedDirective Top of Stack not to be NULL.");
663     // Store the old into MappedDirective & assign argument NewDK to Directive.
664     Top->MappedDirective = NewDK;
665   }
666   /// Returns directive kind at specified level.
getDirective(unsigned Level) const667   OpenMPDirectiveKind getDirective(unsigned Level) const {
668     assert(!isStackEmpty() && "No directive at specified level.");
669     return getStackElemAtLevel(Level).Directive;
670   }
671   /// Returns the capture region at the specified level.
getCaptureRegion(unsigned Level,unsigned OpenMPCaptureLevel) const672   OpenMPDirectiveKind getCaptureRegion(unsigned Level,
673                                        unsigned OpenMPCaptureLevel) const {
674     SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
675     getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
676     return CaptureRegions[OpenMPCaptureLevel];
677   }
678   /// Returns parent directive.
getParentDirective() const679   OpenMPDirectiveKind getParentDirective() const {
680     const SharingMapTy *Parent = getSecondOnStackOrNull();
681     return Parent ? Parent->Directive : OMPD_unknown;
682   }
683 
684   /// Add requires decl to internal vector
addRequiresDecl(OMPRequiresDecl * RD)685   void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
686 
687   /// Checks if the defined 'requires' directive has specified type of clause.
hasRequiresDeclWithClause() const688   template <typename ClauseType> bool hasRequiresDeclWithClause() const {
689     return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
690       return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
691         return isa<ClauseType>(C);
692       });
693     });
694   }
695 
696   /// Checks for a duplicate clause amongst previously declared requires
697   /// directives
hasDuplicateRequiresClause(ArrayRef<OMPClause * > ClauseList) const698   bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
699     bool IsDuplicate = false;
700     for (OMPClause *CNew : ClauseList) {
701       for (const OMPRequiresDecl *D : RequiresDecls) {
702         for (const OMPClause *CPrev : D->clauselists()) {
703           if (CNew->getClauseKind() == CPrev->getClauseKind()) {
704             SemaRef.Diag(CNew->getBeginLoc(),
705                          diag::err_omp_requires_clause_redeclaration)
706                 << getOpenMPClauseName(CNew->getClauseKind());
707             SemaRef.Diag(CPrev->getBeginLoc(),
708                          diag::note_omp_requires_previous_clause)
709                 << getOpenMPClauseName(CPrev->getClauseKind());
710             IsDuplicate = true;
711           }
712         }
713       }
714     }
715     return IsDuplicate;
716   }
717 
718   /// Add location of previously encountered target to internal vector
addTargetDirLocation(SourceLocation LocStart)719   void addTargetDirLocation(SourceLocation LocStart) {
720     TargetLocations.push_back(LocStart);
721   }
722 
723   /// Add location for the first encountered atomic directive.
addAtomicDirectiveLoc(SourceLocation Loc)724   void addAtomicDirectiveLoc(SourceLocation Loc) {
725     if (AtomicLocation.isInvalid())
726       AtomicLocation = Loc;
727   }
728 
729   /// Returns the location of the first encountered atomic directive in the
730   /// module.
getAtomicDirectiveLoc() const731   SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
732 
733   // Return previously encountered target region locations.
getEncounteredTargetLocs() const734   ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
735     return TargetLocations;
736   }
737 
738   /// Set default data sharing attribute to none.
setDefaultDSANone(SourceLocation Loc)739   void setDefaultDSANone(SourceLocation Loc) {
740     getTopOfStack().DefaultAttr = DSA_none;
741     getTopOfStack().DefaultAttrLoc = Loc;
742   }
743   /// Set default data sharing attribute to shared.
setDefaultDSAShared(SourceLocation Loc)744   void setDefaultDSAShared(SourceLocation Loc) {
745     getTopOfStack().DefaultAttr = DSA_shared;
746     getTopOfStack().DefaultAttrLoc = Loc;
747   }
748   /// Set default data sharing attribute to private.
setDefaultDSAPrivate(SourceLocation Loc)749   void setDefaultDSAPrivate(SourceLocation Loc) {
750     getTopOfStack().DefaultAttr = DSA_private;
751     getTopOfStack().DefaultAttrLoc = Loc;
752   }
753   /// Set default data sharing attribute to firstprivate.
setDefaultDSAFirstPrivate(SourceLocation Loc)754   void setDefaultDSAFirstPrivate(SourceLocation Loc) {
755     getTopOfStack().DefaultAttr = DSA_firstprivate;
756     getTopOfStack().DefaultAttrLoc = Loc;
757   }
758   /// Set default data mapping attribute to Modifier:Kind
setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,OpenMPDefaultmapClauseKind Kind,SourceLocation Loc)759   void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
760                          OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) {
761     DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
762     DMI.ImplicitBehavior = M;
763     DMI.SLoc = Loc;
764   }
765   /// Check whether the implicit-behavior has been set in defaultmap
checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory)766   bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
767     if (VariableCategory == OMPC_DEFAULTMAP_unknown)
768       return getTopOfStack()
769                      .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
770                      .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
771              getTopOfStack()
772                      .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
773                      .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
774              getTopOfStack()
775                      .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
776                      .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
777     return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
778            OMPC_DEFAULTMAP_MODIFIER_unknown;
779   }
780 
getConstructTraits()781   ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
782     return ConstructTraits;
783   }
handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,bool ScopeEntry)784   void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
785                             bool ScopeEntry) {
786     if (ScopeEntry)
787       ConstructTraits.append(Traits.begin(), Traits.end());
788     else
789       for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
790         llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
791         assert(Top == Trait && "Something left a trait on the stack!");
792         (void)Trait;
793         (void)Top;
794       }
795   }
796 
getDefaultDSA(unsigned Level) const797   DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
798     return getStackSize() <= Level ? DSA_unspecified
799                                    : getStackElemAtLevel(Level).DefaultAttr;
800   }
getDefaultDSA() const801   DefaultDataSharingAttributes getDefaultDSA() const {
802     return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
803   }
getDefaultDSALocation() const804   SourceLocation getDefaultDSALocation() const {
805     return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
806   }
807   OpenMPDefaultmapClauseModifier
getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const808   getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
809     return isStackEmpty()
810                ? OMPC_DEFAULTMAP_MODIFIER_unknown
811                : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
812   }
813   OpenMPDefaultmapClauseModifier
getDefaultmapModifierAtLevel(unsigned Level,OpenMPDefaultmapClauseKind Kind) const814   getDefaultmapModifierAtLevel(unsigned Level,
815                                OpenMPDefaultmapClauseKind Kind) const {
816     return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
817   }
isDefaultmapCapturedByRef(unsigned Level,OpenMPDefaultmapClauseKind Kind) const818   bool isDefaultmapCapturedByRef(unsigned Level,
819                                  OpenMPDefaultmapClauseKind Kind) const {
820     OpenMPDefaultmapClauseModifier M =
821         getDefaultmapModifierAtLevel(Level, Kind);
822     if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
823       return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
824              (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
825              (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
826              (M == OMPC_DEFAULTMAP_MODIFIER_tofrom);
827     }
828     return true;
829   }
mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,OpenMPDefaultmapClauseKind Kind)830   static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
831                                      OpenMPDefaultmapClauseKind Kind) {
832     switch (Kind) {
833     case OMPC_DEFAULTMAP_scalar:
834     case OMPC_DEFAULTMAP_pointer:
835       return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
836              (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
837              (M == OMPC_DEFAULTMAP_MODIFIER_default);
838     case OMPC_DEFAULTMAP_aggregate:
839       return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
840     default:
841       break;
842     }
843     llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
844   }
mustBeFirstprivateAtLevel(unsigned Level,OpenMPDefaultmapClauseKind Kind) const845   bool mustBeFirstprivateAtLevel(unsigned Level,
846                                  OpenMPDefaultmapClauseKind Kind) const {
847     OpenMPDefaultmapClauseModifier M =
848         getDefaultmapModifierAtLevel(Level, Kind);
849     return mustBeFirstprivateBase(M, Kind);
850   }
mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const851   bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
852     OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
853     return mustBeFirstprivateBase(M, Kind);
854   }
855 
856   /// Checks if the specified variable is a threadprivate.
isThreadPrivate(VarDecl * D)857   bool isThreadPrivate(VarDecl *D) {
858     const DSAVarData DVar = getTopDSA(D, false);
859     return isOpenMPThreadPrivate(DVar.CKind);
860   }
861 
862   /// Marks current region as ordered (it has an 'ordered' clause).
setOrderedRegion(bool IsOrdered,const Expr * Param,OMPOrderedClause * Clause)863   void setOrderedRegion(bool IsOrdered, const Expr *Param,
864                         OMPOrderedClause *Clause) {
865     if (IsOrdered)
866       getTopOfStack().OrderedRegion.emplace(Param, Clause);
867     else
868       getTopOfStack().OrderedRegion.reset();
869   }
870   /// Returns true, if region is ordered (has associated 'ordered' clause),
871   /// false - otherwise.
isOrderedRegion() const872   bool isOrderedRegion() const {
873     if (const SharingMapTy *Top = getTopOfStackOrNull())
874       return Top->OrderedRegion.has_value();
875     return false;
876   }
877   /// Returns optional parameter for the ordered region.
getOrderedRegionParam() const878   std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
879     if (const SharingMapTy *Top = getTopOfStackOrNull())
880       if (Top->OrderedRegion)
881         return *Top->OrderedRegion;
882     return std::make_pair(nullptr, nullptr);
883   }
884   /// Returns true, if parent region is ordered (has associated
885   /// 'ordered' clause), false - otherwise.
isParentOrderedRegion() const886   bool isParentOrderedRegion() const {
887     if (const SharingMapTy *Parent = getSecondOnStackOrNull())
888       return Parent->OrderedRegion.has_value();
889     return false;
890   }
891   /// Returns optional parameter for the ordered region.
892   std::pair<const Expr *, OMPOrderedClause *>
getParentOrderedRegionParam() const893   getParentOrderedRegionParam() const {
894     if (const SharingMapTy *Parent = getSecondOnStackOrNull())
895       if (Parent->OrderedRegion)
896         return *Parent->OrderedRegion;
897     return std::make_pair(nullptr, nullptr);
898   }
899   /// Marks current region as having an 'order' clause.
setRegionHasOrderConcurrent(bool HasOrderConcurrent)900   void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
901     getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
902   }
903   /// Returns true, if parent region is order (has associated
904   /// 'order' clause), false - otherwise.
isParentOrderConcurrent() const905   bool isParentOrderConcurrent() const {
906     if (const SharingMapTy *Parent = getSecondOnStackOrNull())
907       return Parent->RegionHasOrderConcurrent;
908     return false;
909   }
910   /// Marks current region as nowait (it has a 'nowait' clause).
setNowaitRegion(bool IsNowait=true)911   void setNowaitRegion(bool IsNowait = true) {
912     getTopOfStack().NowaitRegion = IsNowait;
913   }
914   /// Returns true, if parent region is nowait (has associated
915   /// 'nowait' clause), false - otherwise.
isParentNowaitRegion() const916   bool isParentNowaitRegion() const {
917     if (const SharingMapTy *Parent = getSecondOnStackOrNull())
918       return Parent->NowaitRegion;
919     return false;
920   }
921   /// Marks current region as untied (it has a 'untied' clause).
setUntiedRegion(bool IsUntied=true)922   void setUntiedRegion(bool IsUntied = true) {
923     getTopOfStack().UntiedRegion = IsUntied;
924   }
925   /// Return true if current region is untied.
isUntiedRegion() const926   bool isUntiedRegion() const {
927     const SharingMapTy *Top = getTopOfStackOrNull();
928     return Top ? Top->UntiedRegion : false;
929   }
930   /// Marks parent region as cancel region.
setParentCancelRegion(bool Cancel=true)931   void setParentCancelRegion(bool Cancel = true) {
932     if (SharingMapTy *Parent = getSecondOnStackOrNull())
933       Parent->CancelRegion |= Cancel;
934   }
935   /// Return true if current region has inner cancel construct.
isCancelRegion() const936   bool isCancelRegion() const {
937     const SharingMapTy *Top = getTopOfStackOrNull();
938     return Top ? Top->CancelRegion : false;
939   }
940 
941   /// Mark that parent region already has scan directive.
setParentHasScanDirective(SourceLocation Loc)942   void setParentHasScanDirective(SourceLocation Loc) {
943     if (SharingMapTy *Parent = getSecondOnStackOrNull())
944       Parent->PrevScanLocation = Loc;
945   }
946   /// Return true if current region has inner cancel construct.
doesParentHasScanDirective() const947   bool doesParentHasScanDirective() const {
948     const SharingMapTy *Top = getSecondOnStackOrNull();
949     return Top ? Top->PrevScanLocation.isValid() : false;
950   }
951   /// Return true if current region has inner cancel construct.
getParentScanDirectiveLoc() const952   SourceLocation getParentScanDirectiveLoc() const {
953     const SharingMapTy *Top = getSecondOnStackOrNull();
954     return Top ? Top->PrevScanLocation : SourceLocation();
955   }
956   /// Mark that parent region already has ordered directive.
setParentHasOrderedDirective(SourceLocation Loc)957   void setParentHasOrderedDirective(SourceLocation Loc) {
958     if (SharingMapTy *Parent = getSecondOnStackOrNull())
959       Parent->PrevOrderedLocation = Loc;
960   }
961   /// Return true if current region has inner ordered construct.
doesParentHasOrderedDirective() const962   bool doesParentHasOrderedDirective() const {
963     const SharingMapTy *Top = getSecondOnStackOrNull();
964     return Top ? Top->PrevOrderedLocation.isValid() : false;
965   }
966   /// Returns the location of the previously specified ordered directive.
getParentOrderedDirectiveLoc() const967   SourceLocation getParentOrderedDirectiveLoc() const {
968     const SharingMapTy *Top = getSecondOnStackOrNull();
969     return Top ? Top->PrevOrderedLocation : SourceLocation();
970   }
971 
972   /// Set collapse value for the region.
setAssociatedLoops(unsigned Val)973   void setAssociatedLoops(unsigned Val) {
974     getTopOfStack().AssociatedLoops = Val;
975     if (Val > 1)
976       getTopOfStack().HasMutipleLoops = true;
977   }
978   /// Return collapse value for region.
getAssociatedLoops() const979   unsigned getAssociatedLoops() const {
980     const SharingMapTy *Top = getTopOfStackOrNull();
981     return Top ? Top->AssociatedLoops : 0;
982   }
983   /// Returns true if the construct is associated with multiple loops.
hasMutipleLoops() const984   bool hasMutipleLoops() const {
985     const SharingMapTy *Top = getTopOfStackOrNull();
986     return Top ? Top->HasMutipleLoops : false;
987   }
988 
989   /// Marks current target region as one with closely nested teams
990   /// region.
setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc)991   void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
992     if (SharingMapTy *Parent = getSecondOnStackOrNull())
993       Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
994   }
995   /// Returns true, if current region has closely nested teams region.
hasInnerTeamsRegion() const996   bool hasInnerTeamsRegion() const {
997     return getInnerTeamsRegionLoc().isValid();
998   }
999   /// Returns location of the nested teams region (if any).
getInnerTeamsRegionLoc() const1000   SourceLocation getInnerTeamsRegionLoc() const {
1001     const SharingMapTy *Top = getTopOfStackOrNull();
1002     return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
1003   }
1004 
getCurScope() const1005   Scope *getCurScope() const {
1006     const SharingMapTy *Top = getTopOfStackOrNull();
1007     return Top ? Top->CurScope : nullptr;
1008   }
setContext(DeclContext * DC)1009   void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
getConstructLoc() const1010   SourceLocation getConstructLoc() const {
1011     const SharingMapTy *Top = getTopOfStackOrNull();
1012     return Top ? Top->ConstructLoc : SourceLocation();
1013   }
1014 
1015   /// Do the check specified in \a Check to all component lists and return true
1016   /// if any issue is found.
checkMappableExprComponentListsForDecl(const ValueDecl * VD,bool CurrentRegionOnly,const llvm::function_ref<bool (OMPClauseMappableExprCommon::MappableExprComponentListRef,OpenMPClauseKind)> Check) const1017   bool checkMappableExprComponentListsForDecl(
1018       const ValueDecl *VD, bool CurrentRegionOnly,
1019       const llvm::function_ref<
1020           bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1021                OpenMPClauseKind)>
1022           Check) const {
1023     if (isStackEmpty())
1024       return false;
1025     auto SI = begin();
1026     auto SE = end();
1027 
1028     if (SI == SE)
1029       return false;
1030 
1031     if (CurrentRegionOnly)
1032       SE = std::next(SI);
1033     else
1034       std::advance(SI, 1);
1035 
1036     for (; SI != SE; ++SI) {
1037       auto MI = SI->MappedExprComponents.find(VD);
1038       if (MI != SI->MappedExprComponents.end())
1039         for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1040              MI->second.Components)
1041           if (Check(L, MI->second.Kind))
1042             return true;
1043     }
1044     return false;
1045   }
1046 
1047   /// Do the check specified in \a Check to all component lists at a given level
1048   /// and return true if any issue is found.
checkMappableExprComponentListsForDeclAtLevel(const ValueDecl * VD,unsigned Level,const llvm::function_ref<bool (OMPClauseMappableExprCommon::MappableExprComponentListRef,OpenMPClauseKind)> Check) const1049   bool checkMappableExprComponentListsForDeclAtLevel(
1050       const ValueDecl *VD, unsigned Level,
1051       const llvm::function_ref<
1052           bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1053                OpenMPClauseKind)>
1054           Check) const {
1055     if (getStackSize() <= Level)
1056       return false;
1057 
1058     const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1059     auto MI = StackElem.MappedExprComponents.find(VD);
1060     if (MI != StackElem.MappedExprComponents.end())
1061       for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1062            MI->second.Components)
1063         if (Check(L, MI->second.Kind))
1064           return true;
1065     return false;
1066   }
1067 
1068   /// Create a new mappable expression component list associated with a given
1069   /// declaration and initialize it with the provided list of components.
addMappableExpressionComponents(const ValueDecl * VD,OMPClauseMappableExprCommon::MappableExprComponentListRef Components,OpenMPClauseKind WhereFoundClauseKind)1070   void addMappableExpressionComponents(
1071       const ValueDecl *VD,
1072       OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
1073       OpenMPClauseKind WhereFoundClauseKind) {
1074     MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1075     // Create new entry and append the new components there.
1076     MEC.Components.resize(MEC.Components.size() + 1);
1077     MEC.Components.back().append(Components.begin(), Components.end());
1078     MEC.Kind = WhereFoundClauseKind;
1079   }
1080 
getNestingLevel() const1081   unsigned getNestingLevel() const {
1082     assert(!isStackEmpty());
1083     return getStackSize() - 1;
1084   }
addDoacrossDependClause(OMPClause * C,const OperatorOffsetTy & OpsOffs)1085   void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1086     SharingMapTy *Parent = getSecondOnStackOrNull();
1087     assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1088     Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1089   }
1090   llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
getDoacrossDependClauses() const1091   getDoacrossDependClauses() const {
1092     const SharingMapTy &StackElem = getTopOfStack();
1093     if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1094       const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1095       return llvm::make_range(Ref.begin(), Ref.end());
1096     }
1097     return llvm::make_range(StackElem.DoacrossDepends.end(),
1098                             StackElem.DoacrossDepends.end());
1099   }
1100 
1101   // Store types of classes which have been explicitly mapped
addMappedClassesQualTypes(QualType QT)1102   void addMappedClassesQualTypes(QualType QT) {
1103     SharingMapTy &StackElem = getTopOfStack();
1104     StackElem.MappedClassesQualTypes.insert(QT);
1105   }
1106 
1107   // Return set of mapped classes types
isClassPreviouslyMapped(QualType QT) const1108   bool isClassPreviouslyMapped(QualType QT) const {
1109     const SharingMapTy &StackElem = getTopOfStack();
1110     return StackElem.MappedClassesQualTypes.contains(QT);
1111   }
1112 
1113   /// Adds global declare target to the parent target region.
addToParentTargetRegionLinkGlobals(DeclRefExpr * E)1114   void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1115     assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1116                E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1117            "Expected declare target link global.");
1118     for (auto &Elem : *this) {
1119       if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1120         Elem.DeclareTargetLinkVarDecls.push_back(E);
1121         return;
1122       }
1123     }
1124   }
1125 
1126   /// Returns the list of globals with declare target link if current directive
1127   /// is target.
getLinkGlobals() const1128   ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1129     assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1130            "Expected target executable directive.");
1131     return getTopOfStack().DeclareTargetLinkVarDecls;
1132   }
1133 
1134   /// Adds list of allocators expressions.
addInnerAllocatorExpr(Expr * E)1135   void addInnerAllocatorExpr(Expr *E) {
1136     getTopOfStack().InnerUsedAllocators.push_back(E);
1137   }
1138   /// Return list of used allocators.
getInnerAllocators() const1139   ArrayRef<Expr *> getInnerAllocators() const {
1140     return getTopOfStack().InnerUsedAllocators;
1141   }
1142   /// Marks the declaration as implicitly firstprivate nin the task-based
1143   /// regions.
addImplicitTaskFirstprivate(unsigned Level,Decl * D)1144   void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1145     getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1146   }
1147   /// Checks if the decl is implicitly firstprivate in the task-based region.
isImplicitTaskFirstprivate(Decl * D) const1148   bool isImplicitTaskFirstprivate(Decl *D) const {
1149     return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1150   }
1151 
1152   /// Marks decl as used in uses_allocators clause as the allocator.
addUsesAllocatorsDecl(const Decl * D,UsesAllocatorsDeclKind Kind)1153   void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1154     getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1155   }
1156   /// Checks if specified decl is used in uses allocator clause as the
1157   /// allocator.
1158   std::optional<UsesAllocatorsDeclKind>
isUsesAllocatorsDecl(unsigned Level,const Decl * D) const1159   isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1160     const SharingMapTy &StackElem = getTopOfStack();
1161     auto I = StackElem.UsesAllocatorsDecls.find(D);
1162     if (I == StackElem.UsesAllocatorsDecls.end())
1163       return std::nullopt;
1164     return I->getSecond();
1165   }
1166   std::optional<UsesAllocatorsDeclKind>
isUsesAllocatorsDecl(const Decl * D) const1167   isUsesAllocatorsDecl(const Decl *D) const {
1168     const SharingMapTy &StackElem = getTopOfStack();
1169     auto I = StackElem.UsesAllocatorsDecls.find(D);
1170     if (I == StackElem.UsesAllocatorsDecls.end())
1171       return std::nullopt;
1172     return I->getSecond();
1173   }
1174 
addDeclareMapperVarRef(Expr * Ref)1175   void addDeclareMapperVarRef(Expr *Ref) {
1176     SharingMapTy &StackElem = getTopOfStack();
1177     StackElem.DeclareMapperVar = Ref;
1178   }
getDeclareMapperVarRef() const1179   const Expr *getDeclareMapperVarRef() const {
1180     const SharingMapTy *Top = getTopOfStackOrNull();
1181     return Top ? Top->DeclareMapperVar : nullptr;
1182   }
1183 
1184   /// Add a new iterator variable.
addIteratorVarDecl(VarDecl * VD)1185   void addIteratorVarDecl(VarDecl *VD) {
1186     SharingMapTy &StackElem = getTopOfStack();
1187     StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl());
1188   }
1189   /// Check if variable declaration is an iterator VarDecl.
isIteratorVarDecl(const VarDecl * VD) const1190   bool isIteratorVarDecl(const VarDecl *VD) const {
1191     const SharingMapTy *Top = getTopOfStackOrNull();
1192     if (!Top)
1193       return false;
1194 
1195     return llvm::is_contained(Top->IteratorVarDecls, VD->getCanonicalDecl());
1196   }
1197   /// get captured field from ImplicitDefaultFirstprivateFDs
getImplicitFDCapExprDecl(const FieldDecl * FD) const1198   VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1199     const_iterator I = begin();
1200     const_iterator EndI = end();
1201     size_t StackLevel = getStackSize();
1202     for (; I != EndI; ++I) {
1203       if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1204         break;
1205       StackLevel--;
1206     }
1207     assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1208     if (I == EndI)
1209       return nullptr;
1210     for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1211       if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1212         return IFD.VD;
1213     return nullptr;
1214   }
1215   /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
isImplicitDefaultFirstprivateFD(VarDecl * VD) const1216   bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1217     const_iterator I = begin();
1218     const_iterator EndI = end();
1219     for (; I != EndI; ++I)
1220       if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1221         break;
1222     if (I == EndI)
1223       return false;
1224     for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1225       if (IFD.VD == VD)
1226         return true;
1227     return false;
1228   }
1229   /// Store capture FD info in ImplicitDefaultFirstprivateFDs
addImplicitDefaultFirstprivateFD(const FieldDecl * FD,VarDecl * VD)1230   void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1231     iterator I = begin();
1232     const_iterator EndI = end();
1233     size_t StackLevel = getStackSize();
1234     for (; I != EndI; ++I) {
1235       if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1236         I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1237         break;
1238       }
1239       StackLevel--;
1240     }
1241     assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1242   }
1243 };
1244 
isImplicitTaskingRegion(OpenMPDirectiveKind DKind)1245 bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1246   return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1247 }
1248 
isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind)1249 bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1250   return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1251          DKind == OMPD_unknown;
1252 }
1253 
1254 } // namespace
1255 
getExprAsWritten(const Expr * E)1256 static const Expr *getExprAsWritten(const Expr *E) {
1257   if (const auto *FE = dyn_cast<FullExpr>(E))
1258     E = FE->getSubExpr();
1259 
1260   if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1261     E = MTE->getSubExpr();
1262 
1263   while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1264     E = Binder->getSubExpr();
1265 
1266   if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1267     E = ICE->getSubExprAsWritten();
1268   return E->IgnoreParens();
1269 }
1270 
getExprAsWritten(Expr * E)1271 static Expr *getExprAsWritten(Expr *E) {
1272   return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1273 }
1274 
getCanonicalDecl(const ValueDecl * D)1275 static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1276   if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1277     if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1278       D = ME->getMemberDecl();
1279   const auto *VD = dyn_cast<VarDecl>(D);
1280   const auto *FD = dyn_cast<FieldDecl>(D);
1281   if (VD != nullptr) {
1282     VD = VD->getCanonicalDecl();
1283     D = VD;
1284   } else {
1285     assert(FD);
1286     FD = FD->getCanonicalDecl();
1287     D = FD;
1288   }
1289   return D;
1290 }
1291 
getCanonicalDecl(ValueDecl * D)1292 static ValueDecl *getCanonicalDecl(ValueDecl *D) {
1293   return const_cast<ValueDecl *>(
1294       getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1295 }
1296 
getDSA(const_iterator & Iter,ValueDecl * D) const1297 DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1298                                           ValueDecl *D) const {
1299   D = getCanonicalDecl(D);
1300   auto *VD = dyn_cast<VarDecl>(D);
1301   const auto *FD = dyn_cast<FieldDecl>(D);
1302   DSAVarData DVar;
1303   if (Iter == end()) {
1304     // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1305     // in a region but not in construct]
1306     //  File-scope or namespace-scope variables referenced in called routines
1307     //  in the region are shared unless they appear in a threadprivate
1308     //  directive.
1309     if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1310       DVar.CKind = OMPC_shared;
1311 
1312     // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1313     // in a region but not in construct]
1314     //  Variables with static storage duration that are declared in called
1315     //  routines in the region are shared.
1316     if (VD && VD->hasGlobalStorage())
1317       DVar.CKind = OMPC_shared;
1318 
1319     // Non-static data members are shared by default.
1320     if (FD)
1321       DVar.CKind = OMPC_shared;
1322 
1323     return DVar;
1324   }
1325 
1326   // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1327   // in a Construct, C/C++, predetermined, p.1]
1328   // Variables with automatic storage duration that are declared in a scope
1329   // inside the construct are private.
1330   if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1331       (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1332     DVar.CKind = OMPC_private;
1333     return DVar;
1334   }
1335 
1336   DVar.DKind = Iter->Directive;
1337   // Explicitly specified attributes and local variables with predetermined
1338   // attributes.
1339   if (Iter->SharingMap.count(D)) {
1340     const DSAInfo &Data = Iter->SharingMap.lookup(D);
1341     DVar.RefExpr = Data.RefExpr.getPointer();
1342     DVar.PrivateCopy = Data.PrivateCopy;
1343     DVar.CKind = Data.Attributes;
1344     DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1345     DVar.Modifier = Data.Modifier;
1346     DVar.AppliedToPointee = Data.AppliedToPointee;
1347     return DVar;
1348   }
1349 
1350   // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1351   // in a Construct, C/C++, implicitly determined, p.1]
1352   //  In a parallel or task construct, the data-sharing attributes of these
1353   //  variables are determined by the default clause, if present.
1354   switch (Iter->DefaultAttr) {
1355   case DSA_shared:
1356     DVar.CKind = OMPC_shared;
1357     DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1358     return DVar;
1359   case DSA_none:
1360     return DVar;
1361   case DSA_firstprivate:
1362     if (VD && VD->getStorageDuration() == SD_Static &&
1363         VD->getDeclContext()->isFileContext()) {
1364       DVar.CKind = OMPC_unknown;
1365     } else {
1366       DVar.CKind = OMPC_firstprivate;
1367     }
1368     DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1369     return DVar;
1370   case DSA_private:
1371     // each variable with static storage duration that is declared
1372     // in a namespace or global scope and referenced in the construct,
1373     // and that does not have a predetermined data-sharing attribute
1374     if (VD && VD->getStorageDuration() == SD_Static &&
1375         VD->getDeclContext()->isFileContext()) {
1376       DVar.CKind = OMPC_unknown;
1377     } else {
1378       DVar.CKind = OMPC_private;
1379     }
1380     DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1381     return DVar;
1382   case DSA_unspecified:
1383     // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1384     // in a Construct, implicitly determined, p.2]
1385     //  In a parallel construct, if no default clause is present, these
1386     //  variables are shared.
1387     DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1388     if ((isOpenMPParallelDirective(DVar.DKind) &&
1389          !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1390         isOpenMPTeamsDirective(DVar.DKind)) {
1391       DVar.CKind = OMPC_shared;
1392       return DVar;
1393     }
1394 
1395     // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1396     // in a Construct, implicitly determined, p.4]
1397     //  In a task construct, if no default clause is present, a variable that in
1398     //  the enclosing context is determined to be shared by all implicit tasks
1399     //  bound to the current team is shared.
1400     if (isOpenMPTaskingDirective(DVar.DKind)) {
1401       DSAVarData DVarTemp;
1402       const_iterator I = Iter, E = end();
1403       do {
1404         ++I;
1405         // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1406         // Referenced in a Construct, implicitly determined, p.6]
1407         //  In a task construct, if no default clause is present, a variable
1408         //  whose data-sharing attribute is not determined by the rules above is
1409         //  firstprivate.
1410         DVarTemp = getDSA(I, D);
1411         if (DVarTemp.CKind != OMPC_shared) {
1412           DVar.RefExpr = nullptr;
1413           DVar.CKind = OMPC_firstprivate;
1414           return DVar;
1415         }
1416       } while (I != E && !isImplicitTaskingRegion(I->Directive));
1417       DVar.CKind =
1418           (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1419       return DVar;
1420     }
1421   }
1422   // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1423   // in a Construct, implicitly determined, p.3]
1424   //  For constructs other than task, if no default clause is present, these
1425   //  variables inherit their data-sharing attributes from the enclosing
1426   //  context.
1427   return getDSA(++Iter, D);
1428 }
1429 
addUniqueAligned(const ValueDecl * D,const Expr * NewDE)1430 const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1431                                          const Expr *NewDE) {
1432   assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1433   D = getCanonicalDecl(D);
1434   SharingMapTy &StackElem = getTopOfStack();
1435   auto It = StackElem.AlignedMap.find(D);
1436   if (It == StackElem.AlignedMap.end()) {
1437     assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1438     StackElem.AlignedMap[D] = NewDE;
1439     return nullptr;
1440   }
1441   assert(It->second && "Unexpected nullptr expr in the aligned map");
1442   return It->second;
1443 }
1444 
addUniqueNontemporal(const ValueDecl * D,const Expr * NewDE)1445 const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1446                                              const Expr *NewDE) {
1447   assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1448   D = getCanonicalDecl(D);
1449   SharingMapTy &StackElem = getTopOfStack();
1450   auto It = StackElem.NontemporalMap.find(D);
1451   if (It == StackElem.NontemporalMap.end()) {
1452     assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1453     StackElem.NontemporalMap[D] = NewDE;
1454     return nullptr;
1455   }
1456   assert(It->second && "Unexpected nullptr expr in the aligned map");
1457   return It->second;
1458 }
1459 
addLoopControlVariable(const ValueDecl * D,VarDecl * Capture)1460 void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1461   assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1462   D = getCanonicalDecl(D);
1463   SharingMapTy &StackElem = getTopOfStack();
1464   StackElem.LCVMap.try_emplace(
1465       D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1466 }
1467 
1468 const DSAStackTy::LCDeclInfo
isLoopControlVariable(const ValueDecl * D) const1469 DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1470   assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1471   D = getCanonicalDecl(D);
1472   const SharingMapTy &StackElem = getTopOfStack();
1473   auto It = StackElem.LCVMap.find(D);
1474   if (It != StackElem.LCVMap.end())
1475     return It->second;
1476   return {0, nullptr};
1477 }
1478 
1479 const DSAStackTy::LCDeclInfo
isLoopControlVariable(const ValueDecl * D,unsigned Level) const1480 DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1481   assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1482   D = getCanonicalDecl(D);
1483   for (unsigned I = Level + 1; I > 0; --I) {
1484     const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1485     auto It = StackElem.LCVMap.find(D);
1486     if (It != StackElem.LCVMap.end())
1487       return It->second;
1488   }
1489   return {0, nullptr};
1490 }
1491 
1492 const DSAStackTy::LCDeclInfo
isParentLoopControlVariable(const ValueDecl * D) const1493 DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1494   const SharingMapTy *Parent = getSecondOnStackOrNull();
1495   assert(Parent && "Data-sharing attributes stack is empty");
1496   D = getCanonicalDecl(D);
1497   auto It = Parent->LCVMap.find(D);
1498   if (It != Parent->LCVMap.end())
1499     return It->second;
1500   return {0, nullptr};
1501 }
1502 
getParentLoopControlVariable(unsigned I) const1503 const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1504   const SharingMapTy *Parent = getSecondOnStackOrNull();
1505   assert(Parent && "Data-sharing attributes stack is empty");
1506   if (Parent->LCVMap.size() < I)
1507     return nullptr;
1508   for (const auto &Pair : Parent->LCVMap)
1509     if (Pair.second.first == I)
1510       return Pair.first;
1511   return nullptr;
1512 }
1513 
addDSA(const ValueDecl * D,const Expr * E,OpenMPClauseKind A,DeclRefExpr * PrivateCopy,unsigned Modifier,bool AppliedToPointee)1514 void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1515                         DeclRefExpr *PrivateCopy, unsigned Modifier,
1516                         bool AppliedToPointee) {
1517   D = getCanonicalDecl(D);
1518   if (A == OMPC_threadprivate) {
1519     DSAInfo &Data = Threadprivates[D];
1520     Data.Attributes = A;
1521     Data.RefExpr.setPointer(E);
1522     Data.PrivateCopy = nullptr;
1523     Data.Modifier = Modifier;
1524   } else {
1525     DSAInfo &Data = getTopOfStack().SharingMap[D];
1526     assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1527            (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1528            (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1529            (isLoopControlVariable(D).first && A == OMPC_private));
1530     Data.Modifier = Modifier;
1531     if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1532       Data.RefExpr.setInt(/*IntVal=*/true);
1533       return;
1534     }
1535     const bool IsLastprivate =
1536         A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1537     Data.Attributes = A;
1538     Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1539     Data.PrivateCopy = PrivateCopy;
1540     Data.AppliedToPointee = AppliedToPointee;
1541     if (PrivateCopy) {
1542       DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1543       Data.Modifier = Modifier;
1544       Data.Attributes = A;
1545       Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1546       Data.PrivateCopy = nullptr;
1547       Data.AppliedToPointee = AppliedToPointee;
1548     }
1549   }
1550 }
1551 
1552 /// 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)1553 static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
1554                              StringRef Name, const AttrVec *Attrs = nullptr,
1555                              DeclRefExpr *OrigRef = nullptr) {
1556   DeclContext *DC = SemaRef.CurContext;
1557   IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1558   TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
1559   auto *Decl =
1560       VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
1561   if (Attrs) {
1562     for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1563          I != E; ++I)
1564       Decl->addAttr(*I);
1565   }
1566   Decl->setImplicit();
1567   if (OrigRef) {
1568     Decl->addAttr(
1569         OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1570   }
1571   return Decl;
1572 }
1573 
buildDeclRefExpr(Sema & S,VarDecl * D,QualType Ty,SourceLocation Loc,bool RefersToCapture=false)1574 static DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty,
1575                                      SourceLocation Loc,
1576                                      bool RefersToCapture = false) {
1577   D->setReferenced();
1578   D->markUsed(S.Context);
1579   return DeclRefExpr::Create(S.getASTContext(), NestedNameSpecifierLoc(),
1580                              SourceLocation(), D, RefersToCapture, Loc, Ty,
1581                              VK_LValue);
1582 }
1583 
addTaskgroupReductionData(const ValueDecl * D,SourceRange SR,BinaryOperatorKind BOK)1584 void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1585                                            BinaryOperatorKind BOK) {
1586   D = getCanonicalDecl(D);
1587   assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1588   assert(
1589       getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1590       "Additional reduction info may be specified only for reduction items.");
1591   ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1592   assert(ReductionData.ReductionRange.isInvalid() &&
1593          (getTopOfStack().Directive == OMPD_taskgroup ||
1594           ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1595             isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1596            !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1597          "Additional reduction info may be specified only once for reduction "
1598          "items.");
1599   ReductionData.set(BOK, SR);
1600   Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1601   if (!TaskgroupReductionRef) {
1602     VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1603                                SemaRef.Context.VoidPtrTy, ".task_red.");
1604     TaskgroupReductionRef =
1605         buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1606   }
1607 }
1608 
addTaskgroupReductionData(const ValueDecl * D,SourceRange SR,const Expr * ReductionRef)1609 void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1610                                            const Expr *ReductionRef) {
1611   D = getCanonicalDecl(D);
1612   assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1613   assert(
1614       getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1615       "Additional reduction info may be specified only for reduction items.");
1616   ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1617   assert(ReductionData.ReductionRange.isInvalid() &&
1618          (getTopOfStack().Directive == OMPD_taskgroup ||
1619           ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1620             isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1621            !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1622          "Additional reduction info may be specified only once for reduction "
1623          "items.");
1624   ReductionData.set(ReductionRef, SR);
1625   Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1626   if (!TaskgroupReductionRef) {
1627     VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1628                                SemaRef.Context.VoidPtrTy, ".task_red.");
1629     TaskgroupReductionRef =
1630         buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1631   }
1632 }
1633 
getTopMostTaskgroupReductionData(const ValueDecl * D,SourceRange & SR,BinaryOperatorKind & BOK,Expr * & TaskgroupDescriptor) const1634 const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1635     const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1636     Expr *&TaskgroupDescriptor) const {
1637   D = getCanonicalDecl(D);
1638   assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1639   for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1640     const DSAInfo &Data = I->SharingMap.lookup(D);
1641     if (Data.Attributes != OMPC_reduction ||
1642         Data.Modifier != OMPC_REDUCTION_task)
1643       continue;
1644     const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1645     if (!ReductionData.ReductionOp ||
1646         ReductionData.ReductionOp.is<const Expr *>())
1647       return DSAVarData();
1648     SR = ReductionData.ReductionRange;
1649     BOK = ReductionData.ReductionOp.get<ReductionData::BOKPtrType>();
1650     assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1651                                        "expression for the descriptor is not "
1652                                        "set.");
1653     TaskgroupDescriptor = I->TaskgroupReductionRef;
1654     return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1655                       Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1656                       /*AppliedToPointee=*/false);
1657   }
1658   return DSAVarData();
1659 }
1660 
getTopMostTaskgroupReductionData(const ValueDecl * D,SourceRange & SR,const Expr * & ReductionRef,Expr * & TaskgroupDescriptor) const1661 const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1662     const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1663     Expr *&TaskgroupDescriptor) const {
1664   D = getCanonicalDecl(D);
1665   assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1666   for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1667     const DSAInfo &Data = I->SharingMap.lookup(D);
1668     if (Data.Attributes != OMPC_reduction ||
1669         Data.Modifier != OMPC_REDUCTION_task)
1670       continue;
1671     const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1672     if (!ReductionData.ReductionOp ||
1673         !ReductionData.ReductionOp.is<const Expr *>())
1674       return DSAVarData();
1675     SR = ReductionData.ReductionRange;
1676     ReductionRef = ReductionData.ReductionOp.get<const Expr *>();
1677     assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1678                                        "expression for the descriptor is not "
1679                                        "set.");
1680     TaskgroupDescriptor = I->TaskgroupReductionRef;
1681     return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1682                       Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1683                       /*AppliedToPointee=*/false);
1684   }
1685   return DSAVarData();
1686 }
1687 
isOpenMPLocal(VarDecl * D,const_iterator I) const1688 bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1689   D = D->getCanonicalDecl();
1690   for (const_iterator E = end(); I != E; ++I) {
1691     if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1692         isOpenMPTargetExecutionDirective(I->Directive)) {
1693       if (I->CurScope) {
1694         Scope *TopScope = I->CurScope->getParent();
1695         Scope *CurScope = getCurScope();
1696         while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1697           CurScope = CurScope->getParent();
1698         return CurScope != TopScope;
1699       }
1700       for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1701         if (I->Context == DC)
1702           return true;
1703       return false;
1704     }
1705   }
1706   return false;
1707 }
1708 
isConstNotMutableType(Sema & SemaRef,QualType Type,bool AcceptIfMutable=true,bool * IsClassType=nullptr)1709 static bool isConstNotMutableType(Sema &SemaRef, QualType Type,
1710                                   bool AcceptIfMutable = true,
1711                                   bool *IsClassType = nullptr) {
1712   ASTContext &Context = SemaRef.getASTContext();
1713   Type = Type.getNonReferenceType().getCanonicalType();
1714   bool IsConstant = Type.isConstant(Context);
1715   Type = Context.getBaseElementType(Type);
1716   const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1717                                 ? Type->getAsCXXRecordDecl()
1718                                 : nullptr;
1719   if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1720     if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1721       RD = CTD->getTemplatedDecl();
1722   if (IsClassType)
1723     *IsClassType = RD;
1724   return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1725                          RD->hasDefinition() && RD->hasMutableFields());
1726 }
1727 
rejectConstNotMutableType(Sema & SemaRef,const ValueDecl * D,QualType Type,OpenMPClauseKind CKind,SourceLocation ELoc,bool AcceptIfMutable=true,bool ListItemNotVar=false)1728 static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1729                                       QualType Type, OpenMPClauseKind CKind,
1730                                       SourceLocation ELoc,
1731                                       bool AcceptIfMutable = true,
1732                                       bool ListItemNotVar = false) {
1733   ASTContext &Context = SemaRef.getASTContext();
1734   bool IsClassType;
1735   if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
1736     unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1737                     : IsClassType  ? diag::err_omp_const_not_mutable_variable
1738                                    : diag::err_omp_const_variable;
1739     SemaRef.Diag(ELoc, Diag) << getOpenMPClauseName(CKind);
1740     if (!ListItemNotVar && D) {
1741       const VarDecl *VD = dyn_cast<VarDecl>(D);
1742       bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1743                                VarDecl::DeclarationOnly;
1744       SemaRef.Diag(D->getLocation(),
1745                    IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1746           << D;
1747     }
1748     return true;
1749   }
1750   return false;
1751 }
1752 
getTopDSA(ValueDecl * D,bool FromParent)1753 const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1754                                                    bool FromParent) {
1755   D = getCanonicalDecl(D);
1756   DSAVarData DVar;
1757 
1758   auto *VD = dyn_cast<VarDecl>(D);
1759   auto TI = Threadprivates.find(D);
1760   if (TI != Threadprivates.end()) {
1761     DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1762     DVar.CKind = OMPC_threadprivate;
1763     DVar.Modifier = TI->getSecond().Modifier;
1764     return DVar;
1765   }
1766   if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1767     DVar.RefExpr = buildDeclRefExpr(
1768         SemaRef, VD, D->getType().getNonReferenceType(),
1769         VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1770     DVar.CKind = OMPC_threadprivate;
1771     addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1772     return DVar;
1773   }
1774   // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1775   // in a Construct, C/C++, predetermined, p.1]
1776   //  Variables appearing in threadprivate directives are threadprivate.
1777   if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1778        !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1779          SemaRef.getLangOpts().OpenMPUseTLS &&
1780          SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1781       (VD && VD->getStorageClass() == SC_Register &&
1782        VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1783     DVar.RefExpr = buildDeclRefExpr(
1784         SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1785     DVar.CKind = OMPC_threadprivate;
1786     addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1787     return DVar;
1788   }
1789   if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1790       VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1791       !isLoopControlVariable(D).first) {
1792     const_iterator IterTarget =
1793         std::find_if(begin(), end(), [](const SharingMapTy &Data) {
1794           return isOpenMPTargetExecutionDirective(Data.Directive);
1795         });
1796     if (IterTarget != end()) {
1797       const_iterator ParentIterTarget = IterTarget + 1;
1798       for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1799         if (isOpenMPLocal(VD, Iter)) {
1800           DVar.RefExpr =
1801               buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1802                                D->getLocation());
1803           DVar.CKind = OMPC_threadprivate;
1804           return DVar;
1805         }
1806       }
1807       if (!isClauseParsingMode() || IterTarget != begin()) {
1808         auto DSAIter = IterTarget->SharingMap.find(D);
1809         if (DSAIter != IterTarget->SharingMap.end() &&
1810             isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1811           DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1812           DVar.CKind = OMPC_threadprivate;
1813           return DVar;
1814         }
1815         const_iterator End = end();
1816         if (!SemaRef.OpenMP().isOpenMPCapturedByRef(
1817                 D, std::distance(ParentIterTarget, End),
1818                 /*OpenMPCaptureLevel=*/0)) {
1819           DVar.RefExpr =
1820               buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1821                                IterTarget->ConstructLoc);
1822           DVar.CKind = OMPC_threadprivate;
1823           return DVar;
1824         }
1825       }
1826     }
1827   }
1828 
1829   if (isStackEmpty())
1830     // Not in OpenMP execution region and top scope was already checked.
1831     return DVar;
1832 
1833   // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1834   // in a Construct, C/C++, predetermined, p.4]
1835   //  Static data members are shared.
1836   // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1837   // in a Construct, C/C++, predetermined, p.7]
1838   //  Variables with static storage duration that are declared in a scope
1839   //  inside the construct are shared.
1840   if (VD && VD->isStaticDataMember()) {
1841     // Check for explicitly specified attributes.
1842     const_iterator I = begin();
1843     const_iterator EndI = end();
1844     if (FromParent && I != EndI)
1845       ++I;
1846     if (I != EndI) {
1847       auto It = I->SharingMap.find(D);
1848       if (It != I->SharingMap.end()) {
1849         const DSAInfo &Data = It->getSecond();
1850         DVar.RefExpr = Data.RefExpr.getPointer();
1851         DVar.PrivateCopy = Data.PrivateCopy;
1852         DVar.CKind = Data.Attributes;
1853         DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1854         DVar.DKind = I->Directive;
1855         DVar.Modifier = Data.Modifier;
1856         DVar.AppliedToPointee = Data.AppliedToPointee;
1857         return DVar;
1858       }
1859     }
1860 
1861     DVar.CKind = OMPC_shared;
1862     return DVar;
1863   }
1864 
1865   auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1866   // The predetermined shared attribute for const-qualified types having no
1867   // mutable members was removed after OpenMP 3.1.
1868   if (SemaRef.LangOpts.OpenMP <= 31) {
1869     // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1870     // in a Construct, C/C++, predetermined, p.6]
1871     //  Variables with const qualified type having no mutable member are
1872     //  shared.
1873     if (isConstNotMutableType(SemaRef, D->getType())) {
1874       // Variables with const-qualified type having no mutable member may be
1875       // listed in a firstprivate clause, even if they are static data members.
1876       DSAVarData DVarTemp = hasInnermostDSA(
1877           D,
1878           [](OpenMPClauseKind C, bool) {
1879             return C == OMPC_firstprivate || C == OMPC_shared;
1880           },
1881           MatchesAlways, FromParent);
1882       if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1883         return DVarTemp;
1884 
1885       DVar.CKind = OMPC_shared;
1886       return DVar;
1887     }
1888   }
1889 
1890   // Explicitly specified attributes and local variables with predetermined
1891   // attributes.
1892   const_iterator I = begin();
1893   const_iterator EndI = end();
1894   if (FromParent && I != EndI)
1895     ++I;
1896   if (I == EndI)
1897     return DVar;
1898   auto It = I->SharingMap.find(D);
1899   if (It != I->SharingMap.end()) {
1900     const DSAInfo &Data = It->getSecond();
1901     DVar.RefExpr = Data.RefExpr.getPointer();
1902     DVar.PrivateCopy = Data.PrivateCopy;
1903     DVar.CKind = Data.Attributes;
1904     DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1905     DVar.DKind = I->Directive;
1906     DVar.Modifier = Data.Modifier;
1907     DVar.AppliedToPointee = Data.AppliedToPointee;
1908   }
1909 
1910   return DVar;
1911 }
1912 
getImplicitDSA(ValueDecl * D,bool FromParent) const1913 const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1914                                                         bool FromParent) const {
1915   if (isStackEmpty()) {
1916     const_iterator I;
1917     return getDSA(I, D);
1918   }
1919   D = getCanonicalDecl(D);
1920   const_iterator StartI = begin();
1921   const_iterator EndI = end();
1922   if (FromParent && StartI != EndI)
1923     ++StartI;
1924   return getDSA(StartI, D);
1925 }
1926 
getImplicitDSA(ValueDecl * D,unsigned Level) const1927 const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1928                                                         unsigned Level) const {
1929   if (getStackSize() <= Level)
1930     return DSAVarData();
1931   D = getCanonicalDecl(D);
1932   const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1933   return getDSA(StartI, D);
1934 }
1935 
1936 const DSAStackTy::DSAVarData
hasDSA(ValueDecl * D,const llvm::function_ref<bool (OpenMPClauseKind,bool,DefaultDataSharingAttributes)> CPred,const llvm::function_ref<bool (OpenMPDirectiveKind)> DPred,bool FromParent) const1937 DSAStackTy::hasDSA(ValueDecl *D,
1938                    const llvm::function_ref<bool(OpenMPClauseKind, bool,
1939                                                  DefaultDataSharingAttributes)>
1940                        CPred,
1941                    const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1942                    bool FromParent) const {
1943   if (isStackEmpty())
1944     return {};
1945   D = getCanonicalDecl(D);
1946   const_iterator I = begin();
1947   const_iterator EndI = end();
1948   if (FromParent && I != EndI)
1949     ++I;
1950   for (; I != EndI; ++I) {
1951     if (!DPred(I->Directive) &&
1952         !isImplicitOrExplicitTaskingRegion(I->Directive))
1953       continue;
1954     const_iterator NewI = I;
1955     DSAVarData DVar = getDSA(NewI, D);
1956     if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1957       return DVar;
1958   }
1959   return {};
1960 }
1961 
hasInnermostDSA(ValueDecl * D,const llvm::function_ref<bool (OpenMPClauseKind,bool)> CPred,const llvm::function_ref<bool (OpenMPDirectiveKind)> DPred,bool FromParent) const1962 const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1963     ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1964     const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1965     bool FromParent) const {
1966   if (isStackEmpty())
1967     return {};
1968   D = getCanonicalDecl(D);
1969   const_iterator StartI = begin();
1970   const_iterator EndI = end();
1971   if (FromParent && StartI != EndI)
1972     ++StartI;
1973   if (StartI == EndI || !DPred(StartI->Directive))
1974     return {};
1975   const_iterator NewI = StartI;
1976   DSAVarData DVar = getDSA(NewI, D);
1977   return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1978              ? DVar
1979              : DSAVarData();
1980 }
1981 
hasExplicitDSA(const ValueDecl * D,const llvm::function_ref<bool (OpenMPClauseKind,bool)> CPred,unsigned Level,bool NotLastprivate) const1982 bool DSAStackTy::hasExplicitDSA(
1983     const ValueDecl *D,
1984     const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1985     unsigned Level, bool NotLastprivate) const {
1986   if (getStackSize() <= Level)
1987     return false;
1988   D = getCanonicalDecl(D);
1989   const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1990   auto I = StackElem.SharingMap.find(D);
1991   if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1992       CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1993       (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1994     return true;
1995   // Check predetermined rules for the loop control variables.
1996   auto LI = StackElem.LCVMap.find(D);
1997   if (LI != StackElem.LCVMap.end())
1998     return CPred(OMPC_private, /*AppliedToPointee=*/false);
1999   return false;
2000 }
2001 
hasExplicitDirective(const llvm::function_ref<bool (OpenMPDirectiveKind)> DPred,unsigned Level) const2002 bool DSAStackTy::hasExplicitDirective(
2003     const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2004     unsigned Level) const {
2005   if (getStackSize() <= Level)
2006     return false;
2007   const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2008   return DPred(StackElem.Directive);
2009 }
2010 
hasDirective(const llvm::function_ref<bool (OpenMPDirectiveKind,const DeclarationNameInfo &,SourceLocation)> DPred,bool FromParent) const2011 bool DSAStackTy::hasDirective(
2012     const llvm::function_ref<bool(OpenMPDirectiveKind,
2013                                   const DeclarationNameInfo &, SourceLocation)>
2014         DPred,
2015     bool FromParent) const {
2016   // We look only in the enclosing region.
2017   size_t Skip = FromParent ? 2 : 1;
2018   for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
2019        I != E; ++I) {
2020     if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2021       return true;
2022   }
2023   return false;
2024 }
2025 
InitDataSharingAttributesStack()2026 void SemaOpenMP::InitDataSharingAttributesStack() {
2027   VarDataSharingAttributesStack = new DSAStackTy(SemaRef);
2028 }
2029 
2030 #define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2031 
pushOpenMPFunctionRegion()2032 void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2033 
popOpenMPFunctionRegion(const FunctionScopeInfo * OldFSI)2034 void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2035   DSAStack->popFunction(OldFSI);
2036 }
2037 
isOpenMPDeviceDelayedContext(Sema & S)2038 static bool isOpenMPDeviceDelayedContext(Sema &S) {
2039   assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2040          "Expected OpenMP device compilation.");
2041   return !S.OpenMP().isInOpenMPTargetExecutionDirective();
2042 }
2043 
2044 namespace {
2045 /// Status of the function emission on the host/device.
2046 enum class FunctionEmissionStatus {
2047   Emitted,
2048   Discarded,
2049   Unknown,
2050 };
2051 } // anonymous namespace
2052 
2053 SemaBase::SemaDiagnosticBuilder
diagIfOpenMPDeviceCode(SourceLocation Loc,unsigned DiagID,const FunctionDecl * FD)2054 SemaOpenMP::diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID,
2055                                    const FunctionDecl *FD) {
2056   assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&
2057          "Expected OpenMP device compilation.");
2058 
2059   SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2060   if (FD) {
2061     Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(FD);
2062     switch (FES) {
2063     case Sema::FunctionEmissionStatus::Emitted:
2064       Kind = SemaDiagnosticBuilder::K_Immediate;
2065       break;
2066     case Sema::FunctionEmissionStatus::Unknown:
2067       // TODO: We should always delay diagnostics here in case a target
2068       //       region is in a function we do not emit. However, as the
2069       //       current diagnostics are associated with the function containing
2070       //       the target region and we do not emit that one, we would miss out
2071       //       on diagnostics for the target region itself. We need to anchor
2072       //       the diagnostics with the new generated function *or* ensure we
2073       //       emit diagnostics associated with the surrounding function.
2074       Kind = isOpenMPDeviceDelayedContext(SemaRef)
2075                  ? SemaDiagnosticBuilder::K_Deferred
2076                  : SemaDiagnosticBuilder::K_Immediate;
2077       break;
2078     case Sema::FunctionEmissionStatus::TemplateDiscarded:
2079     case Sema::FunctionEmissionStatus::OMPDiscarded:
2080       Kind = SemaDiagnosticBuilder::K_Nop;
2081       break;
2082     case Sema::FunctionEmissionStatus::CUDADiscarded:
2083       llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2084       break;
2085     }
2086   }
2087 
2088   return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2089 }
2090 
2091 SemaBase::SemaDiagnosticBuilder
diagIfOpenMPHostCode(SourceLocation Loc,unsigned DiagID,const FunctionDecl * FD)2092 SemaOpenMP::diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID,
2093                                  const FunctionDecl *FD) {
2094   assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice &&
2095          "Expected OpenMP host compilation.");
2096 
2097   SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2098   if (FD) {
2099     Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(FD);
2100     switch (FES) {
2101     case Sema::FunctionEmissionStatus::Emitted:
2102       Kind = SemaDiagnosticBuilder::K_Immediate;
2103       break;
2104     case Sema::FunctionEmissionStatus::Unknown:
2105       Kind = SemaDiagnosticBuilder::K_Deferred;
2106       break;
2107     case Sema::FunctionEmissionStatus::TemplateDiscarded:
2108     case Sema::FunctionEmissionStatus::OMPDiscarded:
2109     case Sema::FunctionEmissionStatus::CUDADiscarded:
2110       Kind = SemaDiagnosticBuilder::K_Nop;
2111       break;
2112     }
2113   }
2114 
2115   return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2116 }
2117 
2118 static OpenMPDefaultmapClauseKind
getVariableCategoryFromDecl(const LangOptions & LO,const ValueDecl * VD)2119 getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD) {
2120   if (LO.OpenMP <= 45) {
2121     if (VD->getType().getNonReferenceType()->isScalarType())
2122       return OMPC_DEFAULTMAP_scalar;
2123     return OMPC_DEFAULTMAP_aggregate;
2124   }
2125   if (VD->getType().getNonReferenceType()->isAnyPointerType())
2126     return OMPC_DEFAULTMAP_pointer;
2127   if (VD->getType().getNonReferenceType()->isScalarType())
2128     return OMPC_DEFAULTMAP_scalar;
2129   return OMPC_DEFAULTMAP_aggregate;
2130 }
2131 
isOpenMPCapturedByRef(const ValueDecl * D,unsigned Level,unsigned OpenMPCaptureLevel) const2132 bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2133                                        unsigned OpenMPCaptureLevel) const {
2134   assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2135 
2136   ASTContext &Ctx = getASTContext();
2137   bool IsByRef = true;
2138 
2139   // Find the directive that is associated with the provided scope.
2140   D = cast<ValueDecl>(D->getCanonicalDecl());
2141   QualType Ty = D->getType();
2142 
2143   bool IsVariableUsedInMapClause = false;
2144   if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2145     // This table summarizes how a given variable should be passed to the device
2146     // given its type and the clauses where it appears. This table is based on
2147     // the description in OpenMP 4.5 [2.10.4, target Construct] and
2148     // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2149     //
2150     // =========================================================================
2151     // | type |  defaultmap   | pvt | first | is_device_ptr |    map   | res.  |
2152     // |      |(tofrom:scalar)|     |  pvt  |               |has_dv_adr|       |
2153     // =========================================================================
2154     // | scl  |               |     |       |       -       |          | bycopy|
2155     // | scl  |               |  -  |   x   |       -       |     -    | bycopy|
2156     // | scl  |               |  x  |   -   |       -       |     -    | null  |
2157     // | scl  |       x       |     |       |       -       |          | byref |
2158     // | scl  |       x       |  -  |   x   |       -       |     -    | bycopy|
2159     // | scl  |       x       |  x  |   -   |       -       |     -    | null  |
2160     // | scl  |               |  -  |   -   |       -       |     x    | byref |
2161     // | scl  |       x       |  -  |   -   |       -       |     x    | byref |
2162     //
2163     // | agg  |      n.a.     |     |       |       -       |          | byref |
2164     // | agg  |      n.a.     |  -  |   x   |       -       |     -    | byref |
2165     // | agg  |      n.a.     |  x  |   -   |       -       |     -    | null  |
2166     // | agg  |      n.a.     |  -  |   -   |       -       |     x    | byref |
2167     // | agg  |      n.a.     |  -  |   -   |       -       |    x[]   | byref |
2168     //
2169     // | ptr  |      n.a.     |     |       |       -       |          | bycopy|
2170     // | ptr  |      n.a.     |  -  |   x   |       -       |     -    | bycopy|
2171     // | ptr  |      n.a.     |  x  |   -   |       -       |     -    | null  |
2172     // | ptr  |      n.a.     |  -  |   -   |       -       |     x    | byref |
2173     // | ptr  |      n.a.     |  -  |   -   |       -       |    x[]   | bycopy|
2174     // | ptr  |      n.a.     |  -  |   -   |       x       |          | bycopy|
2175     // | ptr  |      n.a.     |  -  |   -   |       x       |     x    | bycopy|
2176     // | ptr  |      n.a.     |  -  |   -   |       x       |    x[]   | bycopy|
2177     // =========================================================================
2178     // Legend:
2179     //  scl - scalar
2180     //  ptr - pointer
2181     //  agg - aggregate
2182     //  x - applies
2183     //  - - invalid in this combination
2184     //  [] - mapped with an array section
2185     //  byref - should be mapped by reference
2186     //  byval - should be mapped by value
2187     //  null - initialize a local variable to null on the device
2188     //
2189     // Observations:
2190     //  - All scalar declarations that show up in a map clause have to be passed
2191     //    by reference, because they may have been mapped in the enclosing data
2192     //    environment.
2193     //  - If the scalar value does not fit the size of uintptr, it has to be
2194     //    passed by reference, regardless the result in the table above.
2195     //  - For pointers mapped by value that have either an implicit map or an
2196     //    array section, the runtime library may pass the NULL value to the
2197     //    device instead of the value passed to it by the compiler.
2198 
2199     if (Ty->isReferenceType())
2200       Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2201 
2202     // Locate map clauses and see if the variable being captured is referred to
2203     // in any of those clauses. Here we only care about variables, not fields,
2204     // because fields are part of aggregates.
2205     bool IsVariableAssociatedWithSection = false;
2206 
2207     DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2208         D, Level,
2209         [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2210          D](OMPClauseMappableExprCommon::MappableExprComponentListRef
2211                 MapExprComponents,
2212             OpenMPClauseKind WhereFoundClauseKind) {
2213           // Both map and has_device_addr clauses information influences how a
2214           // variable is captured. E.g. is_device_ptr does not require changing
2215           // the default behavior.
2216           if (WhereFoundClauseKind != OMPC_map &&
2217               WhereFoundClauseKind != OMPC_has_device_addr)
2218             return false;
2219 
2220           auto EI = MapExprComponents.rbegin();
2221           auto EE = MapExprComponents.rend();
2222 
2223           assert(EI != EE && "Invalid map expression!");
2224 
2225           if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2226             IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2227 
2228           ++EI;
2229           if (EI == EE)
2230             return false;
2231           auto Last = std::prev(EE);
2232           const auto *UO =
2233               dyn_cast<UnaryOperator>(Last->getAssociatedExpression());
2234           if ((UO && UO->getOpcode() == UO_Deref) ||
2235               isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) ||
2236               isa<ArraySectionExpr>(Last->getAssociatedExpression()) ||
2237               isa<MemberExpr>(EI->getAssociatedExpression()) ||
2238               isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) {
2239             IsVariableAssociatedWithSection = true;
2240             // There is nothing more we need to know about this variable.
2241             return true;
2242           }
2243 
2244           // Keep looking for more map info.
2245           return false;
2246         });
2247 
2248     if (IsVariableUsedInMapClause) {
2249       // If variable is identified in a map clause it is always captured by
2250       // reference except if it is a pointer that is dereferenced somehow.
2251       IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2252     } else {
2253       // By default, all the data that has a scalar type is mapped by copy
2254       // (except for reduction variables).
2255       // Defaultmap scalar is mutual exclusive to defaultmap pointer
2256       IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2257                  !Ty->isAnyPointerType()) ||
2258                 !Ty->isScalarType() ||
2259                 DSAStack->isDefaultmapCapturedByRef(
2260                     Level, getVariableCategoryFromDecl(getLangOpts(), D)) ||
2261                 DSAStack->hasExplicitDSA(
2262                     D,
2263                     [](OpenMPClauseKind K, bool AppliedToPointee) {
2264                       return K == OMPC_reduction && !AppliedToPointee;
2265                     },
2266                     Level);
2267     }
2268   }
2269 
2270   if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2271     IsByRef =
2272         ((IsVariableUsedInMapClause &&
2273           DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2274               OMPD_target) ||
2275          !(DSAStack->hasExplicitDSA(
2276                D,
2277                [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2278                  return K == OMPC_firstprivate ||
2279                         (K == OMPC_reduction && AppliedToPointee);
2280                },
2281                Level, /*NotLastprivate=*/true) ||
2282            DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2283         // If the variable is artificial and must be captured by value - try to
2284         // capture by value.
2285         !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2286           !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2287         // If the variable is implicitly firstprivate and scalar - capture by
2288         // copy
2289         !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2290            DSAStack->getDefaultDSA() == DSA_private) &&
2291           !DSAStack->hasExplicitDSA(
2292               D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2293               Level) &&
2294           !DSAStack->isLoopControlVariable(D, Level).first);
2295   }
2296 
2297   // When passing data by copy, we need to make sure it fits the uintptr size
2298   // and alignment, because the runtime library only deals with uintptr types.
2299   // If it does not fit the uintptr size, we need to pass the data by reference
2300   // instead.
2301   if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) >
2302                        Ctx.getTypeSizeInChars(Ctx.getUIntPtrType()) ||
2303                    Ctx.getAlignOfGlobalVarInChars(Ty, dyn_cast<VarDecl>(D)) >
2304                        Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2305     IsByRef = true;
2306   }
2307 
2308   return IsByRef;
2309 }
2310 
getOpenMPNestingLevel() const2311 unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2312   assert(getLangOpts().OpenMP);
2313   return DSAStack->getNestingLevel();
2314 }
2315 
isInOpenMPTaskUntiedContext() const2316 bool SemaOpenMP::isInOpenMPTaskUntiedContext() const {
2317   return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2318          DSAStack->isUntiedRegion();
2319 }
2320 
isInOpenMPTargetExecutionDirective() const2321 bool SemaOpenMP::isInOpenMPTargetExecutionDirective() const {
2322   return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2323           !DSAStack->isClauseParsingMode()) ||
2324          DSAStack->hasDirective(
2325              [](OpenMPDirectiveKind K, const DeclarationNameInfo &,
2326                 SourceLocation) -> bool {
2327                return isOpenMPTargetExecutionDirective(K);
2328              },
2329              false);
2330 }
2331 
isOpenMPRebuildMemberExpr(ValueDecl * D)2332 bool SemaOpenMP::isOpenMPRebuildMemberExpr(ValueDecl *D) {
2333   // Only rebuild for Field.
2334   if (!dyn_cast<FieldDecl>(D))
2335     return false;
2336   DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2337       D,
2338       [](OpenMPClauseKind C, bool AppliedToPointee,
2339          DefaultDataSharingAttributes DefaultAttr) {
2340         return isOpenMPPrivate(C) && !AppliedToPointee &&
2341                (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2342       },
2343       [](OpenMPDirectiveKind) { return true; },
2344       DSAStack->isClauseParsingMode());
2345   if (DVarPrivate.CKind != OMPC_unknown)
2346     return true;
2347   return false;
2348 }
2349 
2350 static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
2351                                              Expr *CaptureExpr, bool WithInit,
2352                                              DeclContext *CurContext,
2353                                              bool AsExpression);
2354 
isOpenMPCapturedDecl(ValueDecl * D,bool CheckScopeInfo,unsigned StopAt)2355 VarDecl *SemaOpenMP::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
2356                                           unsigned StopAt) {
2357   assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2358   D = getCanonicalDecl(D);
2359 
2360   auto *VD = dyn_cast<VarDecl>(D);
2361   // Do not capture constexpr variables.
2362   if (VD && VD->isConstexpr())
2363     return nullptr;
2364 
2365   // If we want to determine whether the variable should be captured from the
2366   // perspective of the current capturing scope, and we've already left all the
2367   // capturing scopes of the top directive on the stack, check from the
2368   // perspective of its parent directive (if any) instead.
2369   DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2370       *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2371 
2372   // If we are attempting to capture a global variable in a directive with
2373   // 'target' we return true so that this global is also mapped to the device.
2374   //
2375   if (VD && !VD->hasLocalStorage() &&
2376       (SemaRef.getCurCapturedRegion() || SemaRef.getCurBlock() ||
2377        SemaRef.getCurLambda())) {
2378     if (isInOpenMPTargetExecutionDirective()) {
2379       DSAStackTy::DSAVarData DVarTop =
2380           DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2381       if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2382         return VD;
2383       // If the declaration is enclosed in a 'declare target' directive,
2384       // then it should not be captured.
2385       //
2386       if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2387         return nullptr;
2388       CapturedRegionScopeInfo *CSI = nullptr;
2389       for (FunctionScopeInfo *FSI : llvm::drop_begin(
2390                llvm::reverse(SemaRef.FunctionScopes),
2391                CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2392                               : 0)) {
2393         if (!isa<CapturingScopeInfo>(FSI))
2394           return nullptr;
2395         if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2396           if (RSI->CapRegionKind == CR_OpenMP) {
2397             CSI = RSI;
2398             break;
2399           }
2400       }
2401       assert(CSI && "Failed to find CapturedRegionScopeInfo");
2402       SmallVector<OpenMPDirectiveKind, 4> Regions;
2403       getOpenMPCaptureRegions(Regions,
2404                               DSAStack->getDirective(CSI->OpenMPLevel));
2405       if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2406         return VD;
2407     }
2408     if (isInOpenMPDeclareTargetContext()) {
2409       // Try to mark variable as declare target if it is used in capturing
2410       // regions.
2411       if (getLangOpts().OpenMP <= 45 &&
2412           !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2413         checkDeclIsAllowedInOpenMPTarget(nullptr, VD);
2414       return nullptr;
2415     }
2416   }
2417 
2418   if (CheckScopeInfo) {
2419     bool OpenMPFound = false;
2420     for (unsigned I = StopAt + 1; I > 0; --I) {
2421       FunctionScopeInfo *FSI = SemaRef.FunctionScopes[I - 1];
2422       if (!isa<CapturingScopeInfo>(FSI))
2423         return nullptr;
2424       if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2425         if (RSI->CapRegionKind == CR_OpenMP) {
2426           OpenMPFound = true;
2427           break;
2428         }
2429     }
2430     if (!OpenMPFound)
2431       return nullptr;
2432   }
2433 
2434   if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2435       (!DSAStack->isClauseParsingMode() ||
2436        DSAStack->getParentDirective() != OMPD_unknown)) {
2437     auto &&Info = DSAStack->isLoopControlVariable(D);
2438     if (Info.first ||
2439         (VD && VD->hasLocalStorage() &&
2440          isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2441         (VD && DSAStack->isForceVarCapturing()))
2442       return VD ? VD : Info.second;
2443     DSAStackTy::DSAVarData DVarTop =
2444         DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2445     if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2446         (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee))
2447       return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2448     // Threadprivate variables must not be captured.
2449     if (isOpenMPThreadPrivate(DVarTop.CKind))
2450       return nullptr;
2451     // The variable is not private or it is the variable in the directive with
2452     // default(none) clause and not used in any clause.
2453     DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2454         D,
2455         [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2456           return isOpenMPPrivate(C) && !AppliedToPointee;
2457         },
2458         [](OpenMPDirectiveKind) { return true; },
2459         DSAStack->isClauseParsingMode());
2460     // Global shared must not be captured.
2461     if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2462         ((DSAStack->getDefaultDSA() != DSA_none &&
2463           DSAStack->getDefaultDSA() != DSA_private &&
2464           DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2465          DVarTop.CKind == OMPC_shared))
2466       return nullptr;
2467     auto *FD = dyn_cast<FieldDecl>(D);
2468     if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2469         !DVarPrivate.PrivateCopy) {
2470       DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2471           D,
2472           [](OpenMPClauseKind C, bool AppliedToPointee,
2473              DefaultDataSharingAttributes DefaultAttr) {
2474             return isOpenMPPrivate(C) && !AppliedToPointee &&
2475                    (DefaultAttr == DSA_firstprivate ||
2476                     DefaultAttr == DSA_private);
2477           },
2478           [](OpenMPDirectiveKind) { return true; },
2479           DSAStack->isClauseParsingMode());
2480       if (DVarPrivate.CKind == OMPC_unknown)
2481         return nullptr;
2482 
2483       VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2484       if (VD)
2485         return VD;
2486       if (SemaRef.getCurrentThisType().isNull())
2487         return nullptr;
2488       Expr *ThisExpr = SemaRef.BuildCXXThisExpr(SourceLocation(),
2489                                                 SemaRef.getCurrentThisType(),
2490                                                 /*IsImplicit=*/true);
2491       const CXXScopeSpec CS = CXXScopeSpec();
2492       Expr *ME = SemaRef.BuildMemberExpr(
2493           ThisExpr, /*IsArrow=*/true, SourceLocation(),
2494           NestedNameSpecifierLoc(), SourceLocation(), FD,
2495           DeclAccessPair::make(FD, FD->getAccess()),
2496           /*HadMultipleCandidates=*/false, DeclarationNameInfo(), FD->getType(),
2497           VK_LValue, OK_Ordinary);
2498       OMPCapturedExprDecl *CD = buildCaptureDecl(
2499           SemaRef, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2500           SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2501       DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2502           SemaRef, CD, CD->getType().getNonReferenceType(), SourceLocation());
2503       VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2504       DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2505       return VD;
2506     }
2507     if (DVarPrivate.CKind != OMPC_unknown ||
2508         (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2509                 DSAStack->getDefaultDSA() == DSA_private ||
2510                 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2511       return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2512   }
2513   return nullptr;
2514 }
2515 
adjustOpenMPTargetScopeIndex(unsigned & FunctionScopesIndex,unsigned Level) const2516 void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2517                                               unsigned Level) const {
2518   FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2519 }
2520 
startOpenMPLoop()2521 void SemaOpenMP::startOpenMPLoop() {
2522   assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2523   if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2524     DSAStack->loopInit();
2525 }
2526 
startOpenMPCXXRangeFor()2527 void SemaOpenMP::startOpenMPCXXRangeFor() {
2528   assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2529   if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2530     DSAStack->resetPossibleLoopCounter();
2531     DSAStack->loopStart();
2532   }
2533 }
2534 
isOpenMPPrivateDecl(ValueDecl * D,unsigned Level,unsigned CapLevel) const2535 OpenMPClauseKind SemaOpenMP::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
2536                                                  unsigned CapLevel) const {
2537   assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2538   if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2539       (!DSAStack->isClauseParsingMode() ||
2540        DSAStack->getParentDirective() != OMPD_unknown)) {
2541     DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2542         D,
2543         [](OpenMPClauseKind C, bool AppliedToPointee,
2544            DefaultDataSharingAttributes DefaultAttr) {
2545           return isOpenMPPrivate(C) && !AppliedToPointee &&
2546                  DefaultAttr == DSA_private;
2547         },
2548         [](OpenMPDirectiveKind) { return true; },
2549         DSAStack->isClauseParsingMode());
2550     if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2551         DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2552         !DSAStack->isLoopControlVariable(D).first)
2553       return OMPC_private;
2554   }
2555   if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2556     bool IsTriviallyCopyable =
2557         D->getType().getNonReferenceType().isTriviallyCopyableType(
2558             getASTContext()) &&
2559         !D->getType()
2560              .getNonReferenceType()
2561              .getCanonicalType()
2562              ->getAsCXXRecordDecl();
2563     OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2564     SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
2565     getOpenMPCaptureRegions(CaptureRegions, DKind);
2566     if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2567         (IsTriviallyCopyable ||
2568          !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2569       if (DSAStack->hasExplicitDSA(
2570               D,
2571               [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2572               Level, /*NotLastprivate=*/true))
2573         return OMPC_firstprivate;
2574       DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2575       if (DVar.CKind != OMPC_shared &&
2576           !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2577         DSAStack->addImplicitTaskFirstprivate(Level, D);
2578         return OMPC_firstprivate;
2579       }
2580     }
2581   }
2582   if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2583       !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2584     if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2585       DSAStack->resetPossibleLoopCounter(D);
2586       DSAStack->loopStart();
2587       return OMPC_private;
2588     }
2589     if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2590          DSAStack->isLoopControlVariable(D).first) &&
2591         !DSAStack->hasExplicitDSA(
2592             D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2593             Level) &&
2594         !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2595       return OMPC_private;
2596   }
2597   if (const auto *VD = dyn_cast<VarDecl>(D)) {
2598     if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2599         DSAStack->isForceVarCapturing() &&
2600         !DSAStack->hasExplicitDSA(
2601             D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2602             Level))
2603       return OMPC_private;
2604   }
2605   // User-defined allocators are private since they must be defined in the
2606   // context of target region.
2607   if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2608       DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2609           DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2610           DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2611     return OMPC_private;
2612   return (DSAStack->hasExplicitDSA(
2613               D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2614               Level) ||
2615           (DSAStack->isClauseParsingMode() &&
2616            DSAStack->getClauseParsingMode() == OMPC_private) ||
2617           // Consider taskgroup reduction descriptor variable a private
2618           // to avoid possible capture in the region.
2619           (DSAStack->hasExplicitDirective(
2620                [](OpenMPDirectiveKind K) {
2621                  return K == OMPD_taskgroup ||
2622                         ((isOpenMPParallelDirective(K) ||
2623                           isOpenMPWorksharingDirective(K)) &&
2624                          !isOpenMPSimdDirective(K));
2625                },
2626                Level) &&
2627            DSAStack->isTaskgroupReductionRef(D, Level)))
2628              ? OMPC_private
2629              : OMPC_unknown;
2630 }
2631 
setOpenMPCaptureKind(FieldDecl * FD,const ValueDecl * D,unsigned Level)2632 void SemaOpenMP::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D,
2633                                       unsigned Level) {
2634   assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2635   D = getCanonicalDecl(D);
2636   OpenMPClauseKind OMPC = OMPC_unknown;
2637   for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2638     const unsigned NewLevel = I - 1;
2639     if (DSAStack->hasExplicitDSA(
2640             D,
2641             [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2642               if (isOpenMPPrivate(K) && !AppliedToPointee) {
2643                 OMPC = K;
2644                 return true;
2645               }
2646               return false;
2647             },
2648             NewLevel))
2649       break;
2650     if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2651             D, NewLevel,
2652             [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
2653                OpenMPClauseKind) { return true; })) {
2654       OMPC = OMPC_map;
2655       break;
2656     }
2657     if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2658                                        NewLevel)) {
2659       OMPC = OMPC_map;
2660       if (DSAStack->mustBeFirstprivateAtLevel(
2661               NewLevel, getVariableCategoryFromDecl(getLangOpts(), D)))
2662         OMPC = OMPC_firstprivate;
2663       break;
2664     }
2665   }
2666   if (OMPC != OMPC_unknown)
2667     FD->addAttr(
2668         OMPCaptureKindAttr::CreateImplicit(getASTContext(), unsigned(OMPC)));
2669 }
2670 
isOpenMPTargetCapturedDecl(const ValueDecl * D,unsigned Level,unsigned CaptureLevel) const2671 bool SemaOpenMP::isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level,
2672                                             unsigned CaptureLevel) const {
2673   assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2674   // Return true if the current level is no longer enclosed in a target region.
2675 
2676   SmallVector<OpenMPDirectiveKind, 4> Regions;
2677   getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2678   const auto *VD = dyn_cast<VarDecl>(D);
2679   return VD && !VD->hasLocalStorage() &&
2680          DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2681                                         Level) &&
2682          Regions[CaptureLevel] != OMPD_task;
2683 }
2684 
isOpenMPGlobalCapturedDecl(ValueDecl * D,unsigned Level,unsigned CaptureLevel) const2685 bool SemaOpenMP::isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level,
2686                                             unsigned CaptureLevel) const {
2687   assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2688   // Return true if the current level is no longer enclosed in a target region.
2689 
2690   if (const auto *VD = dyn_cast<VarDecl>(D)) {
2691     if (!VD->hasLocalStorage()) {
2692       if (isInOpenMPTargetExecutionDirective())
2693         return true;
2694       DSAStackTy::DSAVarData TopDVar =
2695           DSAStack->getTopDSA(D, /*FromParent=*/false);
2696       unsigned NumLevels =
2697           getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2698       if (Level == 0)
2699         // non-file scope static variable with default(firstprivate)
2700         // should be global captured.
2701         return (NumLevels == CaptureLevel + 1 &&
2702                 (TopDVar.CKind != OMPC_shared ||
2703                  DSAStack->getDefaultDSA() == DSA_firstprivate));
2704       do {
2705         --Level;
2706         DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2707         if (DVar.CKind != OMPC_shared)
2708           return true;
2709       } while (Level > 0);
2710     }
2711   }
2712   return true;
2713 }
2714 
DestroyDataSharingAttributesStack()2715 void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2716 
ActOnOpenMPBeginDeclareVariant(SourceLocation Loc,OMPTraitInfo & TI)2717 void SemaOpenMP::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc,
2718                                                 OMPTraitInfo &TI) {
2719   OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2720 }
2721 
ActOnOpenMPEndDeclareVariant()2722 void SemaOpenMP::ActOnOpenMPEndDeclareVariant() {
2723   assert(isInOpenMPDeclareVariantScope() &&
2724          "Not in OpenMP declare variant scope!");
2725 
2726   OMPDeclareVariantScopes.pop_back();
2727 }
2728 
finalizeOpenMPDelayedAnalysis(const FunctionDecl * Caller,const FunctionDecl * Callee,SourceLocation Loc)2729 void SemaOpenMP::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,
2730                                                const FunctionDecl *Callee,
2731                                                SourceLocation Loc) {
2732   assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2733   std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2734       OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2735   // Ignore host functions during device analysis.
2736   if (getLangOpts().OpenMPIsTargetDevice &&
2737       (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2738     return;
2739   // Ignore nohost functions during host analysis.
2740   if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2741       *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2742     return;
2743   const FunctionDecl *FD = Callee->getMostRecentDecl();
2744   DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2745   if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2746       *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2747     // Diagnose host function called during device codegen.
2748     StringRef HostDevTy =
2749         getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2750     Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2751     Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2752          diag::note_omp_marked_device_type_here)
2753         << HostDevTy;
2754     return;
2755   }
2756   if (!getLangOpts().OpenMPIsTargetDevice &&
2757       !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2758       *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2759     // In OpenMP 5.2 or later, if the function has a host variant then allow
2760     // that to be called instead
2761     auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2762       for (OMPDeclareVariantAttr *A :
2763            Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2764         auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2765         auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2766         std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2767             OMPDeclareTargetDeclAttr::getDeviceType(
2768                 VariantFD->getMostRecentDecl());
2769         if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2770           return true;
2771       }
2772       return false;
2773     };
2774     if (getLangOpts().OpenMP >= 52 &&
2775         Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2776       return;
2777     // Diagnose nohost function called during host codegen.
2778     StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2779         OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2780     Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2781     Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2782          diag::note_omp_marked_device_type_here)
2783         << NoHostDevTy;
2784   }
2785 }
2786 
StartOpenMPDSABlock(OpenMPDirectiveKind DKind,const DeclarationNameInfo & DirName,Scope * CurScope,SourceLocation Loc)2787 void SemaOpenMP::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
2788                                      const DeclarationNameInfo &DirName,
2789                                      Scope *CurScope, SourceLocation Loc) {
2790   DSAStack->push(DKind, DirName, CurScope, Loc);
2791   SemaRef.PushExpressionEvaluationContext(
2792       Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
2793 }
2794 
StartOpenMPClause(OpenMPClauseKind K)2795 void SemaOpenMP::StartOpenMPClause(OpenMPClauseKind K) {
2796   DSAStack->setClauseParsingMode(K);
2797 }
2798 
EndOpenMPClause()2799 void SemaOpenMP::EndOpenMPClause() {
2800   DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2801   SemaRef.CleanupVarDeclMarking();
2802 }
2803 
2804 static std::pair<ValueDecl *, bool>
2805 getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2806                SourceRange &ERange, bool AllowArraySection = false,
2807                StringRef DiagType = "");
2808 
2809 /// Check consistency of the reduction clauses.
checkReductionClauses(Sema & S,DSAStackTy * Stack,ArrayRef<OMPClause * > Clauses)2810 static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2811                                   ArrayRef<OMPClause *> Clauses) {
2812   bool InscanFound = false;
2813   SourceLocation InscanLoc;
2814   // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2815   // A reduction clause without the inscan reduction-modifier may not appear on
2816   // a construct on which a reduction clause with the inscan reduction-modifier
2817   // appears.
2818   for (OMPClause *C : Clauses) {
2819     if (C->getClauseKind() != OMPC_reduction)
2820       continue;
2821     auto *RC = cast<OMPReductionClause>(C);
2822     if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2823       InscanFound = true;
2824       InscanLoc = RC->getModifierLoc();
2825       continue;
2826     }
2827     if (RC->getModifier() == OMPC_REDUCTION_task) {
2828       // OpenMP 5.0, 2.19.5.4 reduction Clause.
2829       // A reduction clause with the task reduction-modifier may only appear on
2830       // a parallel construct, a worksharing construct or a combined or
2831       // composite construct for which any of the aforementioned constructs is a
2832       // constituent construct and simd or loop are not constituent constructs.
2833       OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2834       if (!(isOpenMPParallelDirective(CurDir) ||
2835             isOpenMPWorksharingDirective(CurDir)) ||
2836           isOpenMPSimdDirective(CurDir))
2837         S.Diag(RC->getModifierLoc(),
2838                diag::err_omp_reduction_task_not_parallel_or_worksharing);
2839       continue;
2840     }
2841   }
2842   if (InscanFound) {
2843     for (OMPClause *C : Clauses) {
2844       if (C->getClauseKind() != OMPC_reduction)
2845         continue;
2846       auto *RC = cast<OMPReductionClause>(C);
2847       if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2848         S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2849                    ? RC->getBeginLoc()
2850                    : RC->getModifierLoc(),
2851                diag::err_omp_inscan_reduction_expected);
2852         S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2853         continue;
2854       }
2855       for (Expr *Ref : RC->varlists()) {
2856         assert(Ref && "NULL expr in OpenMP nontemporal clause.");
2857         SourceLocation ELoc;
2858         SourceRange ERange;
2859         Expr *SimpleRefExpr = Ref;
2860         auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2861                                   /*AllowArraySection=*/true);
2862         ValueDecl *D = Res.first;
2863         if (!D)
2864           continue;
2865         if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2866           S.Diag(Ref->getExprLoc(),
2867                  diag::err_omp_reduction_not_inclusive_exclusive)
2868               << Ref->getSourceRange();
2869         }
2870       }
2871     }
2872   }
2873 }
2874 
2875 static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2876                                  ArrayRef<OMPClause *> Clauses);
2877 static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2878                                  bool WithInit);
2879 
2880 static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2881                               const ValueDecl *D,
2882                               const DSAStackTy::DSAVarData &DVar,
2883                               bool IsLoopIterVar = false);
2884 
EndOpenMPDSABlock(Stmt * CurDirective)2885 void SemaOpenMP::EndOpenMPDSABlock(Stmt *CurDirective) {
2886   // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2887   //  A variable of class type (or array thereof) that appears in a lastprivate
2888   //  clause requires an accessible, unambiguous default constructor for the
2889   //  class type, unless the list item is also specified in a firstprivate
2890   //  clause.
2891   if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2892     for (OMPClause *C : D->clauses()) {
2893       if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
2894         SmallVector<Expr *, 8> PrivateCopies;
2895         for (Expr *DE : Clause->varlists()) {
2896           if (DE->isValueDependent() || DE->isTypeDependent()) {
2897             PrivateCopies.push_back(nullptr);
2898             continue;
2899           }
2900           auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2901           auto *VD = cast<VarDecl>(DRE->getDecl());
2902           QualType Type = VD->getType().getNonReferenceType();
2903           const DSAStackTy::DSAVarData DVar =
2904               DSAStack->getTopDSA(VD, /*FromParent=*/false);
2905           if (DVar.CKind == OMPC_lastprivate) {
2906             // Generate helper private variable and initialize it with the
2907             // default value. The address of the original variable is replaced
2908             // by the address of the new private variable in CodeGen. This new
2909             // variable is not added to IdResolver, so the code in the OpenMP
2910             // region uses original variable for proper diagnostics.
2911             VarDecl *VDPrivate = buildVarDecl(
2912                 SemaRef, DE->getExprLoc(), Type.getUnqualifiedType(),
2913                 VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2914             SemaRef.ActOnUninitializedDecl(VDPrivate);
2915             if (VDPrivate->isInvalidDecl()) {
2916               PrivateCopies.push_back(nullptr);
2917               continue;
2918             }
2919             PrivateCopies.push_back(buildDeclRefExpr(
2920                 SemaRef, VDPrivate, DE->getType(), DE->getExprLoc()));
2921           } else {
2922             // The variable is also a firstprivate, so initialization sequence
2923             // for private copy is generated already.
2924             PrivateCopies.push_back(nullptr);
2925           }
2926         }
2927         Clause->setPrivateCopies(PrivateCopies);
2928         continue;
2929       }
2930       // Finalize nontemporal clause by handling private copies, if any.
2931       if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
2932         SmallVector<Expr *, 8> PrivateRefs;
2933         for (Expr *RefExpr : Clause->varlists()) {
2934           assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2935           SourceLocation ELoc;
2936           SourceRange ERange;
2937           Expr *SimpleRefExpr = RefExpr;
2938           auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
2939           if (Res.second)
2940             // It will be analyzed later.
2941             PrivateRefs.push_back(RefExpr);
2942           ValueDecl *D = Res.first;
2943           if (!D)
2944             continue;
2945 
2946           const DSAStackTy::DSAVarData DVar =
2947               DSAStack->getTopDSA(D, /*FromParent=*/false);
2948           PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2949                                                  : SimpleRefExpr);
2950         }
2951         Clause->setPrivateRefs(PrivateRefs);
2952         continue;
2953       }
2954       if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
2955         for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2956           OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2957           auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
2958           if (!DRE)
2959             continue;
2960           ValueDecl *VD = DRE->getDecl();
2961           if (!VD || !isa<VarDecl>(VD))
2962             continue;
2963           DSAStackTy::DSAVarData DVar =
2964               DSAStack->getTopDSA(VD, /*FromParent=*/false);
2965           // OpenMP [2.12.5, target Construct]
2966           // Memory allocators that appear in a uses_allocators clause cannot
2967           // appear in other data-sharing attribute clauses or data-mapping
2968           // attribute clauses in the same construct.
2969           Expr *MapExpr = nullptr;
2970           if (DVar.RefExpr ||
2971               DSAStack->checkMappableExprComponentListsForDecl(
2972                   VD, /*CurrentRegionOnly=*/true,
2973                   [VD, &MapExpr](
2974                       OMPClauseMappableExprCommon::MappableExprComponentListRef
2975                           MapExprComponents,
2976                       OpenMPClauseKind C) {
2977                     auto MI = MapExprComponents.rbegin();
2978                     auto ME = MapExprComponents.rend();
2979                     if (MI != ME &&
2980                         MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2981                             VD->getCanonicalDecl()) {
2982                       MapExpr = MI->getAssociatedExpression();
2983                       return true;
2984                     }
2985                     return false;
2986                   })) {
2987             Diag(D.Allocator->getExprLoc(),
2988                  diag::err_omp_allocator_used_in_clauses)
2989                 << D.Allocator->getSourceRange();
2990             if (DVar.RefExpr)
2991               reportOriginalDsa(SemaRef, DSAStack, VD, DVar);
2992             else
2993               Diag(MapExpr->getExprLoc(), diag::note_used_here)
2994                   << MapExpr->getSourceRange();
2995           }
2996         }
2997         continue;
2998       }
2999     }
3000     // Check allocate clauses.
3001     if (!SemaRef.CurContext->isDependentContext())
3002       checkAllocateClauses(SemaRef, DSAStack, D->clauses());
3003     checkReductionClauses(SemaRef, DSAStack, D->clauses());
3004   }
3005 
3006   DSAStack->pop();
3007   SemaRef.DiscardCleanupsInEvaluationContext();
3008   SemaRef.PopExpressionEvaluationContext();
3009 }
3010 
3011 static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
3012                                      Expr *NumIterations, Sema &SemaRef,
3013                                      Scope *S, DSAStackTy *Stack);
3014 
finishLinearClauses(Sema & SemaRef,ArrayRef<OMPClause * > Clauses,OMPLoopBasedDirective::HelperExprs & B,DSAStackTy * Stack)3015 static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
3016                                 OMPLoopBasedDirective::HelperExprs &B,
3017                                 DSAStackTy *Stack) {
3018   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
3019          "loop exprs were not built");
3020 
3021   if (SemaRef.CurContext->isDependentContext())
3022     return false;
3023 
3024   // Finalize the clauses that need pre-built expressions for CodeGen.
3025   for (OMPClause *C : Clauses) {
3026     auto *LC = dyn_cast<OMPLinearClause>(C);
3027     if (!LC)
3028       continue;
3029     if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
3030                                  B.NumIterations, SemaRef,
3031                                  SemaRef.getCurScope(), Stack))
3032       return true;
3033   }
3034 
3035   return false;
3036 }
3037 
3038 namespace {
3039 
3040 class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3041 private:
3042   Sema &SemaRef;
3043 
3044 public:
VarDeclFilterCCC(Sema & S)3045   explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
ValidateCandidate(const TypoCorrection & Candidate)3046   bool ValidateCandidate(const TypoCorrection &Candidate) override {
3047     NamedDecl *ND = Candidate.getCorrectionDecl();
3048     if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3049       return VD->hasGlobalStorage() &&
3050              SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3051                                    SemaRef.getCurScope());
3052     }
3053     return false;
3054   }
3055 
clone()3056   std::unique_ptr<CorrectionCandidateCallback> clone() override {
3057     return std::make_unique<VarDeclFilterCCC>(*this);
3058   }
3059 };
3060 
3061 class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3062 private:
3063   Sema &SemaRef;
3064 
3065 public:
VarOrFuncDeclFilterCCC(Sema & S)3066   explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
ValidateCandidate(const TypoCorrection & Candidate)3067   bool ValidateCandidate(const TypoCorrection &Candidate) override {
3068     NamedDecl *ND = Candidate.getCorrectionDecl();
3069     if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3070                isa<FunctionDecl>(ND))) {
3071       return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3072                                    SemaRef.getCurScope());
3073     }
3074     return false;
3075   }
3076 
clone()3077   std::unique_ptr<CorrectionCandidateCallback> clone() override {
3078     return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3079   }
3080 };
3081 
3082 } // namespace
3083 
ActOnOpenMPIdExpression(Scope * CurScope,CXXScopeSpec & ScopeSpec,const DeclarationNameInfo & Id,OpenMPDirectiveKind Kind)3084 ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope *CurScope,
3085                                                CXXScopeSpec &ScopeSpec,
3086                                                const DeclarationNameInfo &Id,
3087                                                OpenMPDirectiveKind Kind) {
3088   ASTContext &Context = getASTContext();
3089   LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName);
3090   SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
3091                            /*ObjectType=*/QualType(),
3092                            /*AllowBuiltinCreation=*/true);
3093 
3094   if (Lookup.isAmbiguous())
3095     return ExprError();
3096 
3097   VarDecl *VD;
3098   if (!Lookup.isSingleResult()) {
3099     VarDeclFilterCCC CCC(SemaRef);
3100     if (TypoCorrection Corrected =
3101             SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
3102                                 CCC, Sema::CTK_ErrorRecovery)) {
3103       SemaRef.diagnoseTypo(Corrected,
3104                            PDiag(Lookup.empty()
3105                                      ? diag::err_undeclared_var_use_suggest
3106                                      : diag::err_omp_expected_var_arg_suggest)
3107                                << Id.getName());
3108       VD = Corrected.getCorrectionDeclAs<VarDecl>();
3109     } else {
3110       Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3111                                        : diag::err_omp_expected_var_arg)
3112           << Id.getName();
3113       return ExprError();
3114     }
3115   } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3116     Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3117     Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3118     return ExprError();
3119   }
3120   Lookup.suppressDiagnostics();
3121 
3122   // OpenMP [2.9.2, Syntax, C/C++]
3123   //   Variables must be file-scope, namespace-scope, or static block-scope.
3124   if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
3125     Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3126         << getOpenMPDirectiveName(Kind) << !VD->isStaticLocal();
3127     bool IsDecl =
3128         VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3129     Diag(VD->getLocation(),
3130          IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3131         << VD;
3132     return ExprError();
3133   }
3134 
3135   VarDecl *CanonicalVD = VD->getCanonicalDecl();
3136   NamedDecl *ND = CanonicalVD;
3137   // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3138   //   A threadprivate directive for file-scope variables must appear outside
3139   //   any definition or declaration.
3140   if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3141       !SemaRef.getCurLexicalContext()->isTranslationUnit()) {
3142     Diag(Id.getLoc(), diag::err_omp_var_scope)
3143         << getOpenMPDirectiveName(Kind) << VD;
3144     bool IsDecl =
3145         VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3146     Diag(VD->getLocation(),
3147          IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3148         << VD;
3149     return ExprError();
3150   }
3151   // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3152   //   A threadprivate directive for static class member variables must appear
3153   //   in the class definition, in the same scope in which the member
3154   //   variables are declared.
3155   if (CanonicalVD->isStaticDataMember() &&
3156       !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) {
3157     Diag(Id.getLoc(), diag::err_omp_var_scope)
3158         << getOpenMPDirectiveName(Kind) << VD;
3159     bool IsDecl =
3160         VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3161     Diag(VD->getLocation(),
3162          IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3163         << VD;
3164     return ExprError();
3165   }
3166   // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3167   //   A threadprivate directive for namespace-scope variables must appear
3168   //   outside any definition or declaration other than the namespace
3169   //   definition itself.
3170   if (CanonicalVD->getDeclContext()->isNamespace() &&
3171       (!SemaRef.getCurLexicalContext()->isFileContext() ||
3172        !SemaRef.getCurLexicalContext()->Encloses(
3173            CanonicalVD->getDeclContext()))) {
3174     Diag(Id.getLoc(), diag::err_omp_var_scope)
3175         << getOpenMPDirectiveName(Kind) << VD;
3176     bool IsDecl =
3177         VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3178     Diag(VD->getLocation(),
3179          IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3180         << VD;
3181     return ExprError();
3182   }
3183   // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3184   //   A threadprivate directive for static block-scope variables must appear
3185   //   in the scope of the variable and not in a nested scope.
3186   if (CanonicalVD->isLocalVarDecl() && CurScope &&
3187       !SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(), CurScope)) {
3188     Diag(Id.getLoc(), diag::err_omp_var_scope)
3189         << getOpenMPDirectiveName(Kind) << VD;
3190     bool IsDecl =
3191         VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3192     Diag(VD->getLocation(),
3193          IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3194         << VD;
3195     return ExprError();
3196   }
3197 
3198   // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3199   //   A threadprivate directive must lexically precede all references to any
3200   //   of the variables in its list.
3201   if (Kind == OMPD_threadprivate && VD->isUsed() &&
3202       !DSAStack->isThreadPrivate(VD)) {
3203     Diag(Id.getLoc(), diag::err_omp_var_used)
3204         << getOpenMPDirectiveName(Kind) << VD;
3205     return ExprError();
3206   }
3207 
3208   QualType ExprType = VD->getType().getNonReferenceType();
3209   return DeclRefExpr::Create(Context, NestedNameSpecifierLoc(),
3210                              SourceLocation(), VD,
3211                              /*RefersToEnclosingVariableOrCapture=*/false,
3212                              Id.getLoc(), ExprType, VK_LValue);
3213 }
3214 
3215 SemaOpenMP::DeclGroupPtrTy
ActOnOpenMPThreadprivateDirective(SourceLocation Loc,ArrayRef<Expr * > VarList)3216 SemaOpenMP::ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
3217                                               ArrayRef<Expr *> VarList) {
3218   if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3219     SemaRef.CurContext->addDecl(D);
3220     return DeclGroupPtrTy::make(DeclGroupRef(D));
3221   }
3222   return nullptr;
3223 }
3224 
3225 namespace {
3226 class LocalVarRefChecker final
3227     : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3228   Sema &SemaRef;
3229 
3230 public:
VisitDeclRefExpr(const DeclRefExpr * E)3231   bool VisitDeclRefExpr(const DeclRefExpr *E) {
3232     if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3233       if (VD->hasLocalStorage()) {
3234         SemaRef.Diag(E->getBeginLoc(),
3235                      diag::err_omp_local_var_in_threadprivate_init)
3236             << E->getSourceRange();
3237         SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3238             << VD << VD->getSourceRange();
3239         return true;
3240       }
3241     }
3242     return false;
3243   }
VisitStmt(const Stmt * S)3244   bool VisitStmt(const Stmt *S) {
3245     for (const Stmt *Child : S->children()) {
3246       if (Child && Visit(Child))
3247         return true;
3248     }
3249     return false;
3250   }
LocalVarRefChecker(Sema & SemaRef)3251   explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3252 };
3253 } // namespace
3254 
3255 OMPThreadPrivateDecl *
CheckOMPThreadPrivateDecl(SourceLocation Loc,ArrayRef<Expr * > VarList)3256 SemaOpenMP::CheckOMPThreadPrivateDecl(SourceLocation Loc,
3257                                       ArrayRef<Expr *> VarList) {
3258   ASTContext &Context = getASTContext();
3259   SmallVector<Expr *, 8> Vars;
3260   for (Expr *RefExpr : VarList) {
3261     auto *DE = cast<DeclRefExpr>(RefExpr);
3262     auto *VD = cast<VarDecl>(DE->getDecl());
3263     SourceLocation ILoc = DE->getExprLoc();
3264 
3265     // Mark variable as used.
3266     VD->setReferenced();
3267     VD->markUsed(Context);
3268 
3269     QualType QType = VD->getType();
3270     if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3271       // It will be analyzed later.
3272       Vars.push_back(DE);
3273       continue;
3274     }
3275 
3276     // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3277     //   A threadprivate variable must not have an incomplete type.
3278     if (SemaRef.RequireCompleteType(
3279             ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) {
3280       continue;
3281     }
3282 
3283     // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3284     //   A threadprivate variable must not have a reference type.
3285     if (VD->getType()->isReferenceType()) {
3286       Diag(ILoc, diag::err_omp_ref_type_arg)
3287           << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
3288       bool IsDecl =
3289           VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3290       Diag(VD->getLocation(),
3291            IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3292           << VD;
3293       continue;
3294     }
3295 
3296     // Check if this is a TLS variable. If TLS is not being supported, produce
3297     // the corresponding diagnostic.
3298     if ((VD->getTLSKind() != VarDecl::TLS_None &&
3299          !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3300            getLangOpts().OpenMPUseTLS &&
3301            getASTContext().getTargetInfo().isTLSSupported())) ||
3302         (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3303          !VD->isLocalVarDecl())) {
3304       Diag(ILoc, diag::err_omp_var_thread_local)
3305           << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3306       bool IsDecl =
3307           VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3308       Diag(VD->getLocation(),
3309            IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3310           << VD;
3311       continue;
3312     }
3313 
3314     // Check if initial value of threadprivate variable reference variable with
3315     // local storage (it is not supported by runtime).
3316     if (const Expr *Init = VD->getAnyInitializer()) {
3317       LocalVarRefChecker Checker(SemaRef);
3318       if (Checker.Visit(Init))
3319         continue;
3320     }
3321 
3322     Vars.push_back(RefExpr);
3323     DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3324     VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3325         Context, SourceRange(Loc, Loc)));
3326     if (ASTMutationListener *ML = Context.getASTMutationListener())
3327       ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3328   }
3329   OMPThreadPrivateDecl *D = nullptr;
3330   if (!Vars.empty()) {
3331     D = OMPThreadPrivateDecl::Create(Context, SemaRef.getCurLexicalContext(),
3332                                      Loc, Vars);
3333     D->setAccess(AS_public);
3334   }
3335   return D;
3336 }
3337 
3338 static OMPAllocateDeclAttr::AllocatorTypeTy
getAllocatorKind(Sema & S,DSAStackTy * Stack,Expr * Allocator)3339 getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3340   if (!Allocator)
3341     return OMPAllocateDeclAttr::OMPNullMemAlloc;
3342   if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3343       Allocator->isInstantiationDependent() ||
3344       Allocator->containsUnexpandedParameterPack())
3345     return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3346   auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3347   llvm::FoldingSetNodeID AEId;
3348   const Expr *AE = Allocator->IgnoreParenImpCasts();
3349   AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3350   for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3351     auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3352     const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3353     llvm::FoldingSetNodeID DAEId;
3354     DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3355                                             /*Canonical=*/true);
3356     if (AEId == DAEId) {
3357       AllocatorKindRes = AllocatorKind;
3358       break;
3359     }
3360   }
3361   return AllocatorKindRes;
3362 }
3363 
checkPreviousOMPAllocateAttribute(Sema & S,DSAStackTy * Stack,Expr * RefExpr,VarDecl * VD,OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,Expr * Allocator)3364 static bool checkPreviousOMPAllocateAttribute(
3365     Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3366     OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3367   if (!VD->hasAttr<OMPAllocateDeclAttr>())
3368     return false;
3369   const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3370   Expr *PrevAllocator = A->getAllocator();
3371   OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3372       getAllocatorKind(S, Stack, PrevAllocator);
3373   bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3374   if (AllocatorsMatch &&
3375       AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3376       Allocator && PrevAllocator) {
3377     const Expr *AE = Allocator->IgnoreParenImpCasts();
3378     const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3379     llvm::FoldingSetNodeID AEId, PAEId;
3380     AE->Profile(AEId, S.Context, /*Canonical=*/true);
3381     PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3382     AllocatorsMatch = AEId == PAEId;
3383   }
3384   if (!AllocatorsMatch) {
3385     SmallString<256> AllocatorBuffer;
3386     llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3387     if (Allocator)
3388       Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3389     SmallString<256> PrevAllocatorBuffer;
3390     llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3391     if (PrevAllocator)
3392       PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3393                                  S.getPrintingPolicy());
3394 
3395     SourceLocation AllocatorLoc =
3396         Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3397     SourceRange AllocatorRange =
3398         Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3399     SourceLocation PrevAllocatorLoc =
3400         PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3401     SourceRange PrevAllocatorRange =
3402         PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3403     S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3404         << (Allocator ? 1 : 0) << AllocatorStream.str()
3405         << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3406         << AllocatorRange;
3407     S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3408         << PrevAllocatorRange;
3409     return true;
3410   }
3411   return false;
3412 }
3413 
3414 static void
applyOMPAllocateAttribute(Sema & S,VarDecl * VD,OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,Expr * Allocator,Expr * Alignment,SourceRange SR)3415 applyOMPAllocateAttribute(Sema &S, VarDecl *VD,
3416                           OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3417                           Expr *Allocator, Expr *Alignment, SourceRange SR) {
3418   if (VD->hasAttr<OMPAllocateDeclAttr>())
3419     return;
3420   if (Alignment &&
3421       (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3422        Alignment->isInstantiationDependent() ||
3423        Alignment->containsUnexpandedParameterPack()))
3424     // Apply later when we have a usable value.
3425     return;
3426   if (Allocator &&
3427       (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3428        Allocator->isInstantiationDependent() ||
3429        Allocator->containsUnexpandedParameterPack()))
3430     return;
3431   auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3432                                                 Allocator, Alignment, SR);
3433   VD->addAttr(A);
3434   if (ASTMutationListener *ML = S.Context.getASTMutationListener())
3435     ML->DeclarationMarkedOpenMPAllocate(VD, A);
3436 }
3437 
ActOnOpenMPAllocateDirective(SourceLocation Loc,ArrayRef<Expr * > VarList,ArrayRef<OMPClause * > Clauses,DeclContext * Owner)3438 SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPAllocateDirective(
3439     SourceLocation Loc, ArrayRef<Expr *> VarList, ArrayRef<OMPClause *> Clauses,
3440     DeclContext *Owner) {
3441   assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3442   Expr *Alignment = nullptr;
3443   Expr *Allocator = nullptr;
3444   if (Clauses.empty()) {
3445     // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3446     // allocate directives that appear in a target region must specify an
3447     // allocator clause unless a requires directive with the dynamic_allocators
3448     // clause is present in the same compilation unit.
3449     if (getLangOpts().OpenMPIsTargetDevice &&
3450         !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3451       SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3452   } else {
3453     for (const OMPClause *C : Clauses)
3454       if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3455         Allocator = AC->getAllocator();
3456       else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3457         Alignment = AC->getAlignment();
3458       else
3459         llvm_unreachable("Unexpected clause on allocate directive");
3460   }
3461   OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3462       getAllocatorKind(SemaRef, DSAStack, Allocator);
3463   SmallVector<Expr *, 8> Vars;
3464   for (Expr *RefExpr : VarList) {
3465     auto *DE = cast<DeclRefExpr>(RefExpr);
3466     auto *VD = cast<VarDecl>(DE->getDecl());
3467 
3468     // Check if this is a TLS variable or global register.
3469     if (VD->getTLSKind() != VarDecl::TLS_None ||
3470         VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3471         (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3472          !VD->isLocalVarDecl()))
3473       continue;
3474 
3475     // If the used several times in the allocate directive, the same allocator
3476     // must be used.
3477     if (checkPreviousOMPAllocateAttribute(SemaRef, DSAStack, RefExpr, VD,
3478                                           AllocatorKind, Allocator))
3479       continue;
3480 
3481     // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3482     // If a list item has a static storage type, the allocator expression in the
3483     // allocator clause must be a constant expression that evaluates to one of
3484     // the predefined memory allocator values.
3485     if (Allocator && VD->hasGlobalStorage()) {
3486       if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3487         Diag(Allocator->getExprLoc(),
3488              diag::err_omp_expected_predefined_allocator)
3489             << Allocator->getSourceRange();
3490         bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3491                       VarDecl::DeclarationOnly;
3492         Diag(VD->getLocation(),
3493              IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3494             << VD;
3495         continue;
3496       }
3497     }
3498 
3499     Vars.push_back(RefExpr);
3500     applyOMPAllocateAttribute(SemaRef, VD, AllocatorKind, Allocator, Alignment,
3501                               DE->getSourceRange());
3502   }
3503   if (Vars.empty())
3504     return nullptr;
3505   if (!Owner)
3506     Owner = SemaRef.getCurLexicalContext();
3507   auto *D = OMPAllocateDecl::Create(getASTContext(), Owner, Loc, Vars, Clauses);
3508   D->setAccess(AS_public);
3509   Owner->addDecl(D);
3510   return DeclGroupPtrTy::make(DeclGroupRef(D));
3511 }
3512 
3513 SemaOpenMP::DeclGroupPtrTy
ActOnOpenMPRequiresDirective(SourceLocation Loc,ArrayRef<OMPClause * > ClauseList)3514 SemaOpenMP::ActOnOpenMPRequiresDirective(SourceLocation Loc,
3515                                          ArrayRef<OMPClause *> ClauseList) {
3516   OMPRequiresDecl *D = nullptr;
3517   if (!SemaRef.CurContext->isFileContext()) {
3518     Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3519   } else {
3520     D = CheckOMPRequiresDecl(Loc, ClauseList);
3521     if (D) {
3522       SemaRef.CurContext->addDecl(D);
3523       DSAStack->addRequiresDecl(D);
3524     }
3525   }
3526   return DeclGroupPtrTy::make(DeclGroupRef(D));
3527 }
3528 
ActOnOpenMPAssumesDirective(SourceLocation Loc,OpenMPDirectiveKind DKind,ArrayRef<std::string> Assumptions,bool SkippedClauses)3529 void SemaOpenMP::ActOnOpenMPAssumesDirective(SourceLocation Loc,
3530                                              OpenMPDirectiveKind DKind,
3531                                              ArrayRef<std::string> Assumptions,
3532                                              bool SkippedClauses) {
3533   if (!SkippedClauses && Assumptions.empty())
3534     Diag(Loc, diag::err_omp_no_clause_for_directive)
3535         << llvm::omp::getAllAssumeClauseOptions()
3536         << llvm::omp::getOpenMPDirectiveName(DKind);
3537 
3538   auto *AA =
3539       OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc);
3540   if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3541     OMPAssumeScoped.push_back(AA);
3542     return;
3543   }
3544 
3545   // Global assumes without assumption clauses are ignored.
3546   if (Assumptions.empty())
3547     return;
3548 
3549   assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3550          "Unexpected omp assumption directive!");
3551   OMPAssumeGlobal.push_back(AA);
3552 
3553   // The OMPAssumeGlobal scope above will take care of new declarations but
3554   // we also want to apply the assumption to existing ones, e.g., to
3555   // declarations in included headers. To this end, we traverse all existing
3556   // declaration contexts and annotate function declarations here.
3557   SmallVector<DeclContext *, 8> DeclContexts;
3558   auto *Ctx = SemaRef.CurContext;
3559   while (Ctx->getLexicalParent())
3560     Ctx = Ctx->getLexicalParent();
3561   DeclContexts.push_back(Ctx);
3562   while (!DeclContexts.empty()) {
3563     DeclContext *DC = DeclContexts.pop_back_val();
3564     for (auto *SubDC : DC->decls()) {
3565       if (SubDC->isInvalidDecl())
3566         continue;
3567       if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3568         DeclContexts.push_back(CTD->getTemplatedDecl());
3569         llvm::append_range(DeclContexts, CTD->specializations());
3570         continue;
3571       }
3572       if (auto *DC = dyn_cast<DeclContext>(SubDC))
3573         DeclContexts.push_back(DC);
3574       if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3575         F->addAttr(AA);
3576         continue;
3577       }
3578     }
3579   }
3580 }
3581 
ActOnOpenMPEndAssumesDirective()3582 void SemaOpenMP::ActOnOpenMPEndAssumesDirective() {
3583   assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3584   OMPAssumeScoped.pop_back();
3585 }
3586 
3587 OMPRequiresDecl *
CheckOMPRequiresDecl(SourceLocation Loc,ArrayRef<OMPClause * > ClauseList)3588 SemaOpenMP::CheckOMPRequiresDecl(SourceLocation Loc,
3589                                  ArrayRef<OMPClause *> ClauseList) {
3590   /// For target specific clauses, the requires directive cannot be
3591   /// specified after the handling of any of the target regions in the
3592   /// current compilation unit.
3593   ArrayRef<SourceLocation> TargetLocations =
3594       DSAStack->getEncounteredTargetLocs();
3595   SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3596   if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3597     for (const OMPClause *CNew : ClauseList) {
3598       // Check if any of the requires clauses affect target regions.
3599       if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3600           isa<OMPUnifiedAddressClause>(CNew) ||
3601           isa<OMPReverseOffloadClause>(CNew) ||
3602           isa<OMPDynamicAllocatorsClause>(CNew)) {
3603         Diag(Loc, diag::err_omp_directive_before_requires)
3604             << "target" << getOpenMPClauseName(CNew->getClauseKind());
3605         for (SourceLocation TargetLoc : TargetLocations) {
3606           Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3607               << "target";
3608         }
3609       } else if (!AtomicLoc.isInvalid() &&
3610                  isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3611         Diag(Loc, diag::err_omp_directive_before_requires)
3612             << "atomic" << getOpenMPClauseName(CNew->getClauseKind());
3613         Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3614             << "atomic";
3615       }
3616     }
3617   }
3618 
3619   if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3620     return OMPRequiresDecl::Create(
3621         getASTContext(), SemaRef.getCurLexicalContext(), Loc, ClauseList);
3622   return nullptr;
3623 }
3624 
reportOriginalDsa(Sema & SemaRef,const DSAStackTy * Stack,const ValueDecl * D,const DSAStackTy::DSAVarData & DVar,bool IsLoopIterVar)3625 static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3626                               const ValueDecl *D,
3627                               const DSAStackTy::DSAVarData &DVar,
3628                               bool IsLoopIterVar) {
3629   if (DVar.RefExpr) {
3630     SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3631         << getOpenMPClauseName(DVar.CKind);
3632     return;
3633   }
3634   enum {
3635     PDSA_StaticMemberShared,
3636     PDSA_StaticLocalVarShared,
3637     PDSA_LoopIterVarPrivate,
3638     PDSA_LoopIterVarLinear,
3639     PDSA_LoopIterVarLastprivate,
3640     PDSA_ConstVarShared,
3641     PDSA_GlobalVarShared,
3642     PDSA_TaskVarFirstprivate,
3643     PDSA_LocalVarPrivate,
3644     PDSA_Implicit
3645   } Reason = PDSA_Implicit;
3646   bool ReportHint = false;
3647   auto ReportLoc = D->getLocation();
3648   auto *VD = dyn_cast<VarDecl>(D);
3649   if (IsLoopIterVar) {
3650     if (DVar.CKind == OMPC_private)
3651       Reason = PDSA_LoopIterVarPrivate;
3652     else if (DVar.CKind == OMPC_lastprivate)
3653       Reason = PDSA_LoopIterVarLastprivate;
3654     else
3655       Reason = PDSA_LoopIterVarLinear;
3656   } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3657              DVar.CKind == OMPC_firstprivate) {
3658     Reason = PDSA_TaskVarFirstprivate;
3659     ReportLoc = DVar.ImplicitDSALoc;
3660   } else if (VD && VD->isStaticLocal())
3661     Reason = PDSA_StaticLocalVarShared;
3662   else if (VD && VD->isStaticDataMember())
3663     Reason = PDSA_StaticMemberShared;
3664   else if (VD && VD->isFileVarDecl())
3665     Reason = PDSA_GlobalVarShared;
3666   else if (D->getType().isConstant(SemaRef.getASTContext()))
3667     Reason = PDSA_ConstVarShared;
3668   else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3669     ReportHint = true;
3670     Reason = PDSA_LocalVarPrivate;
3671   }
3672   if (Reason != PDSA_Implicit) {
3673     SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3674         << Reason << ReportHint
3675         << getOpenMPDirectiveName(Stack->getCurrentDirective());
3676   } else if (DVar.ImplicitDSALoc.isValid()) {
3677     SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3678         << getOpenMPClauseName(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 class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3728   DSAStackTy *Stack;
3729   Sema &SemaRef;
3730   bool ErrorFound = false;
3731   bool TryCaptureCXXThisMembers = false;
3732   CapturedStmt *CS = nullptr;
3733   const static unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3734   llvm::SmallVector<Expr *, 4> ImplicitFirstprivate;
3735   llvm::SmallVector<Expr *, 4> ImplicitPrivate;
3736   llvm::SmallVector<Expr *, 4> ImplicitMap[DefaultmapKindNum][OMPC_MAP_delete];
3737   llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3738       ImplicitMapModifier[DefaultmapKindNum];
3739   SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3740   llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3741 
VisitSubCaptures(OMPExecutableDirective * S)3742   void VisitSubCaptures(OMPExecutableDirective *S) {
3743     // Check implicitly captured variables.
3744     if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3745       return;
3746     if (S->getDirectiveKind() == OMPD_atomic ||
3747         S->getDirectiveKind() == OMPD_critical ||
3748         S->getDirectiveKind() == OMPD_section ||
3749         S->getDirectiveKind() == OMPD_master ||
3750         S->getDirectiveKind() == OMPD_masked ||
3751         S->getDirectiveKind() == OMPD_scope ||
3752         isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3753       Visit(S->getAssociatedStmt());
3754       return;
3755     }
3756     visitSubCaptures(S->getInnermostCapturedStmt());
3757     // Try to capture inner this->member references to generate correct mappings
3758     // and diagnostics.
3759     if (TryCaptureCXXThisMembers ||
3760         (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
3761          llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3762                       [](const CapturedStmt::Capture &C) {
3763                         return C.capturesThis();
3764                       }))) {
3765       bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3766       TryCaptureCXXThisMembers = true;
3767       Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3768       TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3769     }
3770     // In tasks firstprivates are not captured anymore, need to analyze them
3771     // explicitly.
3772     if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3773         !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3774       for (OMPClause *C : S->clauses())
3775         if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3776           for (Expr *Ref : FC->varlists())
3777             Visit(Ref);
3778         }
3779     }
3780   }
3781 
3782 public:
VisitDeclRefExpr(DeclRefExpr * E)3783   void VisitDeclRefExpr(DeclRefExpr *E) {
3784     if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3785         E->isValueDependent() || E->containsUnexpandedParameterPack() ||
3786         E->isInstantiationDependent() ||
3787         E->isNonOdrUse() == clang::NOUR_Unevaluated)
3788       return;
3789     if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3790       // Check the datasharing rules for the expressions in the clauses.
3791       if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3792                   !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3793                   !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3794         if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3795           if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3796             Visit(CED->getInit());
3797             return;
3798           }
3799       } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3800         // Do not analyze internal variables and do not enclose them into
3801         // implicit clauses.
3802         if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3803           return;
3804       VD = VD->getCanonicalDecl();
3805       // Skip internally declared variables.
3806       if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3807           !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3808           !Stack->isImplicitTaskFirstprivate(VD))
3809         return;
3810       // Skip allocators in uses_allocators clauses.
3811       if (Stack->isUsesAllocatorsDecl(VD))
3812         return;
3813 
3814       DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3815       // Check if the variable has explicit DSA set and stop analysis if it so.
3816       if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3817         return;
3818 
3819       // Skip internally declared static variables.
3820       std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3821           OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3822       if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3823           (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3824            !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3825           !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3826           !Stack->isImplicitTaskFirstprivate(VD))
3827         return;
3828 
3829       SourceLocation ELoc = E->getExprLoc();
3830       OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3831       // The default(none) clause requires that each variable that is referenced
3832       // in the construct, and does not have a predetermined data-sharing
3833       // attribute, must have its data-sharing attribute explicitly determined
3834       // by being listed in a data-sharing attribute clause.
3835       if (DVar.CKind == OMPC_unknown &&
3836           (Stack->getDefaultDSA() == DSA_none ||
3837            Stack->getDefaultDSA() == DSA_private ||
3838            Stack->getDefaultDSA() == DSA_firstprivate) &&
3839           isImplicitOrExplicitTaskingRegion(DKind) &&
3840           VarsWithInheritedDSA.count(VD) == 0) {
3841         bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3842         if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3843                               Stack->getDefaultDSA() == DSA_private)) {
3844           DSAStackTy::DSAVarData DVar =
3845               Stack->getImplicitDSA(VD, /*FromParent=*/false);
3846           InheritedDSA = DVar.CKind == OMPC_unknown;
3847         }
3848         if (InheritedDSA)
3849           VarsWithInheritedDSA[VD] = E;
3850         if (Stack->getDefaultDSA() == DSA_none)
3851           return;
3852       }
3853 
3854       // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3855       // If implicit-behavior is none, each variable referenced in the
3856       // construct that does not have a predetermined data-sharing attribute
3857       // and does not appear in a to or link clause on a declare target
3858       // directive must be listed in a data-mapping attribute clause, a
3859       // data-sharing attribute clause (including a data-sharing attribute
3860       // clause on a combined construct where target. is one of the
3861       // constituent constructs), or an is_device_ptr clause.
3862       OpenMPDefaultmapClauseKind ClauseKind =
3863           getVariableCategoryFromDecl(SemaRef.getLangOpts(), VD);
3864       if (SemaRef.getLangOpts().OpenMP >= 50) {
3865         bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3866                               OMPC_DEFAULTMAP_MODIFIER_none;
3867         if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3868             VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3869           // Only check for data-mapping attribute and is_device_ptr here
3870           // since we have already make sure that the declaration does not
3871           // have a data-sharing attribute above
3872           if (!Stack->checkMappableExprComponentListsForDecl(
3873                   VD, /*CurrentRegionOnly=*/true,
3874                   [VD](OMPClauseMappableExprCommon::MappableExprComponentListRef
3875                            MapExprComponents,
3876                        OpenMPClauseKind) {
3877                     auto MI = MapExprComponents.rbegin();
3878                     auto ME = MapExprComponents.rend();
3879                     return MI != ME && MI->getAssociatedDeclaration() == VD;
3880                   })) {
3881             VarsWithInheritedDSA[VD] = E;
3882             return;
3883           }
3884         }
3885       }
3886       if (SemaRef.getLangOpts().OpenMP > 50) {
3887         bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3888                                  OMPC_DEFAULTMAP_MODIFIER_present;
3889         if (IsModifierPresent) {
3890           if (!llvm::is_contained(ImplicitMapModifier[ClauseKind],
3891                                   OMPC_MAP_MODIFIER_present)) {
3892             ImplicitMapModifier[ClauseKind].push_back(
3893                 OMPC_MAP_MODIFIER_present);
3894           }
3895         }
3896       }
3897 
3898       if (isOpenMPTargetExecutionDirective(DKind) &&
3899           !Stack->isLoopControlVariable(VD).first) {
3900         if (!Stack->checkMappableExprComponentListsForDecl(
3901                 VD, /*CurrentRegionOnly=*/true,
3902                 [this](OMPClauseMappableExprCommon::MappableExprComponentListRef
3903                            StackComponents,
3904                        OpenMPClauseKind) {
3905                   if (SemaRef.LangOpts.OpenMP >= 50)
3906                     return !StackComponents.empty();
3907                   // Variable is used if it has been marked as an array, array
3908                   // section, array shaping or the variable itself.
3909                   return StackComponents.size() == 1 ||
3910                          llvm::all_of(
3911                              llvm::drop_begin(llvm::reverse(StackComponents)),
3912                              [](const OMPClauseMappableExprCommon::
3913                                     MappableComponent &MC) {
3914                                return MC.getAssociatedDeclaration() ==
3915                                           nullptr &&
3916                                       (isa<ArraySectionExpr>(
3917                                            MC.getAssociatedExpression()) ||
3918                                        isa<OMPArrayShapingExpr>(
3919                                            MC.getAssociatedExpression()) ||
3920                                        isa<ArraySubscriptExpr>(
3921                                            MC.getAssociatedExpression()));
3922                              });
3923                 })) {
3924           bool IsFirstprivate = false;
3925           // By default lambdas are captured as firstprivates.
3926           if (const auto *RD =
3927                   VD->getType().getNonReferenceType()->getAsCXXRecordDecl())
3928             IsFirstprivate = RD->isLambda();
3929           IsFirstprivate =
3930               IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3931           if (IsFirstprivate) {
3932             ImplicitFirstprivate.emplace_back(E);
3933           } else {
3934             OpenMPDefaultmapClauseModifier M =
3935                 Stack->getDefaultmapModifier(ClauseKind);
3936             OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
3937                 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3938             ImplicitMap[ClauseKind][Kind].emplace_back(E);
3939           }
3940           return;
3941         }
3942       }
3943 
3944       // OpenMP [2.9.3.6, Restrictions, p.2]
3945       //  A list item that appears in a reduction clause of the innermost
3946       //  enclosing worksharing or parallel construct may not be accessed in an
3947       //  explicit task.
3948       DVar = Stack->hasInnermostDSA(
3949           VD,
3950           [](OpenMPClauseKind C, bool AppliedToPointee) {
3951             return C == OMPC_reduction && !AppliedToPointee;
3952           },
3953           [](OpenMPDirectiveKind K) {
3954             return isOpenMPParallelDirective(K) ||
3955                    isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
3956           },
3957           /*FromParent=*/true);
3958       if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3959         ErrorFound = true;
3960         SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3961         reportOriginalDsa(SemaRef, Stack, VD, DVar);
3962         return;
3963       }
3964 
3965       // Define implicit data-sharing attributes for task.
3966       DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
3967       if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
3968            (((Stack->getDefaultDSA() == DSA_firstprivate &&
3969               DVar.CKind == OMPC_firstprivate) ||
3970              (Stack->getDefaultDSA() == DSA_private &&
3971               DVar.CKind == OMPC_private)) &&
3972             !DVar.RefExpr)) &&
3973           !Stack->isLoopControlVariable(VD).first) {
3974         if (Stack->getDefaultDSA() == DSA_private)
3975           ImplicitPrivate.push_back(E);
3976         else
3977           ImplicitFirstprivate.push_back(E);
3978         return;
3979       }
3980 
3981       // Store implicitly used globals with declare target link for parent
3982       // target.
3983       if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
3984           *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3985         Stack->addToParentTargetRegionLinkGlobals(E);
3986         return;
3987       }
3988     }
3989   }
VisitMemberExpr(MemberExpr * E)3990   void VisitMemberExpr(MemberExpr *E) {
3991     if (E->isTypeDependent() || E->isValueDependent() ||
3992         E->containsUnexpandedParameterPack() || E->isInstantiationDependent())
3993       return;
3994     auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
3995     OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3996     if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
3997       if (!FD)
3998         return;
3999       DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
4000       // Check if the variable has explicit DSA set and stop analysis if it
4001       // so.
4002       if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
4003         return;
4004 
4005       if (isOpenMPTargetExecutionDirective(DKind) &&
4006           !Stack->isLoopControlVariable(FD).first &&
4007           !Stack->checkMappableExprComponentListsForDecl(
4008               FD, /*CurrentRegionOnly=*/true,
4009               [](OMPClauseMappableExprCommon::MappableExprComponentListRef
4010                      StackComponents,
4011                  OpenMPClauseKind) {
4012                 return isa<CXXThisExpr>(
4013                     cast<MemberExpr>(
4014                         StackComponents.back().getAssociatedExpression())
4015                         ->getBase()
4016                         ->IgnoreParens());
4017               })) {
4018         // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
4019         //  A bit-field cannot appear in a map clause.
4020         //
4021         if (FD->isBitField())
4022           return;
4023 
4024         // Check to see if the member expression is referencing a class that
4025         // has already been explicitly mapped
4026         if (Stack->isClassPreviouslyMapped(TE->getType()))
4027           return;
4028 
4029         OpenMPDefaultmapClauseModifier Modifier =
4030             Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4031         OpenMPDefaultmapClauseKind ClauseKind =
4032             getVariableCategoryFromDecl(SemaRef.getLangOpts(), FD);
4033         OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
4034             Modifier, /*IsAggregateOrDeclareTarget*/ true);
4035         ImplicitMap[ClauseKind][Kind].emplace_back(E);
4036         return;
4037       }
4038 
4039       SourceLocation ELoc = E->getExprLoc();
4040       // OpenMP [2.9.3.6, Restrictions, p.2]
4041       //  A list item that appears in a reduction clause of the innermost
4042       //  enclosing worksharing or parallel construct may not be accessed in
4043       //  an  explicit task.
4044       DVar = Stack->hasInnermostDSA(
4045           FD,
4046           [](OpenMPClauseKind C, bool AppliedToPointee) {
4047             return C == OMPC_reduction && !AppliedToPointee;
4048           },
4049           [](OpenMPDirectiveKind K) {
4050             return isOpenMPParallelDirective(K) ||
4051                    isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
4052           },
4053           /*FromParent=*/true);
4054       if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4055         ErrorFound = true;
4056         SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4057         reportOriginalDsa(SemaRef, Stack, FD, DVar);
4058         return;
4059       }
4060 
4061       // Define implicit data-sharing attributes for task.
4062       DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4063       if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4064           !Stack->isLoopControlVariable(FD).first) {
4065         // Check if there is a captured expression for the current field in the
4066         // region. Do not mark it as firstprivate unless there is no captured
4067         // expression.
4068         // TODO: try to make it firstprivate.
4069         if (DVar.CKind != OMPC_unknown)
4070           ImplicitFirstprivate.push_back(E);
4071       }
4072       return;
4073     }
4074     if (isOpenMPTargetExecutionDirective(DKind)) {
4075       OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
4076       if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4077                                         Stack->getCurrentDirective(),
4078                                         /*NoDiagnose=*/true))
4079         return;
4080       const auto *VD = cast<ValueDecl>(
4081           CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4082       if (!Stack->checkMappableExprComponentListsForDecl(
4083               VD, /*CurrentRegionOnly=*/true,
4084               [&CurComponents](
4085                   OMPClauseMappableExprCommon::MappableExprComponentListRef
4086                       StackComponents,
4087                   OpenMPClauseKind) {
4088                 auto CCI = CurComponents.rbegin();
4089                 auto CCE = CurComponents.rend();
4090                 for (const auto &SC : llvm::reverse(StackComponents)) {
4091                   // Do both expressions have the same kind?
4092                   if (CCI->getAssociatedExpression()->getStmtClass() !=
4093                       SC.getAssociatedExpression()->getStmtClass())
4094                     if (!((isa<ArraySectionExpr>(
4095                                SC.getAssociatedExpression()) ||
4096                            isa<OMPArrayShapingExpr>(
4097                                SC.getAssociatedExpression())) &&
4098                           isa<ArraySubscriptExpr>(
4099                               CCI->getAssociatedExpression())))
4100                       return false;
4101 
4102                   const Decl *CCD = CCI->getAssociatedDeclaration();
4103                   const Decl *SCD = SC.getAssociatedDeclaration();
4104                   CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4105                   SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4106                   if (SCD != CCD)
4107                     return false;
4108                   std::advance(CCI, 1);
4109                   if (CCI == CCE)
4110                     break;
4111                 }
4112                 return true;
4113               })) {
4114         Visit(E->getBase());
4115       }
4116     } else if (!TryCaptureCXXThisMembers) {
4117       Visit(E->getBase());
4118     }
4119   }
VisitOMPExecutableDirective(OMPExecutableDirective * S)4120   void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4121     for (OMPClause *C : S->clauses()) {
4122       // Skip analysis of arguments of private clauses for task|target
4123       // directives.
4124       if (isa_and_nonnull<OMPPrivateClause>(C))
4125         continue;
4126       // Skip analysis of arguments of implicitly defined firstprivate clause
4127       // for task|target directives.
4128       // Skip analysis of arguments of implicitly defined map clause for target
4129       // directives.
4130       if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
4131                  C->isImplicit() &&
4132                  !isOpenMPTaskingDirective(Stack->getCurrentDirective()))) {
4133         for (Stmt *CC : C->children()) {
4134           if (CC)
4135             Visit(CC);
4136         }
4137       }
4138     }
4139     // Check implicitly captured variables.
4140     VisitSubCaptures(S);
4141   }
4142 
VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective * S)4143   void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) {
4144     // Loop transformation directives do not introduce data sharing
4145     VisitStmt(S);
4146   }
4147 
VisitCallExpr(CallExpr * S)4148   void VisitCallExpr(CallExpr *S) {
4149     for (Stmt *C : S->arguments()) {
4150       if (C) {
4151         // Check implicitly captured variables in the task-based directives to
4152         // check if they must be firstprivatized.
4153         Visit(C);
4154       }
4155     }
4156     if (Expr *Callee = S->getCallee()) {
4157       auto *CI = Callee->IgnoreParenImpCasts();
4158       if (auto *CE = dyn_cast<MemberExpr>(CI))
4159         Visit(CE->getBase());
4160       else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4161         Visit(CE);
4162     }
4163   }
VisitStmt(Stmt * S)4164   void VisitStmt(Stmt *S) {
4165     for (Stmt *C : S->children()) {
4166       if (C) {
4167         // Check implicitly captured variables in the task-based directives to
4168         // check if they must be firstprivatized.
4169         Visit(C);
4170       }
4171     }
4172   }
4173 
visitSubCaptures(CapturedStmt * S)4174   void visitSubCaptures(CapturedStmt *S) {
4175     for (const CapturedStmt::Capture &Cap : S->captures()) {
4176       if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4177         continue;
4178       VarDecl *VD = Cap.getCapturedVar();
4179       // Do not try to map the variable if it or its sub-component was mapped
4180       // already.
4181       if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
4182           Stack->checkMappableExprComponentListsForDecl(
4183               VD, /*CurrentRegionOnly=*/true,
4184               [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
4185                  OpenMPClauseKind) { return true; }))
4186         continue;
4187       DeclRefExpr *DRE = buildDeclRefExpr(
4188           SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4189           Cap.getLocation(), /*RefersToCapture=*/true);
4190       Visit(DRE);
4191     }
4192   }
isErrorFound() const4193   bool isErrorFound() const { return ErrorFound; }
getImplicitFirstprivate() const4194   ArrayRef<Expr *> getImplicitFirstprivate() const {
4195     return ImplicitFirstprivate;
4196   }
getImplicitPrivate() const4197   ArrayRef<Expr *> getImplicitPrivate() const { return ImplicitPrivate; }
getImplicitMap(OpenMPDefaultmapClauseKind DK,OpenMPMapClauseKind MK) const4198   ArrayRef<Expr *> getImplicitMap(OpenMPDefaultmapClauseKind DK,
4199                                   OpenMPMapClauseKind MK) const {
4200     return ImplicitMap[DK][MK];
4201   }
4202   ArrayRef<OpenMPMapModifierKind>
getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind) const4203   getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind) const {
4204     return ImplicitMapModifier[Kind];
4205   }
getVarsWithInheritedDSA() const4206   const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4207     return VarsWithInheritedDSA;
4208   }
4209 
DSAAttrChecker(DSAStackTy * S,Sema & SemaRef,CapturedStmt * CS)4210   DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4211       : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4212     // Process declare target link variables for the target directives.
4213     if (isOpenMPTargetExecutionDirective(S->getCurrentDirective())) {
4214       for (DeclRefExpr *E : Stack->getLinkGlobals())
4215         Visit(E);
4216     }
4217   }
4218 };
4219 } // namespace
4220 
handleDeclareVariantConstructTrait(DSAStackTy * Stack,OpenMPDirectiveKind DKind,bool ScopeEntry)4221 static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4222                                                OpenMPDirectiveKind DKind,
4223                                                bool ScopeEntry) {
4224   SmallVector<llvm::omp::TraitProperty, 8> Traits;
4225   if (isOpenMPTargetExecutionDirective(DKind))
4226     Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4227   if (isOpenMPTeamsDirective(DKind))
4228     Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4229   if (isOpenMPParallelDirective(DKind))
4230     Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4231   if (isOpenMPWorksharingDirective(DKind))
4232     Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4233   if (isOpenMPSimdDirective(DKind))
4234     Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4235   Stack->handleConstructTrait(Traits, ScopeEntry);
4236 }
4237 
4238 static SmallVector<SemaOpenMP::CapturedParamNameType>
getParallelRegionParams(Sema & SemaRef,bool LoopBoundSharing)4239 getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4240   ASTContext &Context = SemaRef.getASTContext();
4241   QualType KmpInt32Ty =
4242       Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4243   QualType KmpInt32PtrTy =
4244       Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4245   SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4246       std::make_pair(".global_tid.", KmpInt32PtrTy),
4247       std::make_pair(".bound_tid.", KmpInt32PtrTy),
4248   };
4249   if (LoopBoundSharing) {
4250     QualType KmpSizeTy = Context.getSizeType().withConst();
4251     Params.push_back(std::make_pair(".previous.lb.", KmpSizeTy));
4252     Params.push_back(std::make_pair(".previous.ub.", KmpSizeTy));
4253   }
4254 
4255   // __context with shared vars
4256   Params.push_back(std::make_pair(StringRef(), QualType()));
4257   return Params;
4258 }
4259 
4260 static SmallVector<SemaOpenMP::CapturedParamNameType>
getTeamsRegionParams(Sema & SemaRef)4261 getTeamsRegionParams(Sema &SemaRef) {
4262   return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4263 }
4264 
4265 static SmallVector<SemaOpenMP::CapturedParamNameType>
getTaskRegionParams(Sema & SemaRef)4266 getTaskRegionParams(Sema &SemaRef) {
4267   ASTContext &Context = SemaRef.getASTContext();
4268   QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4269   QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4270   QualType KmpInt32PtrTy =
4271       Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4272   QualType Args[] = {VoidPtrTy};
4273   FunctionProtoType::ExtProtoInfo EPI;
4274   EPI.Variadic = true;
4275   QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4276   SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4277       std::make_pair(".global_tid.", KmpInt32Ty),
4278       std::make_pair(".part_id.", KmpInt32PtrTy),
4279       std::make_pair(".privates.", VoidPtrTy),
4280       std::make_pair(
4281           ".copy_fn.",
4282           Context.getPointerType(CopyFnType).withConst().withRestrict()),
4283       std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4284       std::make_pair(StringRef(), QualType()) // __context with shared vars
4285   };
4286   return Params;
4287 }
4288 
4289 static SmallVector<SemaOpenMP::CapturedParamNameType>
getTargetRegionParams(Sema & SemaRef)4290 getTargetRegionParams(Sema &SemaRef) {
4291   ASTContext &Context = SemaRef.getASTContext();
4292   SmallVector<SemaOpenMP::CapturedParamNameType> Params;
4293   if (SemaRef.getLangOpts().OpenMPIsTargetDevice) {
4294     QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4295     Params.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4296   }
4297   // __context with shared vars
4298   Params.push_back(std::make_pair(StringRef(), QualType()));
4299   return Params;
4300 }
4301 
4302 static SmallVector<SemaOpenMP::CapturedParamNameType>
getUnknownRegionParams(Sema & SemaRef)4303 getUnknownRegionParams(Sema &SemaRef) {
4304   SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4305       std::make_pair(StringRef(), QualType()) // __context with shared vars
4306   };
4307   return Params;
4308 }
4309 
4310 static SmallVector<SemaOpenMP::CapturedParamNameType>
getTaskloopRegionParams(Sema & SemaRef)4311 getTaskloopRegionParams(Sema &SemaRef) {
4312   ASTContext &Context = SemaRef.getASTContext();
4313   QualType KmpInt32Ty =
4314       Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4315   QualType KmpUInt64Ty =
4316       Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4317   QualType KmpInt64Ty =
4318       Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4319   QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4320   QualType KmpInt32PtrTy =
4321       Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4322   QualType Args[] = {VoidPtrTy};
4323   FunctionProtoType::ExtProtoInfo EPI;
4324   EPI.Variadic = true;
4325   QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4326   SmallVector<SemaOpenMP::CapturedParamNameType> Params{
4327       std::make_pair(".global_tid.", KmpInt32Ty),
4328       std::make_pair(".part_id.", KmpInt32PtrTy),
4329       std::make_pair(".privates.", VoidPtrTy),
4330       std::make_pair(
4331           ".copy_fn.",
4332           Context.getPointerType(CopyFnType).withConst().withRestrict()),
4333       std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4334       std::make_pair(".lb.", KmpUInt64Ty),
4335       std::make_pair(".ub.", KmpUInt64Ty),
4336       std::make_pair(".st.", KmpInt64Ty),
4337       std::make_pair(".liter.", KmpInt32Ty),
4338       std::make_pair(".reductions.", VoidPtrTy),
4339       std::make_pair(StringRef(), QualType()) // __context with shared vars
4340   };
4341   return Params;
4342 }
4343 
processCapturedRegions(Sema & SemaRef,OpenMPDirectiveKind DKind,Scope * CurScope,SourceLocation Loc)4344 static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind,
4345                                    Scope *CurScope, SourceLocation Loc) {
4346   SmallVector<OpenMPDirectiveKind> Regions;
4347   getOpenMPCaptureRegions(Regions, DKind);
4348 
4349   bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(DKind);
4350 
4351   auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4352     CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4353         SemaRef.getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4354   };
4355 
4356   for (auto [Level, RKind] : llvm::enumerate(Regions)) {
4357     switch (RKind) {
4358     // All region kinds that can be returned from `getOpenMPCaptureRegions`
4359     // are listed here.
4360     case OMPD_parallel:
4361       SemaRef.ActOnCapturedRegionStart(
4362           Loc, CurScope, CR_OpenMP,
4363           getParallelRegionParams(SemaRef, LoopBoundSharing), Level);
4364       break;
4365     case OMPD_teams:
4366       SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4367                                        getTeamsRegionParams(SemaRef), Level);
4368       break;
4369     case OMPD_task:
4370       SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4371                                        getTaskRegionParams(SemaRef), Level);
4372       // Mark this captured region as inlined, because we don't use outlined
4373       // function directly.
4374       MarkAsInlined(SemaRef.getCurCapturedRegion());
4375       break;
4376     case OMPD_taskloop:
4377       SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4378                                        getTaskloopRegionParams(SemaRef), Level);
4379       // Mark this captured region as inlined, because we don't use outlined
4380       // function directly.
4381       MarkAsInlined(SemaRef.getCurCapturedRegion());
4382       break;
4383     case OMPD_target:
4384       SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4385                                        getTargetRegionParams(SemaRef), Level);
4386       break;
4387     case OMPD_unknown:
4388       SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4389                                        getUnknownRegionParams(SemaRef));
4390       break;
4391     case OMPD_metadirective:
4392     case OMPD_nothing:
4393     default:
4394       llvm_unreachable("Unexpected capture region");
4395     }
4396   }
4397 }
4398 
ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind,Scope * CurScope)4399 void SemaOpenMP::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind,
4400                                         Scope *CurScope) {
4401   switch (DKind) {
4402   case OMPD_atomic:
4403   case OMPD_critical:
4404   case OMPD_masked:
4405   case OMPD_master:
4406   case OMPD_section:
4407   case OMPD_tile:
4408   case OMPD_unroll:
4409   case OMPD_reverse:
4410   case OMPD_interchange:
4411     break;
4412   default:
4413     processCapturedRegions(SemaRef, DKind, CurScope,
4414                            DSAStack->getConstructLoc());
4415     break;
4416   }
4417 
4418   DSAStack->setContext(SemaRef.CurContext);
4419   handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
4420 }
4421 
getNumberOfConstructScopes(unsigned Level) const4422 int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4423   return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4424 }
4425 
getOpenMPCaptureLevels(OpenMPDirectiveKind DKind)4426 int SemaOpenMP::getOpenMPCaptureLevels(OpenMPDirectiveKind DKind) {
4427   SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4428   getOpenMPCaptureRegions(CaptureRegions, DKind);
4429   return CaptureRegions.size();
4430 }
4431 
buildCaptureDecl(Sema & S,IdentifierInfo * Id,Expr * CaptureExpr,bool WithInit,DeclContext * CurContext,bool AsExpression)4432 static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
4433                                              Expr *CaptureExpr, bool WithInit,
4434                                              DeclContext *CurContext,
4435                                              bool AsExpression) {
4436   assert(CaptureExpr);
4437   ASTContext &C = S.getASTContext();
4438   Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4439   QualType Ty = Init->getType();
4440   if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4441     if (S.getLangOpts().CPlusPlus) {
4442       Ty = C.getLValueReferenceType(Ty);
4443     } else {
4444       Ty = C.getPointerType(Ty);
4445       ExprResult Res =
4446           S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4447       if (!Res.isUsable())
4448         return nullptr;
4449       Init = Res.get();
4450     }
4451     WithInit = true;
4452   }
4453   auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4454                                           CaptureExpr->getBeginLoc());
4455   if (!WithInit)
4456     CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4457   CurContext->addHiddenDecl(CED);
4458   Sema::TentativeAnalysisScope Trap(S);
4459   S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4460   return CED;
4461 }
4462 
buildCapture(Sema & S,ValueDecl * D,Expr * CaptureExpr,bool WithInit)4463 static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4464                                  bool WithInit) {
4465   OMPCapturedExprDecl *CD;
4466   if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4467     CD = cast<OMPCapturedExprDecl>(VD);
4468   else
4469     CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4470                           S.CurContext,
4471                           /*AsExpression=*/false);
4472   return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4473                           CaptureExpr->getExprLoc());
4474 }
4475 
buildCapture(Sema & S,Expr * CaptureExpr,DeclRefExpr * & Ref,StringRef Name)4476 static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4477                                StringRef Name) {
4478   CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4479   if (!Ref) {
4480     OMPCapturedExprDecl *CD = buildCaptureDecl(
4481         S, &S.getASTContext().Idents.get(Name), CaptureExpr,
4482         /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4483     Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4484                            CaptureExpr->getExprLoc());
4485   }
4486   ExprResult Res = Ref;
4487   if (!S.getLangOpts().CPlusPlus &&
4488       CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4489       Ref->getType()->isPointerType()) {
4490     Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4491     if (!Res.isUsable())
4492       return ExprError();
4493   }
4494   return S.DefaultLvalueConversion(Res.get());
4495 }
4496 
4497 namespace {
4498 // OpenMP directives parsed in this section are represented as a
4499 // CapturedStatement with an associated statement.  If a syntax error
4500 // is detected during the parsing of the associated statement, the
4501 // compiler must abort processing and close the CapturedStatement.
4502 //
4503 // Combined directives such as 'target parallel' have more than one
4504 // nested CapturedStatements.  This RAII ensures that we unwind out
4505 // of all the nested CapturedStatements when an error is found.
4506 class CaptureRegionUnwinderRAII {
4507 private:
4508   Sema &S;
4509   bool &ErrorFound;
4510   OpenMPDirectiveKind DKind = OMPD_unknown;
4511 
4512 public:
CaptureRegionUnwinderRAII(Sema & S,bool & ErrorFound,OpenMPDirectiveKind DKind)4513   CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4514                             OpenMPDirectiveKind DKind)
4515       : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
~CaptureRegionUnwinderRAII()4516   ~CaptureRegionUnwinderRAII() {
4517     if (ErrorFound) {
4518       int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4519       while (--ThisCaptureLevel >= 0)
4520         S.ActOnCapturedRegionError();
4521     }
4522   }
4523 };
4524 } // namespace
4525 
tryCaptureOpenMPLambdas(ValueDecl * V)4526 void SemaOpenMP::tryCaptureOpenMPLambdas(ValueDecl *V) {
4527   // Capture variables captured by reference in lambdas for target-based
4528   // directives.
4529   if (!SemaRef.CurContext->isDependentContext() &&
4530       (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4531        isOpenMPTargetDataManagementDirective(
4532            DSAStack->getCurrentDirective()))) {
4533     QualType Type = V->getType();
4534     if (const auto *RD = Type.getCanonicalType()
4535                              .getNonReferenceType()
4536                              ->getAsCXXRecordDecl()) {
4537       bool SavedForceCaptureByReferenceInTargetExecutable =
4538           DSAStack->isForceCaptureByReferenceInTargetExecutable();
4539       DSAStack->setForceCaptureByReferenceInTargetExecutable(
4540           /*V=*/true);
4541       if (RD->isLambda()) {
4542         llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4543         FieldDecl *ThisCapture;
4544         RD->getCaptureFields(Captures, ThisCapture);
4545         for (const LambdaCapture &LC : RD->captures()) {
4546           if (LC.getCaptureKind() == LCK_ByRef) {
4547             VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4548             DeclContext *VDC = VD->getDeclContext();
4549             if (!VDC->Encloses(SemaRef.CurContext))
4550               continue;
4551             SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
4552           } else if (LC.getCaptureKind() == LCK_This) {
4553             QualType ThisTy = SemaRef.getCurrentThisType();
4554             if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4555                                         ThisTy, ThisCapture->getType()))
4556               SemaRef.CheckCXXThisCapture(LC.getLocation());
4557           }
4558         }
4559       }
4560       DSAStack->setForceCaptureByReferenceInTargetExecutable(
4561           SavedForceCaptureByReferenceInTargetExecutable);
4562     }
4563   }
4564 }
4565 
checkOrderedOrderSpecified(Sema & S,const ArrayRef<OMPClause * > Clauses)4566 static bool checkOrderedOrderSpecified(Sema &S,
4567                                        const ArrayRef<OMPClause *> Clauses) {
4568   const OMPOrderedClause *Ordered = nullptr;
4569   const OMPOrderClause *Order = nullptr;
4570 
4571   for (const OMPClause *Clause : Clauses) {
4572     if (Clause->getClauseKind() == OMPC_ordered)
4573       Ordered = cast<OMPOrderedClause>(Clause);
4574     else if (Clause->getClauseKind() == OMPC_order) {
4575       Order = cast<OMPOrderClause>(Clause);
4576       if (Order->getKind() != OMPC_ORDER_concurrent)
4577         Order = nullptr;
4578     }
4579     if (Ordered && Order)
4580       break;
4581   }
4582 
4583   if (Ordered && Order) {
4584     S.Diag(Order->getKindKwLoc(),
4585            diag::err_omp_simple_clause_incompatible_with_ordered)
4586         << getOpenMPClauseName(OMPC_order)
4587         << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4588         << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4589     S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4590         << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4591     return true;
4592   }
4593   return false;
4594 }
4595 
ActOnOpenMPRegionEnd(StmtResult S,ArrayRef<OMPClause * > Clauses)4596 StmtResult SemaOpenMP::ActOnOpenMPRegionEnd(StmtResult S,
4597                                             ArrayRef<OMPClause *> Clauses) {
4598   handleDeclareVariantConstructTrait(DSAStack, DSAStack->getCurrentDirective(),
4599                                      /* ScopeEntry */ false);
4600   if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
4601     return S;
4602 
4603   bool ErrorFound = false;
4604   CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4605       SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4606   if (!S.isUsable()) {
4607     ErrorFound = true;
4608     return StmtError();
4609   }
4610 
4611   SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4612   getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4613   OMPOrderedClause *OC = nullptr;
4614   OMPScheduleClause *SC = nullptr;
4615   SmallVector<const OMPLinearClause *, 4> LCs;
4616   SmallVector<const OMPClauseWithPreInit *, 4> PICs;
4617   // This is required for proper codegen.
4618   for (OMPClause *Clause : Clauses) {
4619     if (!getLangOpts().OpenMPSimd &&
4620         (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4621          DSAStack->getCurrentDirective() == OMPD_target) &&
4622         Clause->getClauseKind() == OMPC_in_reduction) {
4623       // Capture taskgroup task_reduction descriptors inside the tasking regions
4624       // with the corresponding in_reduction items.
4625       auto *IRC = cast<OMPInReductionClause>(Clause);
4626       for (Expr *E : IRC->taskgroup_descriptors())
4627         if (E)
4628           SemaRef.MarkDeclarationsReferencedInExpr(E);
4629     }
4630     if (isOpenMPPrivate(Clause->getClauseKind()) ||
4631         Clause->getClauseKind() == OMPC_copyprivate ||
4632         (getLangOpts().OpenMPUseTLS &&
4633          getASTContext().getTargetInfo().isTLSSupported() &&
4634          Clause->getClauseKind() == OMPC_copyin)) {
4635       DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4636       // Mark all variables in private list clauses as used in inner region.
4637       for (Stmt *VarRef : Clause->children()) {
4638         if (auto *E = cast_or_null<Expr>(VarRef)) {
4639           SemaRef.MarkDeclarationsReferencedInExpr(E);
4640         }
4641       }
4642       DSAStack->setForceVarCapturing(/*V=*/false);
4643     } else if (CaptureRegions.size() > 1 ||
4644                CaptureRegions.back() != OMPD_unknown) {
4645       if (auto *C = OMPClauseWithPreInit::get(Clause))
4646         PICs.push_back(C);
4647       if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4648         if (Expr *E = C->getPostUpdateExpr())
4649           SemaRef.MarkDeclarationsReferencedInExpr(E);
4650       }
4651     }
4652     if (Clause->getClauseKind() == OMPC_schedule)
4653       SC = cast<OMPScheduleClause>(Clause);
4654     else if (Clause->getClauseKind() == OMPC_ordered)
4655       OC = cast<OMPOrderedClause>(Clause);
4656     else if (Clause->getClauseKind() == OMPC_linear)
4657       LCs.push_back(cast<OMPLinearClause>(Clause));
4658   }
4659   // Capture allocator expressions if used.
4660   for (Expr *E : DSAStack->getInnerAllocators())
4661     SemaRef.MarkDeclarationsReferencedInExpr(E);
4662   // OpenMP, 2.7.1 Loop Construct, Restrictions
4663   // The nonmonotonic modifier cannot be specified if an ordered clause is
4664   // specified.
4665   if (SC &&
4666       (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4667        SC->getSecondScheduleModifier() ==
4668            OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4669       OC) {
4670     Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4671              ? SC->getFirstScheduleModifierLoc()
4672              : SC->getSecondScheduleModifierLoc(),
4673          diag::err_omp_simple_clause_incompatible_with_ordered)
4674         << getOpenMPClauseName(OMPC_schedule)
4675         << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4676                                          OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4677         << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4678     ErrorFound = true;
4679   }
4680   // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4681   // If an order(concurrent) clause is present, an ordered clause may not appear
4682   // on the same directive.
4683   if (checkOrderedOrderSpecified(SemaRef, Clauses))
4684     ErrorFound = true;
4685   if (!LCs.empty() && OC && OC->getNumForLoops()) {
4686     for (const OMPLinearClause *C : LCs) {
4687       Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4688           << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4689     }
4690     ErrorFound = true;
4691   }
4692   if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4693       isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4694       OC->getNumForLoops()) {
4695     Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4696         << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
4697     ErrorFound = true;
4698   }
4699   if (ErrorFound) {
4700     return StmtError();
4701   }
4702   StmtResult SR = S;
4703   unsigned CompletedRegions = 0;
4704   for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4705     // Mark all variables in private list clauses as used in inner region.
4706     // Required for proper codegen of combined directives.
4707     // TODO: add processing for other clauses.
4708     if (ThisCaptureRegion != OMPD_unknown) {
4709       for (const clang::OMPClauseWithPreInit *C : PICs) {
4710         OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4711         // Find the particular capture region for the clause if the
4712         // directive is a combined one with multiple capture regions.
4713         // If the directive is not a combined one, the capture region
4714         // associated with the clause is OMPD_unknown and is generated
4715         // only once.
4716         if (CaptureRegion == ThisCaptureRegion ||
4717             CaptureRegion == OMPD_unknown) {
4718           if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4719             for (Decl *D : DS->decls())
4720               SemaRef.MarkVariableReferenced(D->getLocation(),
4721                                              cast<VarDecl>(D));
4722           }
4723         }
4724       }
4725     }
4726     if (ThisCaptureRegion == OMPD_target) {
4727       // Capture allocator traits in the target region. They are used implicitly
4728       // and, thus, are not captured by default.
4729       for (OMPClause *C : Clauses) {
4730         if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4731           for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4732                ++I) {
4733             OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4734             if (Expr *E = D.AllocatorTraits)
4735               SemaRef.MarkDeclarationsReferencedInExpr(E);
4736           }
4737           continue;
4738         }
4739       }
4740     }
4741     if (ThisCaptureRegion == OMPD_parallel) {
4742       // Capture temp arrays for inscan reductions and locals in aligned
4743       // clauses.
4744       for (OMPClause *C : Clauses) {
4745         if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4746           if (RC->getModifier() != OMPC_REDUCTION_inscan)
4747             continue;
4748           for (Expr *E : RC->copy_array_temps())
4749             if (E)
4750               SemaRef.MarkDeclarationsReferencedInExpr(E);
4751         }
4752         if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4753           for (Expr *E : AC->varlists())
4754             SemaRef.MarkDeclarationsReferencedInExpr(E);
4755         }
4756       }
4757     }
4758     if (++CompletedRegions == CaptureRegions.size())
4759       DSAStack->setBodyComplete();
4760     SR = SemaRef.ActOnCapturedRegionEnd(SR.get());
4761   }
4762   return SR;
4763 }
4764 
checkCancelRegion(Sema & SemaRef,OpenMPDirectiveKind CurrentRegion,OpenMPDirectiveKind CancelRegion,SourceLocation StartLoc)4765 static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4766                               OpenMPDirectiveKind CancelRegion,
4767                               SourceLocation StartLoc) {
4768   // CancelRegion is only needed for cancel and cancellation_point.
4769   if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4770     return false;
4771 
4772   if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4773       CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4774     return false;
4775 
4776   SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4777       << getOpenMPDirectiveName(CancelRegion);
4778   return true;
4779 }
4780 
checkNestingOfRegions(Sema & SemaRef,const DSAStackTy * Stack,OpenMPDirectiveKind CurrentRegion,const DeclarationNameInfo & CurrentName,OpenMPDirectiveKind CancelRegion,OpenMPBindClauseKind BindKind,SourceLocation StartLoc)4781 static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4782                                   OpenMPDirectiveKind CurrentRegion,
4783                                   const DeclarationNameInfo &CurrentName,
4784                                   OpenMPDirectiveKind CancelRegion,
4785                                   OpenMPBindClauseKind BindKind,
4786                                   SourceLocation StartLoc) {
4787   if (!Stack->getCurScope())
4788     return false;
4789 
4790   OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4791   OpenMPDirectiveKind OffendingRegion = ParentRegion;
4792   bool NestingProhibited = false;
4793   bool CloseNesting = true;
4794   bool OrphanSeen = false;
4795   enum {
4796     NoRecommend,
4797     ShouldBeInParallelRegion,
4798     ShouldBeInOrderedRegion,
4799     ShouldBeInTargetRegion,
4800     ShouldBeInTeamsRegion,
4801     ShouldBeInLoopSimdRegion,
4802   } Recommend = NoRecommend;
4803 
4804   SmallVector<OpenMPDirectiveKind, 4> LeafOrComposite;
4805   ArrayRef<OpenMPDirectiveKind> ParentLOC =
4806       getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4807   OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
4808 
4809   if (SemaRef.LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() &&
4810       CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop &&
4811       CurrentRegion != OMPD_parallel &&
4812       !isOpenMPCombinedParallelADirective(CurrentRegion)) {
4813     SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
4814         << getOpenMPDirectiveName(CurrentRegion);
4815     return true;
4816   }
4817   if (isOpenMPSimdDirective(ParentRegion) &&
4818       ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
4819        (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
4820         CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4821         CurrentRegion != OMPD_scan))) {
4822     // OpenMP [2.16, Nesting of Regions]
4823     // OpenMP constructs may not be nested inside a simd region.
4824     // OpenMP [2.8.1,simd Construct, Restrictions]
4825     // An ordered construct with the simd clause is the only OpenMP
4826     // construct that can appear in the simd region.
4827     // Allowing a SIMD construct nested in another SIMD construct is an
4828     // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
4829     // message.
4830     // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
4831     // The only OpenMP constructs that can be encountered during execution of
4832     // a simd region are the atomic construct, the loop construct, the simd
4833     // construct and the ordered construct with the simd clause.
4834     SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
4835                                ? diag::err_omp_prohibited_region_simd
4836                                : diag::warn_omp_nesting_simd)
4837         << (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0);
4838     return CurrentRegion != OMPD_simd;
4839   }
4840   if (EnclosingConstruct == OMPD_atomic) {
4841     // OpenMP [2.16, Nesting of Regions]
4842     // OpenMP constructs may not be nested inside an atomic region.
4843     SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
4844     return true;
4845   }
4846   if (CurrentRegion == OMPD_section) {
4847     // OpenMP [2.7.2, sections Construct, Restrictions]
4848     // Orphaned section directives are prohibited. That is, the section
4849     // directives must appear within the sections construct and must not be
4850     // encountered elsewhere in the sections region.
4851     if (EnclosingConstruct != OMPD_sections) {
4852       SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
4853           << (ParentRegion != OMPD_unknown)
4854           << getOpenMPDirectiveName(ParentRegion);
4855       return true;
4856     }
4857     return false;
4858   }
4859   // Allow some constructs (except teams and cancellation constructs) to be
4860   // orphaned (they could be used in functions, called from OpenMP regions
4861   // with the required preconditions).
4862   if (ParentRegion == OMPD_unknown &&
4863       !isOpenMPNestingTeamsDirective(CurrentRegion) &&
4864       CurrentRegion != OMPD_cancellation_point &&
4865       CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
4866     return false;
4867   // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
4868   // for a detailed explanation
4869   if (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop &&
4870       (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
4871       (isOpenMPWorksharingDirective(ParentRegion) ||
4872        EnclosingConstruct == OMPD_loop)) {
4873     int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
4874     SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
4875         << true << getOpenMPDirectiveName(ParentRegion) << ErrorMsgNumber
4876         << getOpenMPDirectiveName(CurrentRegion);
4877     return true;
4878   }
4879   if (CurrentRegion == OMPD_cancellation_point ||
4880       CurrentRegion == OMPD_cancel) {
4881     // OpenMP [2.16, Nesting of Regions]
4882     // A cancellation point construct for which construct-type-clause is
4883     // taskgroup must be nested inside a task construct. A cancellation
4884     // point construct for which construct-type-clause is not taskgroup must
4885     // be closely nested inside an OpenMP construct that matches the type
4886     // specified in construct-type-clause.
4887     // A cancel construct for which construct-type-clause is taskgroup must be
4888     // nested inside a task construct. A cancel construct for which
4889     // construct-type-clause is not taskgroup must be closely nested inside an
4890     // OpenMP construct that matches the type specified in
4891     // construct-type-clause.
4892     ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(ParentRegion);
4893     if (CancelRegion == OMPD_taskgroup) {
4894       NestingProhibited = EnclosingConstruct != OMPD_task &&
4895                           (SemaRef.getLangOpts().OpenMP < 50 ||
4896                            EnclosingConstruct != OMPD_taskloop);
4897     } else if (CancelRegion == OMPD_sections) {
4898       NestingProhibited = EnclosingConstruct != OMPD_section &&
4899                           EnclosingConstruct != OMPD_sections;
4900     } else {
4901       NestingProhibited = CancelRegion != Leafs.back();
4902     }
4903     OrphanSeen = ParentRegion == OMPD_unknown;
4904   } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
4905     // OpenMP 5.1 [2.22, Nesting of Regions]
4906     // A masked region may not be closely nested inside a worksharing, loop,
4907     // atomic, task, or taskloop region.
4908     NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4909                         isOpenMPGenericLoopDirective(ParentRegion) ||
4910                         isOpenMPTaskingDirective(ParentRegion);
4911   } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
4912     // OpenMP [2.16, Nesting of Regions]
4913     // A critical region may not be nested (closely or otherwise) inside a
4914     // critical region with the same name. Note that this restriction is not
4915     // sufficient to prevent deadlock.
4916     SourceLocation PreviousCriticalLoc;
4917     bool DeadLock = Stack->hasDirective(
4918         [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
4919                                             const DeclarationNameInfo &DNI,
4920                                             SourceLocation Loc) {
4921           if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
4922             PreviousCriticalLoc = Loc;
4923             return true;
4924           }
4925           return false;
4926         },
4927         false /* skip top directive */);
4928     if (DeadLock) {
4929       SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
4930           << CurrentName.getName();
4931       if (PreviousCriticalLoc.isValid())
4932         SemaRef.Diag(PreviousCriticalLoc,
4933                      diag::note_omp_previous_critical_region);
4934       return true;
4935     }
4936   } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
4937     // OpenMP 5.1 [2.22, Nesting of Regions]
4938     // A scope region may not be closely nested inside a worksharing, loop,
4939     // task, taskloop, critical, ordered, atomic, or masked region.
4940     // OpenMP 5.1 [2.22, Nesting of Regions]
4941     // A barrier region may not be closely nested inside a worksharing, loop,
4942     // task, taskloop, critical, ordered, atomic, or masked region.
4943     NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4944                         isOpenMPGenericLoopDirective(ParentRegion) ||
4945                         isOpenMPTaskingDirective(ParentRegion) ||
4946                         llvm::is_contained({OMPD_masked, OMPD_master,
4947                                             OMPD_critical, OMPD_ordered},
4948                                            EnclosingConstruct);
4949   } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
4950              !isOpenMPParallelDirective(CurrentRegion) &&
4951              !isOpenMPTeamsDirective(CurrentRegion)) {
4952     // OpenMP 5.1 [2.22, Nesting of Regions]
4953     // A loop region that binds to a parallel region or a worksharing region
4954     // may not be closely nested inside a worksharing, loop, task, taskloop,
4955     // critical, ordered, atomic, or masked region.
4956     NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4957                         isOpenMPGenericLoopDirective(ParentRegion) ||
4958                         isOpenMPTaskingDirective(ParentRegion) ||
4959                         llvm::is_contained({OMPD_masked, OMPD_master,
4960                                             OMPD_critical, OMPD_ordered},
4961                                            EnclosingConstruct);
4962     Recommend = ShouldBeInParallelRegion;
4963   } else if (CurrentRegion == OMPD_ordered) {
4964     // OpenMP [2.16, Nesting of Regions]
4965     // An ordered region may not be closely nested inside a critical,
4966     // atomic, or explicit task region.
4967     // An ordered region must be closely nested inside a loop region (or
4968     // parallel loop region) with an ordered clause.
4969     // OpenMP [2.8.1,simd Construct, Restrictions]
4970     // An ordered construct with the simd clause is the only OpenMP construct
4971     // that can appear in the simd region.
4972     NestingProhibited = EnclosingConstruct == OMPD_critical ||
4973                         isOpenMPTaskingDirective(ParentRegion) ||
4974                         !(isOpenMPSimdDirective(ParentRegion) ||
4975                           Stack->isParentOrderedRegion());
4976     Recommend = ShouldBeInOrderedRegion;
4977   } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
4978     // OpenMP [2.16, Nesting of Regions]
4979     // If specified, a teams construct must be contained within a target
4980     // construct.
4981     NestingProhibited =
4982         (SemaRef.LangOpts.OpenMP <= 45 && EnclosingConstruct != OMPD_target) ||
4983         (SemaRef.LangOpts.OpenMP >= 50 && EnclosingConstruct != OMPD_unknown &&
4984          EnclosingConstruct != OMPD_target);
4985     OrphanSeen = ParentRegion == OMPD_unknown;
4986     Recommend = ShouldBeInTargetRegion;
4987   } else if (CurrentRegion == OMPD_scan) {
4988     if (SemaRef.LangOpts.OpenMP >= 50) {
4989       // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
4990       // simd, or for simd. This has to take into account combined directives.
4991       // In 5.2 this seems to be implied by the fact that the specified
4992       // separated constructs are do, for, and simd.
4993       NestingProhibited = !llvm::is_contained(
4994           {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
4995     } else {
4996       NestingProhibited = true;
4997     }
4998     OrphanSeen = ParentRegion == OMPD_unknown;
4999     Recommend = ShouldBeInLoopSimdRegion;
5000   }
5001   if (!NestingProhibited && !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5002       !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5003       EnclosingConstruct == OMPD_teams) {
5004     // OpenMP [5.1, 2.22, Nesting of Regions]
5005     // distribute, distribute simd, distribute parallel worksharing-loop,
5006     // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5007     // including any parallel regions arising from combined constructs,
5008     // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5009     // only OpenMP regions that may be strictly nested inside the teams
5010     // region.
5011     //
5012     // As an extension, we permit atomic within teams as well.
5013     NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5014                         !isOpenMPDistributeDirective(CurrentRegion) &&
5015                         CurrentRegion != OMPD_loop &&
5016                         !(SemaRef.getLangOpts().OpenMPExtensions &&
5017                           CurrentRegion == OMPD_atomic);
5018     Recommend = ShouldBeInParallelRegion;
5019   }
5020   if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5021     // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5022     // If the bind clause is present on the loop construct and binding is
5023     // teams then the corresponding loop region must be strictly nested inside
5024     // a teams region.
5025     NestingProhibited =
5026         BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5027     Recommend = ShouldBeInTeamsRegion;
5028   }
5029   if (!NestingProhibited && isOpenMPNestingDistributeDirective(CurrentRegion)) {
5030     // OpenMP 4.5 [2.17 Nesting of Regions]
5031     // The region associated with the distribute construct must be strictly
5032     // nested inside a teams region
5033     NestingProhibited = EnclosingConstruct != OMPD_teams;
5034     Recommend = ShouldBeInTeamsRegion;
5035   }
5036   if (!NestingProhibited &&
5037       (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5038        isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5039     // OpenMP 4.5 [2.17 Nesting of Regions]
5040     // If a target, target update, target data, target enter data, or
5041     // target exit data construct is encountered during execution of a
5042     // target region, the behavior is unspecified.
5043     NestingProhibited = Stack->hasDirective(
5044         [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5045                            SourceLocation) {
5046           if (isOpenMPTargetExecutionDirective(K)) {
5047             OffendingRegion = K;
5048             return true;
5049           }
5050           return false;
5051         },
5052         false /* don't skip top directive */);
5053     CloseNesting = false;
5054   }
5055   if (NestingProhibited) {
5056     if (OrphanSeen) {
5057       SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5058           << getOpenMPDirectiveName(CurrentRegion) << Recommend;
5059     } else {
5060       SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5061           << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
5062           << Recommend << getOpenMPDirectiveName(CurrentRegion);
5063     }
5064     return true;
5065   }
5066   return false;
5067 }
5068 
5069 struct Kind2Unsigned {
5070   using argument_type = OpenMPDirectiveKind;
operator ()Kind2Unsigned5071   unsigned operator()(argument_type DK) { return unsigned(DK); }
5072 };
checkIfClauses(Sema & S,OpenMPDirectiveKind Kind,ArrayRef<OMPClause * > Clauses,ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers)5073 static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
5074                            ArrayRef<OMPClause *> Clauses,
5075                            ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5076   bool ErrorFound = false;
5077   unsigned NamedModifiersNumber = 0;
5078   llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5079   FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5080   SmallVector<SourceLocation, 4> NameModifierLoc;
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       if (FoundNameModifiers[CurNM]) {
5087         S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5088             << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
5089             << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
5090         ErrorFound = true;
5091       } else if (CurNM != OMPD_unknown) {
5092         NameModifierLoc.push_back(IC->getNameModifierLoc());
5093         ++NamedModifiersNumber;
5094       }
5095       FoundNameModifiers[CurNM] = IC;
5096       if (CurNM == OMPD_unknown)
5097         continue;
5098       // Check if the specified name modifier is allowed for the current
5099       // directive.
5100       // At most one if clause with the particular directive-name-modifier can
5101       // appear on the directive.
5102       if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5103         S.Diag(IC->getNameModifierLoc(),
5104                diag::err_omp_wrong_if_directive_name_modifier)
5105             << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
5106         ErrorFound = true;
5107       }
5108     }
5109   }
5110   // If any if clause on the directive includes a directive-name-modifier then
5111   // all if clauses on the directive must include a directive-name-modifier.
5112   if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5113     if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5114       S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5115              diag::err_omp_no_more_if_clause);
5116     } else {
5117       std::string Values;
5118       std::string Sep(", ");
5119       unsigned AllowedCnt = 0;
5120       unsigned TotalAllowedNum =
5121           AllowedNameModifiers.size() - NamedModifiersNumber;
5122       for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5123            ++Cnt) {
5124         OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5125         if (!FoundNameModifiers[NM]) {
5126           Values += "'";
5127           Values += getOpenMPDirectiveName(NM);
5128           Values += "'";
5129           if (AllowedCnt + 2 == TotalAllowedNum)
5130             Values += " or ";
5131           else if (AllowedCnt + 1 != TotalAllowedNum)
5132             Values += Sep;
5133           ++AllowedCnt;
5134         }
5135       }
5136       S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5137              diag::err_omp_unnamed_if_clause)
5138           << (TotalAllowedNum > 1) << Values;
5139     }
5140     for (SourceLocation Loc : NameModifierLoc) {
5141       S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5142     }
5143     ErrorFound = true;
5144   }
5145   return ErrorFound;
5146 }
5147 
getPrivateItem(Sema & S,Expr * & RefExpr,SourceLocation & ELoc,SourceRange & ERange,bool AllowArraySection,StringRef DiagType)5148 static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5149                                                    SourceLocation &ELoc,
5150                                                    SourceRange &ERange,
5151                                                    bool AllowArraySection,
5152                                                    StringRef DiagType) {
5153   if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5154       RefExpr->containsUnexpandedParameterPack())
5155     return std::make_pair(nullptr, true);
5156 
5157   // OpenMP [3.1, C/C++]
5158   //  A list item is a variable name.
5159   // OpenMP  [2.9.3.3, Restrictions, p.1]
5160   //  A variable that is part of another variable (as an array or
5161   //  structure element) cannot appear in a private clause.
5162   RefExpr = RefExpr->IgnoreParens();
5163   enum {
5164     NoArrayExpr = -1,
5165     ArraySubscript = 0,
5166     OMPArraySection = 1
5167   } IsArrayExpr = NoArrayExpr;
5168   if (AllowArraySection) {
5169     if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5170       Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5171       while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5172         Base = TempASE->getBase()->IgnoreParenImpCasts();
5173       RefExpr = Base;
5174       IsArrayExpr = ArraySubscript;
5175     } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5176       Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5177       while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Base))
5178         Base = TempOASE->getBase()->IgnoreParenImpCasts();
5179       while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5180         Base = TempASE->getBase()->IgnoreParenImpCasts();
5181       RefExpr = Base;
5182       IsArrayExpr = OMPArraySection;
5183     }
5184   }
5185   ELoc = RefExpr->getExprLoc();
5186   ERange = RefExpr->getSourceRange();
5187   RefExpr = RefExpr->IgnoreParenImpCasts();
5188   auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5189   auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5190   if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5191       (S.getCurrentThisType().isNull() || !ME ||
5192        !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5193        !isa<FieldDecl>(ME->getMemberDecl()))) {
5194     if (IsArrayExpr != NoArrayExpr) {
5195       S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5196           << IsArrayExpr << ERange;
5197     } else if (!DiagType.empty()) {
5198       unsigned DiagSelect = S.getLangOpts().CPlusPlus
5199                                 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5200                                 : 0;
5201       S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5202           << DiagSelect << DiagType << ERange;
5203     } else {
5204       S.Diag(ELoc,
5205              AllowArraySection
5206                  ? diag::err_omp_expected_var_name_member_expr_or_array_item
5207                  : diag::err_omp_expected_var_name_member_expr)
5208           << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5209     }
5210     return std::make_pair(nullptr, false);
5211   }
5212   return std::make_pair(
5213       getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5214 }
5215 
5216 namespace {
5217 /// Checks if the allocator is used in uses_allocators clause to be allowed in
5218 /// target regions.
5219 class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5220   DSAStackTy *S = nullptr;
5221 
5222 public:
VisitDeclRefExpr(const DeclRefExpr * E)5223   bool VisitDeclRefExpr(const DeclRefExpr *E) {
5224     return S->isUsesAllocatorsDecl(E->getDecl())
5225                .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5226            DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5227   }
VisitStmt(const Stmt * S)5228   bool VisitStmt(const Stmt *S) {
5229     for (const Stmt *Child : S->children()) {
5230       if (Child && Visit(Child))
5231         return true;
5232     }
5233     return false;
5234   }
AllocatorChecker(DSAStackTy * S)5235   explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5236 };
5237 } // namespace
5238 
checkAllocateClauses(Sema & S,DSAStackTy * Stack,ArrayRef<OMPClause * > Clauses)5239 static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5240                                  ArrayRef<OMPClause *> Clauses) {
5241   assert(!S.CurContext->isDependentContext() &&
5242          "Expected non-dependent context.");
5243   auto AllocateRange =
5244       llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5245   llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5246   auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5247     return isOpenMPPrivate(C->getClauseKind());
5248   });
5249   for (OMPClause *Cl : PrivateRange) {
5250     MutableArrayRef<Expr *>::iterator I, It, Et;
5251     if (Cl->getClauseKind() == OMPC_private) {
5252       auto *PC = cast<OMPPrivateClause>(Cl);
5253       I = PC->private_copies().begin();
5254       It = PC->varlist_begin();
5255       Et = PC->varlist_end();
5256     } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5257       auto *PC = cast<OMPFirstprivateClause>(Cl);
5258       I = PC->private_copies().begin();
5259       It = PC->varlist_begin();
5260       Et = PC->varlist_end();
5261     } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5262       auto *PC = cast<OMPLastprivateClause>(Cl);
5263       I = PC->private_copies().begin();
5264       It = PC->varlist_begin();
5265       Et = PC->varlist_end();
5266     } else if (Cl->getClauseKind() == OMPC_linear) {
5267       auto *PC = cast<OMPLinearClause>(Cl);
5268       I = PC->privates().begin();
5269       It = PC->varlist_begin();
5270       Et = PC->varlist_end();
5271     } else if (Cl->getClauseKind() == OMPC_reduction) {
5272       auto *PC = cast<OMPReductionClause>(Cl);
5273       I = PC->privates().begin();
5274       It = PC->varlist_begin();
5275       Et = PC->varlist_end();
5276     } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5277       auto *PC = cast<OMPTaskReductionClause>(Cl);
5278       I = PC->privates().begin();
5279       It = PC->varlist_begin();
5280       Et = PC->varlist_end();
5281     } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5282       auto *PC = cast<OMPInReductionClause>(Cl);
5283       I = PC->privates().begin();
5284       It = PC->varlist_begin();
5285       Et = PC->varlist_end();
5286     } else {
5287       llvm_unreachable("Expected private clause.");
5288     }
5289     for (Expr *E : llvm::make_range(It, Et)) {
5290       if (!*I) {
5291         ++I;
5292         continue;
5293       }
5294       SourceLocation ELoc;
5295       SourceRange ERange;
5296       Expr *SimpleRefExpr = E;
5297       auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5298                                 /*AllowArraySection=*/true);
5299       DeclToCopy.try_emplace(Res.first,
5300                              cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5301       ++I;
5302     }
5303   }
5304   for (OMPClause *C : AllocateRange) {
5305     auto *AC = cast<OMPAllocateClause>(C);
5306     if (S.getLangOpts().OpenMP >= 50 &&
5307         !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5308         isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5309         AC->getAllocator()) {
5310       Expr *Allocator = AC->getAllocator();
5311       // OpenMP, 2.12.5 target Construct
5312       // Memory allocators that do not appear in a uses_allocators clause cannot
5313       // appear as an allocator in an allocate clause or be used in the target
5314       // region unless a requires directive with the dynamic_allocators clause
5315       // is present in the same compilation unit.
5316       AllocatorChecker Checker(Stack);
5317       if (Checker.Visit(Allocator))
5318         S.Diag(Allocator->getExprLoc(),
5319                diag::err_omp_allocator_not_in_uses_allocators)
5320             << Allocator->getSourceRange();
5321     }
5322     OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5323         getAllocatorKind(S, Stack, AC->getAllocator());
5324     // OpenMP, 2.11.4 allocate Clause, Restrictions.
5325     // For task, taskloop or target directives, allocation requests to memory
5326     // allocators with the trait access set to thread result in unspecified
5327     // behavior.
5328     if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5329         (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5330          isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5331       S.Diag(AC->getAllocator()->getExprLoc(),
5332              diag::warn_omp_allocate_thread_on_task_target_directive)
5333           << getOpenMPDirectiveName(Stack->getCurrentDirective());
5334     }
5335     for (Expr *E : AC->varlists()) {
5336       SourceLocation ELoc;
5337       SourceRange ERange;
5338       Expr *SimpleRefExpr = E;
5339       auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5340       ValueDecl *VD = Res.first;
5341       DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5342       if (!isOpenMPPrivate(Data.CKind)) {
5343         S.Diag(E->getExprLoc(),
5344                diag::err_omp_expected_private_copy_for_allocate);
5345         continue;
5346       }
5347       VarDecl *PrivateVD = DeclToCopy[VD];
5348       if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5349                                             AllocatorKind, AC->getAllocator()))
5350         continue;
5351       // Placeholder until allocate clause supports align modifier.
5352       Expr *Alignment = nullptr;
5353       applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5354                                 Alignment, E->getSourceRange());
5355     }
5356   }
5357 }
5358 
5359 namespace {
5360 /// Rewrite statements and expressions for Sema \p Actions CurContext.
5361 ///
5362 /// Used to wrap already parsed statements/expressions into a new CapturedStmt
5363 /// context. DeclRefExpr used inside the new context are changed to refer to the
5364 /// captured variable instead.
5365 class CaptureVars : public TreeTransform<CaptureVars> {
5366   using BaseTransform = TreeTransform<CaptureVars>;
5367 
5368 public:
CaptureVars(Sema & Actions)5369   CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5370 
AlwaysRebuild()5371   bool AlwaysRebuild() { return true; }
5372 };
5373 } // namespace
5374 
precomputeExpr(Sema & Actions,SmallVectorImpl<Stmt * > & BodyStmts,Expr * E,StringRef Name)5375 static VarDecl *precomputeExpr(Sema &Actions,
5376                                SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5377                                StringRef Name) {
5378   Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5379   VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5380                                  dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5381   auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5382       Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5383   Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5384   BodyStmts.push_back(NewDeclStmt);
5385   return NewVar;
5386 }
5387 
5388 /// Create a closure that computes the number of iterations of a loop.
5389 ///
5390 /// \param Actions   The Sema object.
5391 /// \param LogicalTy Type for the logical iteration number.
5392 /// \param Rel       Comparison operator of the loop condition.
5393 /// \param StartExpr Value of the loop counter at the first iteration.
5394 /// \param StopExpr  Expression the loop counter is compared against in the loop
5395 /// condition. \param StepExpr      Amount of increment after each iteration.
5396 ///
5397 /// \return Closure (CapturedStmt) of the distance calculation.
buildDistanceFunc(Sema & Actions,QualType LogicalTy,BinaryOperator::Opcode Rel,Expr * StartExpr,Expr * StopExpr,Expr * StepExpr)5398 static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5399                                        BinaryOperator::Opcode Rel,
5400                                        Expr *StartExpr, Expr *StopExpr,
5401                                        Expr *StepExpr) {
5402   ASTContext &Ctx = Actions.getASTContext();
5403   TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5404 
5405   // Captured regions currently don't support return values, we use an
5406   // out-parameter instead. All inputs are implicit captures.
5407   // TODO: Instead of capturing each DeclRefExpr occurring in
5408   // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5409   QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5410   Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5411                                           {StringRef(), QualType()}};
5412   Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5413 
5414   Stmt *Body;
5415   {
5416     Sema::CompoundScopeRAII CompoundScope(Actions);
5417     CapturedDecl *CS = cast<CapturedDecl>(Actions.CurContext);
5418 
5419     // Get the LValue expression for the result.
5420     ImplicitParamDecl *DistParam = CS->getParam(0);
5421     DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5422         DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5423 
5424     SmallVector<Stmt *, 4> BodyStmts;
5425 
5426     // Capture all referenced variable references.
5427     // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5428     // CapturedStmt, we could compute them before and capture the result, to be
5429     // used jointly with the LoopVar function.
5430     VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5431     VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5432     VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5433     auto BuildVarRef = [&](VarDecl *VD) {
5434       return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5435     };
5436 
5437     IntegerLiteral *Zero = IntegerLiteral::Create(
5438         Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5439     IntegerLiteral *One = IntegerLiteral::Create(
5440         Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5441     Expr *Dist;
5442     if (Rel == BO_NE) {
5443       // When using a != comparison, the increment can be +1 or -1. This can be
5444       // dynamic at runtime, so we need to check for the direction.
5445       Expr *IsNegStep = AssertSuccess(
5446           Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5447 
5448       // Positive increment.
5449       Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5450           nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5451       ForwardRange = AssertSuccess(
5452           Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5453       Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5454           nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5455 
5456       // Negative increment.
5457       Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5458           nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5459       BackwardRange = AssertSuccess(
5460           Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5461       Expr *NegIncAmount = AssertSuccess(
5462           Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5463       Expr *BackwardDist = AssertSuccess(
5464           Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5465 
5466       // Use the appropriate case.
5467       Dist = AssertSuccess(Actions.ActOnConditionalOp(
5468           {}, {}, IsNegStep, BackwardDist, ForwardDist));
5469     } else {
5470       assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5471              "Expected one of these relational operators");
5472 
5473       // We can derive the direction from any other comparison operator. It is
5474       // non well-formed OpenMP if Step increments/decrements in the other
5475       // directions. Whether at least the first iteration passes the loop
5476       // condition.
5477       Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5478           nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5479 
5480       // Compute the range between first and last counter value.
5481       Expr *Range;
5482       if (Rel == BO_GE || Rel == BO_GT)
5483         Range = AssertSuccess(Actions.BuildBinOp(
5484             nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5485       else
5486         Range = AssertSuccess(Actions.BuildBinOp(
5487             nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5488 
5489       // Ensure unsigned range space.
5490       Range =
5491           AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5492 
5493       if (Rel == BO_LE || Rel == BO_GE) {
5494         // Add one to the range if the relational operator is inclusive.
5495         Range =
5496             AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5497       }
5498 
5499       // Divide by the absolute step amount. If the range is not a multiple of
5500       // the step size, rounding-up the effective upper bound ensures that the
5501       // last iteration is included.
5502       // Note that the rounding-up may cause an overflow in a temporary that
5503       // could be avoided, but would have occurred in a C-style for-loop as
5504       // well.
5505       Expr *Divisor = BuildVarRef(NewStep);
5506       if (Rel == BO_GE || Rel == BO_GT)
5507         Divisor =
5508             AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5509       Expr *DivisorMinusOne =
5510           AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5511       Expr *RangeRoundUp = AssertSuccess(
5512           Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5513       Dist = AssertSuccess(
5514           Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5515 
5516       // If there is not at least one iteration, the range contains garbage. Fix
5517       // to zero in this case.
5518       Dist = AssertSuccess(
5519           Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5520     }
5521 
5522     // Assign the result to the out-parameter.
5523     Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5524         Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5525     BodyStmts.push_back(ResultAssign);
5526 
5527     Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5528   }
5529 
5530   return cast<CapturedStmt>(
5531       AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5532 }
5533 
5534 /// Create a closure that computes the loop variable from the logical iteration
5535 /// number.
5536 ///
5537 /// \param Actions   The Sema object.
5538 /// \param LoopVarTy Type for the loop variable used for result value.
5539 /// \param LogicalTy Type for the logical iteration number.
5540 /// \param StartExpr Value of the loop counter at the first iteration.
5541 /// \param Step      Amount of increment after each iteration.
5542 /// \param Deref     Whether the loop variable is a dereference of the loop
5543 /// counter variable.
5544 ///
5545 /// \return Closure (CapturedStmt) of the loop value calculation.
buildLoopVarFunc(Sema & Actions,QualType LoopVarTy,QualType LogicalTy,DeclRefExpr * StartExpr,Expr * Step,bool Deref)5546 static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5547                                       QualType LogicalTy,
5548                                       DeclRefExpr *StartExpr, Expr *Step,
5549                                       bool Deref) {
5550   ASTContext &Ctx = Actions.getASTContext();
5551 
5552   // Pass the result as an out-parameter. Passing as return value would require
5553   // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5554   // invoke a copy constructor.
5555   QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5556   SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5557                                                 {"Logical", LogicalTy},
5558                                                 {StringRef(), QualType()}};
5559   Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5560 
5561   // Capture the initial iterator which represents the LoopVar value at the
5562   // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5563   // it in every iteration, capture it by value before it is modified.
5564   VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5565   bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5566                                             Sema::TryCapture_ExplicitByVal, {});
5567   (void)Invalid;
5568   assert(!Invalid && "Expecting capture-by-value to work.");
5569 
5570   Expr *Body;
5571   {
5572     Sema::CompoundScopeRAII CompoundScope(Actions);
5573     auto *CS = cast<CapturedDecl>(Actions.CurContext);
5574 
5575     ImplicitParamDecl *TargetParam = CS->getParam(0);
5576     DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5577         TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5578     ImplicitParamDecl *IndvarParam = CS->getParam(1);
5579     DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5580         IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5581 
5582     // Capture the Start expression.
5583     CaptureVars Recap(Actions);
5584     Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5585     Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5586 
5587     Expr *Skip = AssertSuccess(
5588         Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5589     // TODO: Explicitly cast to the iterator's difference_type instead of
5590     // relying on implicit conversion.
5591     Expr *Advanced =
5592         AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5593 
5594     if (Deref) {
5595       // For range-based for-loops convert the loop counter value to a concrete
5596       // loop variable value by dereferencing the iterator.
5597       Advanced =
5598           AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5599     }
5600 
5601     // Assign the result to the output parameter.
5602     Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5603                                             BO_Assign, TargetRef, Advanced));
5604   }
5605   return cast<CapturedStmt>(
5606       AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5607 }
5608 
ActOnOpenMPCanonicalLoop(Stmt * AStmt)5609 StmtResult SemaOpenMP::ActOnOpenMPCanonicalLoop(Stmt *AStmt) {
5610   ASTContext &Ctx = getASTContext();
5611 
5612   // Extract the common elements of ForStmt and CXXForRangeStmt:
5613   // Loop variable, repeat condition, increment
5614   Expr *Cond, *Inc;
5615   VarDecl *LIVDecl, *LUVDecl;
5616   if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5617     Stmt *Init = For->getInit();
5618     if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5619       // For statement declares loop variable.
5620       LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5621     } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5622       // For statement reuses variable.
5623       assert(LCAssign->getOpcode() == BO_Assign &&
5624              "init part must be a loop variable assignment");
5625       auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5626       LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5627     } else
5628       llvm_unreachable("Cannot determine loop variable");
5629     LUVDecl = LIVDecl;
5630 
5631     Cond = For->getCond();
5632     Inc = For->getInc();
5633   } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5634     DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5635     LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5636     LUVDecl = RangeFor->getLoopVariable();
5637 
5638     Cond = RangeFor->getCond();
5639     Inc = RangeFor->getInc();
5640   } else
5641     llvm_unreachable("unhandled kind of loop");
5642 
5643   QualType CounterTy = LIVDecl->getType();
5644   QualType LVTy = LUVDecl->getType();
5645 
5646   // Analyze the loop condition.
5647   Expr *LHS, *RHS;
5648   BinaryOperator::Opcode CondRel;
5649   Cond = Cond->IgnoreImplicit();
5650   if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5651     LHS = CondBinExpr->getLHS();
5652     RHS = CondBinExpr->getRHS();
5653     CondRel = CondBinExpr->getOpcode();
5654   } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5655     assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5656     LHS = CondCXXOp->getArg(0);
5657     RHS = CondCXXOp->getArg(1);
5658     switch (CondCXXOp->getOperator()) {
5659     case OO_ExclaimEqual:
5660       CondRel = BO_NE;
5661       break;
5662     case OO_Less:
5663       CondRel = BO_LT;
5664       break;
5665     case OO_LessEqual:
5666       CondRel = BO_LE;
5667       break;
5668     case OO_Greater:
5669       CondRel = BO_GT;
5670       break;
5671     case OO_GreaterEqual:
5672       CondRel = BO_GE;
5673       break;
5674     default:
5675       llvm_unreachable("unexpected iterator operator");
5676     }
5677   } else
5678     llvm_unreachable("unexpected loop condition");
5679 
5680   // Normalize such that the loop counter is on the LHS.
5681   if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5682       cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5683     std::swap(LHS, RHS);
5684     CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5685   }
5686   auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5687 
5688   // Decide the bit width for the logical iteration counter. By default use the
5689   // unsigned ptrdiff_t integer size (for iterators and pointers).
5690   // TODO: For iterators, use iterator::difference_type,
5691   // std::iterator_traits<>::difference_type or decltype(it - end).
5692   QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5693   if (CounterTy->isIntegerType()) {
5694     unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5695     LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5696   }
5697 
5698   // Analyze the loop increment.
5699   Expr *Step;
5700   if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5701     int Direction;
5702     switch (IncUn->getOpcode()) {
5703     case UO_PreInc:
5704     case UO_PostInc:
5705       Direction = 1;
5706       break;
5707     case UO_PreDec:
5708     case UO_PostDec:
5709       Direction = -1;
5710       break;
5711     default:
5712       llvm_unreachable("unhandled unary increment operator");
5713     }
5714     Step = IntegerLiteral::Create(
5715         Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction), LogicalTy, {});
5716   } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5717     if (IncBin->getOpcode() == BO_AddAssign) {
5718       Step = IncBin->getRHS();
5719     } else if (IncBin->getOpcode() == BO_SubAssign) {
5720       Step = AssertSuccess(
5721           SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5722     } else
5723       llvm_unreachable("unhandled binary increment operator");
5724   } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5725     switch (CondCXXOp->getOperator()) {
5726     case OO_PlusPlus:
5727       Step = IntegerLiteral::Create(
5728           Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5729       break;
5730     case OO_MinusMinus:
5731       Step = IntegerLiteral::Create(
5732           Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5733       break;
5734     case OO_PlusEqual:
5735       Step = CondCXXOp->getArg(1);
5736       break;
5737     case OO_MinusEqual:
5738       Step = AssertSuccess(
5739           SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5740       break;
5741     default:
5742       llvm_unreachable("unhandled overloaded increment operator");
5743     }
5744   } else
5745     llvm_unreachable("unknown increment expression");
5746 
5747   CapturedStmt *DistanceFunc =
5748       buildDistanceFunc(SemaRef, LogicalTy, CondRel, LHS, RHS, Step);
5749   CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5750       SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5751   DeclRefExpr *LVRef =
5752       SemaRef.BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue, {},
5753                                nullptr, nullptr, {}, nullptr);
5754   return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
5755                                   LoopVarFunc, LVRef);
5756 }
5757 
ActOnOpenMPLoopnest(Stmt * AStmt)5758 StmtResult SemaOpenMP::ActOnOpenMPLoopnest(Stmt *AStmt) {
5759   // Handle a literal loop.
5760   if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5761     return ActOnOpenMPCanonicalLoop(AStmt);
5762 
5763   // If not a literal loop, it must be the result of a loop transformation.
5764   OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(AStmt);
5765   assert(
5766       isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
5767       "Loop transformation directive expected");
5768   return LoopTransform;
5769 }
5770 
5771 static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
5772                                             CXXScopeSpec &MapperIdScopeSpec,
5773                                             const DeclarationNameInfo &MapperId,
5774                                             QualType Type,
5775                                             Expr *UnresolvedMapper);
5776 
5777 /// Perform DFS through the structure/class data members trying to find
5778 /// member(s) with user-defined 'default' mapper and generate implicit map
5779 /// clauses for such members with the found 'default' mapper.
5780 static void
processImplicitMapsWithDefaultMappers(Sema & S,DSAStackTy * Stack,SmallVectorImpl<OMPClause * > & Clauses)5781 processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack,
5782                                       SmallVectorImpl<OMPClause *> &Clauses) {
5783   // Check for the default mapper for data members.
5784   if (S.getLangOpts().OpenMP < 50)
5785     return;
5786   SmallVector<OMPClause *, 4> ImplicitMaps;
5787   for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5788     auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5789     if (!C)
5790       continue;
5791     SmallVector<Expr *, 4> SubExprs;
5792     auto *MI = C->mapperlist_begin();
5793     for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
5794          ++I, ++MI) {
5795       // Expression is mapped using mapper - skip it.
5796       if (*MI)
5797         continue;
5798       Expr *E = *I;
5799       // Expression is dependent - skip it, build the mapper when it gets
5800       // instantiated.
5801       if (E->isTypeDependent() || E->isValueDependent() ||
5802           E->containsUnexpandedParameterPack())
5803         continue;
5804       // Array section - need to check for the mapping of the array section
5805       // element.
5806       QualType CanonType = E->getType().getCanonicalType();
5807       if (CanonType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
5808         const auto *OASE = cast<ArraySectionExpr>(E->IgnoreParenImpCasts());
5809         QualType BaseType =
5810             ArraySectionExpr::getBaseOriginalType(OASE->getBase());
5811         QualType ElemType;
5812         if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
5813           ElemType = ATy->getElementType();
5814         else
5815           ElemType = BaseType->getPointeeType();
5816         CanonType = ElemType;
5817       }
5818 
5819       // DFS over data members in structures/classes.
5820       SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(
5821           1, {CanonType, nullptr});
5822       llvm::DenseMap<const Type *, Expr *> Visited;
5823       SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(
5824           1, {nullptr, 1});
5825       while (!Types.empty()) {
5826         QualType BaseType;
5827         FieldDecl *CurFD;
5828         std::tie(BaseType, CurFD) = Types.pop_back_val();
5829         while (ParentChain.back().second == 0)
5830           ParentChain.pop_back();
5831         --ParentChain.back().second;
5832         if (BaseType.isNull())
5833           continue;
5834         // Only structs/classes are allowed to have mappers.
5835         const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
5836         if (!RD)
5837           continue;
5838         auto It = Visited.find(BaseType.getTypePtr());
5839         if (It == Visited.end()) {
5840           // Try to find the associated user-defined mapper.
5841           CXXScopeSpec MapperIdScopeSpec;
5842           DeclarationNameInfo DefaultMapperId;
5843           DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
5844               &S.Context.Idents.get("default")));
5845           DefaultMapperId.setLoc(E->getExprLoc());
5846           ExprResult ER = buildUserDefinedMapperRef(
5847               S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
5848               BaseType, /*UnresolvedMapper=*/nullptr);
5849           if (ER.isInvalid())
5850             continue;
5851           It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
5852         }
5853         // Found default mapper.
5854         if (It->second) {
5855           auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
5856                                                      VK_LValue, OK_Ordinary, E);
5857           OE->setIsUnique(/*V=*/true);
5858           Expr *BaseExpr = OE;
5859           for (const auto &P : ParentChain) {
5860             if (P.first) {
5861               BaseExpr = S.BuildMemberExpr(
5862                   BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
5863                   NestedNameSpecifierLoc(), SourceLocation(), P.first,
5864                   DeclAccessPair::make(P.first, P.first->getAccess()),
5865                   /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
5866                   P.first->getType(), VK_LValue, OK_Ordinary);
5867               BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
5868             }
5869           }
5870           if (CurFD)
5871             BaseExpr = S.BuildMemberExpr(
5872                 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
5873                 NestedNameSpecifierLoc(), SourceLocation(), CurFD,
5874                 DeclAccessPair::make(CurFD, CurFD->getAccess()),
5875                 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
5876                 CurFD->getType(), VK_LValue, OK_Ordinary);
5877           SubExprs.push_back(BaseExpr);
5878           continue;
5879         }
5880         // Check for the "default" mapper for data members.
5881         bool FirstIter = true;
5882         for (FieldDecl *FD : RD->fields()) {
5883           if (!FD)
5884             continue;
5885           QualType FieldTy = FD->getType();
5886           if (FieldTy.isNull() ||
5887               !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
5888             continue;
5889           if (FirstIter) {
5890             FirstIter = false;
5891             ParentChain.emplace_back(CurFD, 1);
5892           } else {
5893             ++ParentChain.back().second;
5894           }
5895           Types.emplace_back(FieldTy, FD);
5896         }
5897       }
5898     }
5899     if (SubExprs.empty())
5900       continue;
5901     CXXScopeSpec MapperIdScopeSpec;
5902     DeclarationNameInfo MapperId;
5903     if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
5904             nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
5905             MapperIdScopeSpec, MapperId, C->getMapType(),
5906             /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
5907             SubExprs, OMPVarListLocTy()))
5908       Clauses.push_back(NewClause);
5909   }
5910 }
5911 
5912 namespace {
5913 /// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
5914 /// call in the associated loop-nest cannot be a 'parallel for'.
5915 class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
5916   Sema &SemaRef;
5917 
5918 public:
teamsLoopCanBeParallelFor() const5919   bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
5920 
5921   // Is there a nested OpenMP loop bind(parallel)
VisitOMPExecutableDirective(const OMPExecutableDirective * D)5922   void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
5923     if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
5924       if (const auto *C = D->getSingleClause<OMPBindClause>())
5925         if (C->getBindKind() == OMPC_BIND_parallel) {
5926           TeamsLoopCanBeParallelFor = false;
5927           // No need to continue visiting any more
5928           return;
5929         }
5930     }
5931     for (const Stmt *Child : D->children())
5932       if (Child)
5933         Visit(Child);
5934   }
5935 
VisitCallExpr(const CallExpr * C)5936   void VisitCallExpr(const CallExpr *C) {
5937     // Function calls inhibit parallel loop translation of 'target teams loop'
5938     // unless the assume-no-nested-parallelism flag has been specified.
5939     // OpenMP API runtime library calls do not inhibit parallel loop
5940     // translation, regardless of the assume-no-nested-parallelism.
5941     bool IsOpenMPAPI = false;
5942     auto *FD = dyn_cast_or_null<FunctionDecl>(C->getCalleeDecl());
5943     if (FD) {
5944       std::string Name = FD->getNameInfo().getAsString();
5945       IsOpenMPAPI = Name.find("omp_") == 0;
5946     }
5947     TeamsLoopCanBeParallelFor =
5948         IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
5949     if (!TeamsLoopCanBeParallelFor)
5950       return;
5951 
5952     for (const Stmt *Child : C->children())
5953       if (Child)
5954         Visit(Child);
5955   }
5956 
VisitCapturedStmt(const CapturedStmt * S)5957   void VisitCapturedStmt(const CapturedStmt *S) {
5958     if (!S)
5959       return;
5960     Visit(S->getCapturedDecl()->getBody());
5961   }
5962 
VisitStmt(const Stmt * S)5963   void VisitStmt(const Stmt *S) {
5964     if (!S)
5965       return;
5966     for (const Stmt *Child : S->children())
5967       if (Child)
5968         Visit(Child);
5969   }
TeamsLoopChecker(Sema & SemaRef)5970   explicit TeamsLoopChecker(Sema &SemaRef)
5971       : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
5972 
5973 private:
5974   bool TeamsLoopCanBeParallelFor;
5975 };
5976 } // namespace
5977 
teamsLoopCanBeParallelFor(Stmt * AStmt,Sema & SemaRef)5978 static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
5979   TeamsLoopChecker Checker(SemaRef);
5980   Checker.Visit(AStmt);
5981   return Checker.teamsLoopCanBeParallelFor();
5982 }
5983 
mapLoopConstruct(llvm::SmallVector<OMPClause * > & ClausesWithoutBind,ArrayRef<OMPClause * > Clauses,OpenMPBindClauseKind & BindKind,OpenMPDirectiveKind & Kind,OpenMPDirectiveKind & PrevMappedDirective,SourceLocation StartLoc,SourceLocation EndLoc,const DeclarationNameInfo & DirName,OpenMPDirectiveKind CancelRegion)5984 bool SemaOpenMP::mapLoopConstruct(
5985     llvm::SmallVector<OMPClause *> &ClausesWithoutBind,
5986     ArrayRef<OMPClause *> Clauses, OpenMPBindClauseKind &BindKind,
5987     OpenMPDirectiveKind &Kind, OpenMPDirectiveKind &PrevMappedDirective,
5988     SourceLocation StartLoc, SourceLocation EndLoc,
5989     const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion) {
5990 
5991   bool UseClausesWithoutBind = false;
5992 
5993   // Restricting to "#pragma omp loop bind"
5994   if (getLangOpts().OpenMP >= 50 && Kind == OMPD_loop) {
5995 
5996     const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
5997 
5998     if (BindKind == OMPC_BIND_unknown) {
5999       // Setting the enclosing teams or parallel construct for the loop
6000       // directive without bind clause.
6001       // [5.0:129:25-28] If the bind clause is not present on the construct and
6002       // the loop construct is closely nested inside a teams or parallel
6003       // construct, the binding region is the corresponding teams or parallel
6004       // region. If none of those conditions hold, the binding region is not
6005       // defined.
6006       BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6007       ArrayRef<OpenMPDirectiveKind> ParentLeafs =
6008           getLeafConstructsOrSelf(ParentDirective);
6009 
6010       if (ParentDirective == OMPD_unknown) {
6011         Diag(DSAStack->getDefaultDSALocation(),
6012              diag::err_omp_bind_required_on_loop);
6013       } else if (ParentLeafs.back() == OMPD_parallel) {
6014         BindKind = OMPC_BIND_parallel;
6015       } else if (ParentLeafs.back() == OMPD_teams) {
6016         BindKind = OMPC_BIND_teams;
6017       }
6018     } else {
6019       // bind clause is present in loop directive. When the loop directive is
6020       // changed to a new directive the bind clause is not used. So, we should
6021       // set flag indicating to only use the clauses that aren't the
6022       // bind clause.
6023       UseClausesWithoutBind = true;
6024     }
6025 
6026     for (OMPClause *C : Clauses) {
6027       // Spec restriction : bind(teams) and reduction not permitted.
6028       if (BindKind == OMPC_BIND_teams &&
6029           C->getClauseKind() == llvm::omp::Clause::OMPC_reduction)
6030         Diag(DSAStack->getDefaultDSALocation(),
6031              diag::err_omp_loop_reduction_clause);
6032 
6033       // A new Vector ClausesWithoutBind, which does not contain the bind
6034       // clause, for passing to new directive.
6035       if (C->getClauseKind() != llvm::omp::Clause::OMPC_bind)
6036         ClausesWithoutBind.push_back(C);
6037     }
6038 
6039     switch (BindKind) {
6040     case OMPC_BIND_parallel:
6041       Kind = OMPD_for;
6042       DSAStack->setCurrentDirective(OMPD_for);
6043       DSAStack->setMappedDirective(OMPD_loop);
6044       PrevMappedDirective = OMPD_loop;
6045       break;
6046     case OMPC_BIND_teams:
6047       Kind = OMPD_distribute;
6048       DSAStack->setCurrentDirective(OMPD_distribute);
6049       DSAStack->setMappedDirective(OMPD_loop);
6050       PrevMappedDirective = OMPD_loop;
6051       break;
6052     case OMPC_BIND_thread:
6053       Kind = OMPD_simd;
6054       DSAStack->setCurrentDirective(OMPD_simd);
6055       DSAStack->setMappedDirective(OMPD_loop);
6056       PrevMappedDirective = OMPD_loop;
6057       break;
6058     case OMPC_BIND_unknown:
6059       break;
6060     }
6061   } else if (PrevMappedDirective == OMPD_loop) {
6062     /// An initial pass after recognizing all the statements is done in the
6063     /// Parser when the directive OMPD_loop is mapped to OMPD_for,
6064     /// OMPD_distribute or OMPD_simd. A second transform pass with call from
6065     /// clang::TreeTransform::TransformOMPExecutableDirective() is done
6066     /// with the Directive as one of the above mapped directive without
6067     /// the bind clause. Then "PrevMappedDirective" stored in the
6068     /// OMPExecutableDirective is accessed and hence this else statement.
6069 
6070     DSAStack->setMappedDirective(OMPD_loop);
6071   }
6072 
6073   return UseClausesWithoutBind;
6074 }
6075 
ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,const DeclarationNameInfo & DirName,OpenMPDirectiveKind CancelRegion,ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,OpenMPDirectiveKind PrevMappedDirective)6076 StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective(
6077     OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6078     OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6079     Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc,
6080     OpenMPDirectiveKind PrevMappedDirective) {
6081   assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
6082 
6083   StmtResult Res = StmtError();
6084   OpenMPBindClauseKind BindKind = OMPC_BIND_unknown;
6085   llvm::SmallVector<OMPClause *> ClausesWithoutBind;
6086   bool UseClausesWithoutBind = false;
6087 
6088   if (const OMPBindClause *BC =
6089           OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6090     BindKind = BC->getBindKind();
6091 
6092   // Variable used to note down the DirectiveKind because mapLoopConstruct may
6093   // change "Kind" variable, due to mapping of "omp loop" to other directives.
6094   OpenMPDirectiveKind DK = Kind;
6095   if (Kind == OMPD_loop || PrevMappedDirective == OMPD_loop) {
6096     UseClausesWithoutBind = mapLoopConstruct(
6097         ClausesWithoutBind, Clauses, BindKind, Kind, PrevMappedDirective,
6098         StartLoc, EndLoc, DirName, CancelRegion);
6099     DK = OMPD_loop;
6100   }
6101 
6102   // First check CancelRegion which is then used in checkNestingOfRegions.
6103   if (checkCancelRegion(SemaRef, Kind, CancelRegion, StartLoc) ||
6104       checkNestingOfRegions(SemaRef, DSAStack, DK, DirName, CancelRegion,
6105                             BindKind, StartLoc)) {
6106     return StmtError();
6107   }
6108 
6109   // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6110   if (getLangOpts().HIP && (isOpenMPTargetExecutionDirective(Kind) ||
6111                             isOpenMPTargetDataManagementDirective(Kind)))
6112     Diag(StartLoc, diag::warn_hip_omp_target_directives);
6113 
6114   llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6115   VarsWithInheritedDSAType VarsWithInheritedDSA;
6116   bool ErrorFound = false;
6117   if (getLangOpts().OpenMP >= 50 && UseClausesWithoutBind) {
6118     ClausesWithImplicit.append(ClausesWithoutBind.begin(),
6119                                ClausesWithoutBind.end());
6120   } else {
6121     ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6122   }
6123   if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6124       isOpenMPCapturingDirective(Kind)) {
6125     assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6126 
6127     // Check default data sharing attributes for referenced variables.
6128     DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(AStmt));
6129     int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6130     Stmt *S = AStmt;
6131     while (--ThisCaptureLevel >= 0)
6132       S = cast<CapturedStmt>(S)->getCapturedStmt();
6133     DSAChecker.Visit(S);
6134     if (!isOpenMPTargetDataManagementDirective(Kind) &&
6135         !isOpenMPTaskingDirective(Kind)) {
6136       // Visit subcaptures to generate implicit clauses for captured vars.
6137       auto *CS = cast<CapturedStmt>(AStmt);
6138       SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
6139       getOpenMPCaptureRegions(CaptureRegions, Kind);
6140       // Ignore outer tasking regions for target directives.
6141       if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6142         CS = cast<CapturedStmt>(CS->getCapturedStmt());
6143       DSAChecker.visitSubCaptures(CS);
6144     }
6145     if (DSAChecker.isErrorFound())
6146       return StmtError();
6147     // Generate list of implicitly defined firstprivate variables.
6148     VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6149 
6150     SmallVector<Expr *, 4> ImplicitFirstprivates(
6151         DSAChecker.getImplicitFirstprivate().begin(),
6152         DSAChecker.getImplicitFirstprivate().end());
6153     SmallVector<Expr *, 4> ImplicitPrivates(
6154         DSAChecker.getImplicitPrivate().begin(),
6155         DSAChecker.getImplicitPrivate().end());
6156     const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
6157     SmallVector<Expr *, 4> ImplicitMaps[DefaultmapKindNum][OMPC_MAP_delete];
6158     SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
6159         ImplicitMapModifiers[DefaultmapKindNum];
6160     SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers>
6161         ImplicitMapModifiersLoc[DefaultmapKindNum];
6162     // Get the original location of present modifier from Defaultmap clause.
6163     SourceLocation PresentModifierLocs[DefaultmapKindNum];
6164     for (OMPClause *C : Clauses) {
6165       if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6166         if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6167           PresentModifierLocs[DMC->getDefaultmapKind()] =
6168               DMC->getDefaultmapModifierLoc();
6169     }
6170     for (unsigned VC = 0; VC < DefaultmapKindNum; ++VC) {
6171       auto K = static_cast<OpenMPDefaultmapClauseKind>(VC);
6172       for (unsigned I = 0; I < OMPC_MAP_delete; ++I) {
6173         ArrayRef<Expr *> ImplicitMap =
6174             DSAChecker.getImplicitMap(K, static_cast<OpenMPMapClauseKind>(I));
6175         ImplicitMaps[VC][I].append(ImplicitMap.begin(), ImplicitMap.end());
6176       }
6177       ArrayRef<OpenMPMapModifierKind> ImplicitModifier =
6178           DSAChecker.getImplicitMapModifier(K);
6179       ImplicitMapModifiers[VC].append(ImplicitModifier.begin(),
6180                                       ImplicitModifier.end());
6181       std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[VC]),
6182                   ImplicitModifier.size(), PresentModifierLocs[VC]);
6183     }
6184     // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6185     for (OMPClause *C : Clauses) {
6186       if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6187         for (Expr *E : IRC->taskgroup_descriptors())
6188           if (E)
6189             ImplicitFirstprivates.emplace_back(E);
6190       }
6191       // OpenMP 5.0, 2.10.1 task Construct
6192       // [detach clause]... The event-handle will be considered as if it was
6193       // specified on a firstprivate clause.
6194       if (auto *DC = dyn_cast<OMPDetachClause>(C))
6195         ImplicitFirstprivates.push_back(DC->getEventHandler());
6196     }
6197     if (!ImplicitFirstprivates.empty()) {
6198       if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
6199               ImplicitFirstprivates, SourceLocation(), SourceLocation(),
6200               SourceLocation())) {
6201         ClausesWithImplicit.push_back(Implicit);
6202         ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6203                      ImplicitFirstprivates.size();
6204       } else {
6205         ErrorFound = true;
6206       }
6207     }
6208     if (!ImplicitPrivates.empty()) {
6209       if (OMPClause *Implicit =
6210               ActOnOpenMPPrivateClause(ImplicitPrivates, SourceLocation(),
6211                                        SourceLocation(), SourceLocation())) {
6212         ClausesWithImplicit.push_back(Implicit);
6213         ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6214                      ImplicitPrivates.size();
6215       } else {
6216         ErrorFound = true;
6217       }
6218     }
6219     // OpenMP 5.0 [2.19.7]
6220     // If a list item appears in a reduction, lastprivate or linear
6221     // clause on a combined target construct then it is treated as
6222     // if it also appears in a map clause with a map-type of tofrom
6223     if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6224         isOpenMPTargetExecutionDirective(Kind)) {
6225       SmallVector<Expr *, 4> ImplicitExprs;
6226       for (OMPClause *C : Clauses) {
6227         if (auto *RC = dyn_cast<OMPReductionClause>(C))
6228           for (Expr *E : RC->varlists())
6229             if (!isa<DeclRefExpr>(E->IgnoreParenImpCasts()))
6230               ImplicitExprs.emplace_back(E);
6231       }
6232       if (!ImplicitExprs.empty()) {
6233         ArrayRef<Expr *> Exprs = ImplicitExprs;
6234         CXXScopeSpec MapperIdScopeSpec;
6235         DeclarationNameInfo MapperId;
6236         if (OMPClause *Implicit = ActOnOpenMPMapClause(
6237                 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(),
6238                 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6239                 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6240                 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6241           ClausesWithImplicit.emplace_back(Implicit);
6242       }
6243     }
6244     for (unsigned I = 0, E = DefaultmapKindNum; I < E; ++I) {
6245       int ClauseKindCnt = -1;
6246       for (ArrayRef<Expr *> ImplicitMap : ImplicitMaps[I]) {
6247         ++ClauseKindCnt;
6248         if (ImplicitMap.empty())
6249           continue;
6250         CXXScopeSpec MapperIdScopeSpec;
6251         DeclarationNameInfo MapperId;
6252         auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6253         if (OMPClause *Implicit = ActOnOpenMPMapClause(
6254                 nullptr, ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I],
6255                 MapperIdScopeSpec, MapperId, K, /*IsMapTypeImplicit=*/true,
6256                 SourceLocation(), SourceLocation(), ImplicitMap,
6257                 OMPVarListLocTy())) {
6258           ClausesWithImplicit.emplace_back(Implicit);
6259           ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6260                         ImplicitMap.size();
6261         } else {
6262           ErrorFound = true;
6263         }
6264       }
6265     }
6266     // Build expressions for implicit maps of data members with 'default'
6267     // mappers.
6268     if (getLangOpts().OpenMP >= 50)
6269       processImplicitMapsWithDefaultMappers(SemaRef, DSAStack,
6270                                             ClausesWithImplicit);
6271   }
6272 
6273   switch (Kind) {
6274   case OMPD_parallel:
6275     Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6276                                        EndLoc);
6277     break;
6278   case OMPD_simd:
6279     Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6280                                    VarsWithInheritedDSA);
6281     break;
6282   case OMPD_tile:
6283     Res =
6284         ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6285     break;
6286   case OMPD_unroll:
6287     Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6288                                      EndLoc);
6289     break;
6290   case OMPD_reverse:
6291     assert(ClausesWithImplicit.empty() &&
6292            "reverse directive does not support any clauses");
6293     Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6294     break;
6295   case OMPD_interchange:
6296     Res = ActOnOpenMPInterchangeDirective(ClausesWithImplicit, AStmt, StartLoc,
6297                                           EndLoc);
6298     break;
6299   case OMPD_for:
6300     Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6301                                   VarsWithInheritedDSA);
6302     break;
6303   case OMPD_for_simd:
6304     Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6305                                       EndLoc, VarsWithInheritedDSA);
6306     break;
6307   case OMPD_sections:
6308     Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6309                                        EndLoc);
6310     break;
6311   case OMPD_section:
6312     assert(ClausesWithImplicit.empty() &&
6313            "No clauses are allowed for 'omp section' directive");
6314     Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6315     break;
6316   case OMPD_single:
6317     Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6318                                      EndLoc);
6319     break;
6320   case OMPD_master:
6321     assert(ClausesWithImplicit.empty() &&
6322            "No clauses are allowed for 'omp master' directive");
6323     Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6324     break;
6325   case OMPD_masked:
6326     Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6327                                      EndLoc);
6328     break;
6329   case OMPD_critical:
6330     Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6331                                        StartLoc, EndLoc);
6332     break;
6333   case OMPD_parallel_for:
6334     Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6335                                           EndLoc, VarsWithInheritedDSA);
6336     break;
6337   case OMPD_parallel_for_simd:
6338     Res = ActOnOpenMPParallelForSimdDirective(
6339         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6340     break;
6341   case OMPD_scope:
6342     Res =
6343         ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6344     break;
6345   case OMPD_parallel_master:
6346     Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6347                                              StartLoc, EndLoc);
6348     break;
6349   case OMPD_parallel_masked:
6350     Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6351                                              StartLoc, EndLoc);
6352     break;
6353   case OMPD_parallel_sections:
6354     Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6355                                                StartLoc, EndLoc);
6356     break;
6357   case OMPD_task:
6358     Res =
6359         ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6360     break;
6361   case OMPD_taskyield:
6362     assert(ClausesWithImplicit.empty() &&
6363            "No clauses are allowed for 'omp taskyield' directive");
6364     assert(AStmt == nullptr &&
6365            "No associated statement allowed for 'omp taskyield' directive");
6366     Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6367     break;
6368   case OMPD_error:
6369     assert(AStmt == nullptr &&
6370            "No associated statement allowed for 'omp error' directive");
6371     Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6372     break;
6373   case OMPD_barrier:
6374     assert(ClausesWithImplicit.empty() &&
6375            "No clauses are allowed for 'omp barrier' directive");
6376     assert(AStmt == nullptr &&
6377            "No associated statement allowed for 'omp barrier' directive");
6378     Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6379     break;
6380   case OMPD_taskwait:
6381     assert(AStmt == nullptr &&
6382            "No associated statement allowed for 'omp taskwait' directive");
6383     Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6384     break;
6385   case OMPD_taskgroup:
6386     Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6387                                         EndLoc);
6388     break;
6389   case OMPD_flush:
6390     assert(AStmt == nullptr &&
6391            "No associated statement allowed for 'omp flush' directive");
6392     Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6393     break;
6394   case OMPD_depobj:
6395     assert(AStmt == nullptr &&
6396            "No associated statement allowed for 'omp depobj' directive");
6397     Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6398     break;
6399   case OMPD_scan:
6400     assert(AStmt == nullptr &&
6401            "No associated statement allowed for 'omp scan' directive");
6402     Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6403     break;
6404   case OMPD_ordered:
6405     Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6406                                       EndLoc);
6407     break;
6408   case OMPD_atomic:
6409     Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6410                                      EndLoc);
6411     break;
6412   case OMPD_teams:
6413     Res =
6414         ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6415     break;
6416   case OMPD_target:
6417     Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6418                                      EndLoc);
6419     break;
6420   case OMPD_target_parallel:
6421     Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6422                                              StartLoc, EndLoc);
6423     break;
6424   case OMPD_target_parallel_for:
6425     Res = ActOnOpenMPTargetParallelForDirective(
6426         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6427     break;
6428   case OMPD_cancellation_point:
6429     assert(ClausesWithImplicit.empty() &&
6430            "No clauses are allowed for 'omp cancellation point' directive");
6431     assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6432                                "cancellation point' directive");
6433     Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6434     break;
6435   case OMPD_cancel:
6436     assert(AStmt == nullptr &&
6437            "No associated statement allowed for 'omp cancel' directive");
6438     Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6439                                      CancelRegion);
6440     break;
6441   case OMPD_target_data:
6442     Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6443                                          EndLoc);
6444     break;
6445   case OMPD_target_enter_data:
6446     Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6447                                               EndLoc, AStmt);
6448     break;
6449   case OMPD_target_exit_data:
6450     Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6451                                              EndLoc, AStmt);
6452     break;
6453   case OMPD_taskloop:
6454     Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6455                                        EndLoc, VarsWithInheritedDSA);
6456     break;
6457   case OMPD_taskloop_simd:
6458     Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6459                                            EndLoc, VarsWithInheritedDSA);
6460     break;
6461   case OMPD_master_taskloop:
6462     Res = ActOnOpenMPMasterTaskLoopDirective(
6463         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6464     break;
6465   case OMPD_masked_taskloop:
6466     Res = ActOnOpenMPMaskedTaskLoopDirective(
6467         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6468     break;
6469   case OMPD_master_taskloop_simd:
6470     Res = ActOnOpenMPMasterTaskLoopSimdDirective(
6471         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6472     break;
6473   case OMPD_masked_taskloop_simd:
6474     Res = ActOnOpenMPMaskedTaskLoopSimdDirective(
6475         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6476     break;
6477   case OMPD_parallel_master_taskloop:
6478     Res = ActOnOpenMPParallelMasterTaskLoopDirective(
6479         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6480     break;
6481   case OMPD_parallel_masked_taskloop:
6482     Res = ActOnOpenMPParallelMaskedTaskLoopDirective(
6483         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6484     break;
6485   case OMPD_parallel_master_taskloop_simd:
6486     Res = ActOnOpenMPParallelMasterTaskLoopSimdDirective(
6487         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6488     break;
6489   case OMPD_parallel_masked_taskloop_simd:
6490     Res = ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
6491         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6492     break;
6493   case OMPD_distribute:
6494     Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6495                                          EndLoc, VarsWithInheritedDSA);
6496     break;
6497   case OMPD_target_update:
6498     Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6499                                            EndLoc, AStmt);
6500     break;
6501   case OMPD_distribute_parallel_for:
6502     Res = ActOnOpenMPDistributeParallelForDirective(
6503         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6504     break;
6505   case OMPD_distribute_parallel_for_simd:
6506     Res = ActOnOpenMPDistributeParallelForSimdDirective(
6507         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6508     break;
6509   case OMPD_distribute_simd:
6510     Res = ActOnOpenMPDistributeSimdDirective(
6511         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6512     break;
6513   case OMPD_target_parallel_for_simd:
6514     Res = ActOnOpenMPTargetParallelForSimdDirective(
6515         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6516     break;
6517   case OMPD_target_simd:
6518     Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6519                                          EndLoc, VarsWithInheritedDSA);
6520     break;
6521   case OMPD_teams_distribute:
6522     Res = ActOnOpenMPTeamsDistributeDirective(
6523         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6524     break;
6525   case OMPD_teams_distribute_simd:
6526     Res = ActOnOpenMPTeamsDistributeSimdDirective(
6527         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6528     break;
6529   case OMPD_teams_distribute_parallel_for_simd:
6530     Res = ActOnOpenMPTeamsDistributeParallelForSimdDirective(
6531         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6532     break;
6533   case OMPD_teams_distribute_parallel_for:
6534     Res = ActOnOpenMPTeamsDistributeParallelForDirective(
6535         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6536     break;
6537   case OMPD_target_teams:
6538     Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6539                                           EndLoc);
6540     break;
6541   case OMPD_target_teams_distribute:
6542     Res = ActOnOpenMPTargetTeamsDistributeDirective(
6543         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6544     break;
6545   case OMPD_target_teams_distribute_parallel_for:
6546     Res = ActOnOpenMPTargetTeamsDistributeParallelForDirective(
6547         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6548     break;
6549   case OMPD_target_teams_distribute_parallel_for_simd:
6550     Res = ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
6551         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6552     break;
6553   case OMPD_target_teams_distribute_simd:
6554     Res = ActOnOpenMPTargetTeamsDistributeSimdDirective(
6555         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6556     break;
6557   case OMPD_interop:
6558     assert(AStmt == nullptr &&
6559            "No associated statement allowed for 'omp interop' directive");
6560     Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6561     break;
6562   case OMPD_dispatch:
6563     Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6564                                        EndLoc);
6565     break;
6566   case OMPD_loop:
6567     Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6568                                           EndLoc, VarsWithInheritedDSA);
6569     break;
6570   case OMPD_teams_loop:
6571     Res = ActOnOpenMPTeamsGenericLoopDirective(
6572         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6573     break;
6574   case OMPD_target_teams_loop:
6575     Res = ActOnOpenMPTargetTeamsGenericLoopDirective(
6576         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6577     break;
6578   case OMPD_parallel_loop:
6579     Res = ActOnOpenMPParallelGenericLoopDirective(
6580         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6581     break;
6582   case OMPD_target_parallel_loop:
6583     Res = ActOnOpenMPTargetParallelGenericLoopDirective(
6584         ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6585     break;
6586   case OMPD_declare_target:
6587   case OMPD_end_declare_target:
6588   case OMPD_threadprivate:
6589   case OMPD_allocate:
6590   case OMPD_declare_reduction:
6591   case OMPD_declare_mapper:
6592   case OMPD_declare_simd:
6593   case OMPD_requires:
6594   case OMPD_declare_variant:
6595   case OMPD_begin_declare_variant:
6596   case OMPD_end_declare_variant:
6597     llvm_unreachable("OpenMP Directive is not allowed");
6598   case OMPD_unknown:
6599   default:
6600     llvm_unreachable("Unknown OpenMP directive");
6601   }
6602 
6603   ErrorFound = Res.isInvalid() || ErrorFound;
6604 
6605   // Check variables in the clauses if default(none) or
6606   // default(firstprivate) was specified.
6607   if (DSAStack->getDefaultDSA() == DSA_none ||
6608       DSAStack->getDefaultDSA() == DSA_private ||
6609       DSAStack->getDefaultDSA() == DSA_firstprivate) {
6610     DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6611     for (OMPClause *C : Clauses) {
6612       switch (C->getClauseKind()) {
6613       case OMPC_num_threads:
6614       case OMPC_dist_schedule:
6615         // Do not analyze if no parent teams directive.
6616         if (isOpenMPTeamsDirective(Kind))
6617           break;
6618         continue;
6619       case OMPC_if:
6620         if (isOpenMPTeamsDirective(Kind) &&
6621             cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6622           break;
6623         if (isOpenMPParallelDirective(Kind) &&
6624             isOpenMPTaskLoopDirective(Kind) &&
6625             cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6626           break;
6627         continue;
6628       case OMPC_schedule:
6629       case OMPC_detach:
6630         break;
6631       case OMPC_grainsize:
6632       case OMPC_num_tasks:
6633       case OMPC_final:
6634       case OMPC_priority:
6635       case OMPC_novariants:
6636       case OMPC_nocontext:
6637         // Do not analyze if no parent parallel directive.
6638         if (isOpenMPParallelDirective(Kind))
6639           break;
6640         continue;
6641       case OMPC_ordered:
6642       case OMPC_device:
6643       case OMPC_num_teams:
6644       case OMPC_thread_limit:
6645       case OMPC_hint:
6646       case OMPC_collapse:
6647       case OMPC_safelen:
6648       case OMPC_simdlen:
6649       case OMPC_sizes:
6650       case OMPC_default:
6651       case OMPC_proc_bind:
6652       case OMPC_private:
6653       case OMPC_firstprivate:
6654       case OMPC_lastprivate:
6655       case OMPC_shared:
6656       case OMPC_reduction:
6657       case OMPC_task_reduction:
6658       case OMPC_in_reduction:
6659       case OMPC_linear:
6660       case OMPC_aligned:
6661       case OMPC_copyin:
6662       case OMPC_copyprivate:
6663       case OMPC_nowait:
6664       case OMPC_untied:
6665       case OMPC_mergeable:
6666       case OMPC_allocate:
6667       case OMPC_read:
6668       case OMPC_write:
6669       case OMPC_update:
6670       case OMPC_capture:
6671       case OMPC_compare:
6672       case OMPC_seq_cst:
6673       case OMPC_acq_rel:
6674       case OMPC_acquire:
6675       case OMPC_release:
6676       case OMPC_relaxed:
6677       case OMPC_depend:
6678       case OMPC_threads:
6679       case OMPC_simd:
6680       case OMPC_map:
6681       case OMPC_nogroup:
6682       case OMPC_defaultmap:
6683       case OMPC_to:
6684       case OMPC_from:
6685       case OMPC_use_device_ptr:
6686       case OMPC_use_device_addr:
6687       case OMPC_is_device_ptr:
6688       case OMPC_has_device_addr:
6689       case OMPC_nontemporal:
6690       case OMPC_order:
6691       case OMPC_destroy:
6692       case OMPC_inclusive:
6693       case OMPC_exclusive:
6694       case OMPC_uses_allocators:
6695       case OMPC_affinity:
6696       case OMPC_bind:
6697       case OMPC_filter:
6698         continue;
6699       case OMPC_allocator:
6700       case OMPC_flush:
6701       case OMPC_depobj:
6702       case OMPC_threadprivate:
6703       case OMPC_uniform:
6704       case OMPC_unknown:
6705       case OMPC_unified_address:
6706       case OMPC_unified_shared_memory:
6707       case OMPC_reverse_offload:
6708       case OMPC_dynamic_allocators:
6709       case OMPC_atomic_default_mem_order:
6710       case OMPC_device_type:
6711       case OMPC_match:
6712       case OMPC_when:
6713       case OMPC_at:
6714       case OMPC_severity:
6715       case OMPC_message:
6716       default:
6717         llvm_unreachable("Unexpected clause");
6718       }
6719       for (Stmt *CC : C->children()) {
6720         if (CC)
6721           DSAChecker.Visit(CC);
6722       }
6723     }
6724     for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6725       VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6726   }
6727   for (const auto &P : VarsWithInheritedDSA) {
6728     if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6729       continue;
6730     ErrorFound = true;
6731     if (DSAStack->getDefaultDSA() == DSA_none ||
6732         DSAStack->getDefaultDSA() == DSA_private ||
6733         DSAStack->getDefaultDSA() == DSA_firstprivate) {
6734       Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6735           << P.first << P.second->getSourceRange();
6736       Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6737     } else if (getLangOpts().OpenMP >= 50) {
6738       Diag(P.second->getExprLoc(),
6739            diag::err_omp_defaultmap_no_attr_for_variable)
6740           << P.first << P.second->getSourceRange();
6741       Diag(DSAStack->getDefaultDSALocation(),
6742            diag::note_omp_defaultmap_attr_none);
6743     }
6744   }
6745 
6746   llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6747   for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(Kind)) {
6748     if (isAllowedClauseForDirective(D, OMPC_if, getLangOpts().OpenMP))
6749       AllowedNameModifiers.push_back(D);
6750   }
6751   if (!AllowedNameModifiers.empty())
6752     ErrorFound = checkIfClauses(SemaRef, Kind, Clauses, AllowedNameModifiers) ||
6753                  ErrorFound;
6754 
6755   if (ErrorFound)
6756     return StmtError();
6757 
6758   if (!SemaRef.CurContext->isDependentContext() &&
6759       isOpenMPTargetExecutionDirective(Kind) &&
6760       !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6761         DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6762         DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6763         DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6764     // Register target to DSA Stack.
6765     DSAStack->addTargetDirLocation(StartLoc);
6766   }
6767 
6768   return Res;
6769 }
6770 
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)6771 SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareSimdDirective(
6772     DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6773     ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6774     ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6775     ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6776   assert(Aligneds.size() == Alignments.size());
6777   assert(Linears.size() == LinModifiers.size());
6778   assert(Linears.size() == Steps.size());
6779   if (!DG || DG.get().isNull())
6780     return DeclGroupPtrTy();
6781 
6782   const int SimdId = 0;
6783   if (!DG.get().isSingleDecl()) {
6784     Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6785         << SimdId;
6786     return DG;
6787   }
6788   Decl *ADecl = DG.get().getSingleDecl();
6789   if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6790     ADecl = FTD->getTemplatedDecl();
6791 
6792   auto *FD = dyn_cast<FunctionDecl>(ADecl);
6793   if (!FD) {
6794     Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6795     return DeclGroupPtrTy();
6796   }
6797 
6798   // OpenMP [2.8.2, declare simd construct, Description]
6799   // The parameter of the simdlen clause must be a constant positive integer
6800   // expression.
6801   ExprResult SL;
6802   if (Simdlen)
6803     SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6804   // OpenMP [2.8.2, declare simd construct, Description]
6805   // The special this pointer can be used as if was one of the arguments to the
6806   // function in any of the linear, aligned, or uniform clauses.
6807   // The uniform clause declares one or more arguments to have an invariant
6808   // value for all concurrent invocations of the function in the execution of a
6809   // single SIMD loop.
6810   llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6811   const Expr *UniformedLinearThis = nullptr;
6812   for (const Expr *E : Uniforms) {
6813     E = E->IgnoreParenImpCasts();
6814     if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6815       if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6816         if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6817             FD->getParamDecl(PVD->getFunctionScopeIndex())
6818                     ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
6819           UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6820           continue;
6821         }
6822     if (isa<CXXThisExpr>(E)) {
6823       UniformedLinearThis = E;
6824       continue;
6825     }
6826     Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6827         << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6828   }
6829   // OpenMP [2.8.2, declare simd construct, Description]
6830   // The aligned clause declares that the object to which each list item points
6831   // is aligned to the number of bytes expressed in the optional parameter of
6832   // the aligned clause.
6833   // The special this pointer can be used as if was one of the arguments to the
6834   // function in any of the linear, aligned, or uniform clauses.
6835   // The type of list items appearing in the aligned clause must be array,
6836   // pointer, reference to array, or reference to pointer.
6837   llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6838   const Expr *AlignedThis = nullptr;
6839   for (const Expr *E : Aligneds) {
6840     E = E->IgnoreParenImpCasts();
6841     if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6842       if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6843         const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6844         if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6845             FD->getParamDecl(PVD->getFunctionScopeIndex())
6846                     ->getCanonicalDecl() == CanonPVD) {
6847           // OpenMP  [2.8.1, simd construct, Restrictions]
6848           // A list-item cannot appear in more than one aligned clause.
6849           if (AlignedArgs.count(CanonPVD) > 0) {
6850             Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6851                 << 1 << getOpenMPClauseName(OMPC_aligned)
6852                 << E->getSourceRange();
6853             Diag(AlignedArgs[CanonPVD]->getExprLoc(),
6854                  diag::note_omp_explicit_dsa)
6855                 << getOpenMPClauseName(OMPC_aligned);
6856             continue;
6857           }
6858           AlignedArgs[CanonPVD] = E;
6859           QualType QTy = PVD->getType()
6860                              .getNonReferenceType()
6861                              .getUnqualifiedType()
6862                              .getCanonicalType();
6863           const Type *Ty = QTy.getTypePtrOrNull();
6864           if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
6865             Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
6866                 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
6867             Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6868           }
6869           continue;
6870         }
6871       }
6872     if (isa<CXXThisExpr>(E)) {
6873       if (AlignedThis) {
6874         Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6875             << 2 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange();
6876         Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
6877             << getOpenMPClauseName(OMPC_aligned);
6878       }
6879       AlignedThis = E;
6880       continue;
6881     }
6882     Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6883         << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6884   }
6885   // The optional parameter of the aligned clause, alignment, must be a constant
6886   // positive integer expression. If no optional parameter is specified,
6887   // implementation-defined default alignments for SIMD instructions on the
6888   // target platforms are assumed.
6889   SmallVector<const Expr *, 4> NewAligns;
6890   for (Expr *E : Alignments) {
6891     ExprResult Align;
6892     if (E)
6893       Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
6894     NewAligns.push_back(Align.get());
6895   }
6896   // OpenMP [2.8.2, declare simd construct, Description]
6897   // The linear clause declares one or more list items to be private to a SIMD
6898   // lane and to have a linear relationship with respect to the iteration space
6899   // of a loop.
6900   // The special this pointer can be used as if was one of the arguments to the
6901   // function in any of the linear, aligned, or uniform clauses.
6902   // When a linear-step expression is specified in a linear clause it must be
6903   // either a constant integer expression or an integer-typed parameter that is
6904   // specified in a uniform clause on the directive.
6905   llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
6906   const bool IsUniformedThis = UniformedLinearThis != nullptr;
6907   auto MI = LinModifiers.begin();
6908   for (const Expr *E : Linears) {
6909     auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
6910     ++MI;
6911     E = E->IgnoreParenImpCasts();
6912     if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6913       if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6914         const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6915         if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6916             FD->getParamDecl(PVD->getFunctionScopeIndex())
6917                     ->getCanonicalDecl() == CanonPVD) {
6918           // OpenMP  [2.15.3.7, linear Clause, Restrictions]
6919           // A list-item cannot appear in more than one linear clause.
6920           if (LinearArgs.count(CanonPVD) > 0) {
6921             Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6922                 << getOpenMPClauseName(OMPC_linear)
6923                 << getOpenMPClauseName(OMPC_linear) << E->getSourceRange();
6924             Diag(LinearArgs[CanonPVD]->getExprLoc(),
6925                  diag::note_omp_explicit_dsa)
6926                 << getOpenMPClauseName(OMPC_linear);
6927             continue;
6928           }
6929           // Each argument can appear in at most one uniform or linear clause.
6930           if (UniformedArgs.count(CanonPVD) > 0) {
6931             Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6932                 << getOpenMPClauseName(OMPC_linear)
6933                 << getOpenMPClauseName(OMPC_uniform) << E->getSourceRange();
6934             Diag(UniformedArgs[CanonPVD]->getExprLoc(),
6935                  diag::note_omp_explicit_dsa)
6936                 << getOpenMPClauseName(OMPC_uniform);
6937             continue;
6938           }
6939           LinearArgs[CanonPVD] = E;
6940           if (E->isValueDependent() || E->isTypeDependent() ||
6941               E->isInstantiationDependent() ||
6942               E->containsUnexpandedParameterPack())
6943             continue;
6944           (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
6945                                       PVD->getOriginalType(),
6946                                       /*IsDeclareSimd=*/true);
6947           continue;
6948         }
6949       }
6950     if (isa<CXXThisExpr>(E)) {
6951       if (UniformedLinearThis) {
6952         Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6953             << getOpenMPClauseName(OMPC_linear)
6954             << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear)
6955             << E->getSourceRange();
6956         Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
6957             << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform
6958                                                    : OMPC_linear);
6959         continue;
6960       }
6961       UniformedLinearThis = E;
6962       if (E->isValueDependent() || E->isTypeDependent() ||
6963           E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
6964         continue;
6965       (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
6966                                   E->getType(), /*IsDeclareSimd=*/true);
6967       continue;
6968     }
6969     Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6970         << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6971   }
6972   Expr *Step = nullptr;
6973   Expr *NewStep = nullptr;
6974   SmallVector<Expr *, 4> NewSteps;
6975   for (Expr *E : Steps) {
6976     // Skip the same step expression, it was checked already.
6977     if (Step == E || !E) {
6978       NewSteps.push_back(E ? NewStep : nullptr);
6979       continue;
6980     }
6981     Step = E;
6982     if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
6983       if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6984         const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6985         if (UniformedArgs.count(CanonPVD) == 0) {
6986           Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
6987               << Step->getSourceRange();
6988         } else if (E->isValueDependent() || E->isTypeDependent() ||
6989                    E->isInstantiationDependent() ||
6990                    E->containsUnexpandedParameterPack() ||
6991                    CanonPVD->getType()->hasIntegerRepresentation()) {
6992           NewSteps.push_back(Step);
6993         } else {
6994           Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
6995               << Step->getSourceRange();
6996         }
6997         continue;
6998       }
6999     NewStep = Step;
7000     if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
7001         !Step->isInstantiationDependent() &&
7002         !Step->containsUnexpandedParameterPack()) {
7003       NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
7004                     .get();
7005       if (NewStep)
7006         NewStep = SemaRef
7007                       .VerifyIntegerConstantExpression(
7008                           NewStep, /*FIXME*/ Sema::AllowFold)
7009                       .get();
7010     }
7011     NewSteps.push_back(NewStep);
7012   }
7013   auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7014       getASTContext(), BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
7015       Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
7016       const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
7017       const_cast<Expr **>(Linears.data()), Linears.size(),
7018       const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
7019       NewSteps.data(), NewSteps.size(), SR);
7020   ADecl->addAttr(NewAttr);
7021   return DG;
7022 }
7023 
setPrototype(Sema & S,FunctionDecl * FD,FunctionDecl * FDWithProto,QualType NewType)7024 static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7025                          QualType NewType) {
7026   assert(NewType->isFunctionProtoType() &&
7027          "Expected function type with prototype.");
7028   assert(FD->getType()->isFunctionNoProtoType() &&
7029          "Expected function with type with no prototype.");
7030   assert(FDWithProto->getType()->isFunctionProtoType() &&
7031          "Expected function with prototype.");
7032   // Synthesize parameters with the same types.
7033   FD->setType(NewType);
7034   SmallVector<ParmVarDecl *, 16> Params;
7035   for (const ParmVarDecl *P : FDWithProto->parameters()) {
7036     auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
7037                                       SourceLocation(), nullptr, P->getType(),
7038                                       /*TInfo=*/nullptr, SC_None, nullptr);
7039     Param->setScopeInfo(0, Params.size());
7040     Param->setImplicit();
7041     Params.push_back(Param);
7042   }
7043 
7044   FD->setParams(Params);
7045 }
7046 
ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl * D)7047 void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) {
7048   if (D->isInvalidDecl())
7049     return;
7050   FunctionDecl *FD = nullptr;
7051   if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7052     FD = UTemplDecl->getTemplatedDecl();
7053   else
7054     FD = cast<FunctionDecl>(D);
7055   assert(FD && "Expected a function declaration!");
7056 
7057   // If we are instantiating templates we do *not* apply scoped assumptions but
7058   // only global ones. We apply scoped assumption to the template definition
7059   // though.
7060   if (!SemaRef.inTemplateInstantiation()) {
7061     for (OMPAssumeAttr *AA : OMPAssumeScoped)
7062       FD->addAttr(AA);
7063   }
7064   for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7065     FD->addAttr(AA);
7066 }
7067 
OMPDeclareVariantScope(OMPTraitInfo & TI)7068 SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7069     : TI(&TI), NameSuffix(TI.getMangledName()) {}
7070 
ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope * S,Declarator & D,MultiTemplateParamsArg TemplateParamLists,SmallVectorImpl<FunctionDecl * > & Bases)7071 void SemaOpenMP::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
7072     Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7073     SmallVectorImpl<FunctionDecl *> &Bases) {
7074   if (!D.getIdentifier())
7075     return;
7076 
7077   OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7078 
7079   // Template specialization is an extension, check if we do it.
7080   bool IsTemplated = !TemplateParamLists.empty();
7081   if (IsTemplated &&
7082       !DVScope.TI->isExtensionActive(
7083           llvm::omp::TraitProperty::implementation_extension_allow_templates))
7084     return;
7085 
7086   const IdentifierInfo *BaseII = D.getIdentifier();
7087   LookupResult Lookup(SemaRef, DeclarationName(BaseII), D.getIdentifierLoc(),
7088                       Sema::LookupOrdinaryName);
7089   SemaRef.LookupParsedName(Lookup, S, &D.getCXXScopeSpec(),
7090                            /*ObjectType=*/QualType());
7091 
7092   TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
7093   QualType FType = TInfo->getType();
7094 
7095   bool IsConstexpr =
7096       D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr;
7097   bool IsConsteval =
7098       D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval;
7099 
7100   for (auto *Candidate : Lookup) {
7101     auto *CandidateDecl = Candidate->getUnderlyingDecl();
7102     FunctionDecl *UDecl = nullptr;
7103     if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7104       auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7105       if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7106         UDecl = FTD->getTemplatedDecl();
7107     } else if (!IsTemplated)
7108       UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7109     if (!UDecl)
7110       continue;
7111 
7112     // Don't specialize constexpr/consteval functions with
7113     // non-constexpr/consteval functions.
7114     if (UDecl->isConstexpr() && !IsConstexpr)
7115       continue;
7116     if (UDecl->isConsteval() && !IsConsteval)
7117       continue;
7118 
7119     QualType UDeclTy = UDecl->getType();
7120     if (!UDeclTy->isDependentType()) {
7121       QualType NewType = getASTContext().mergeFunctionTypes(
7122           FType, UDeclTy, /* OfBlockPointer */ false,
7123           /* Unqualified */ false, /* AllowCXX */ true);
7124       if (NewType.isNull())
7125         continue;
7126     }
7127 
7128     // Found a base!
7129     Bases.push_back(UDecl);
7130   }
7131 
7132   bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7133       llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7134   // If no base was found we create a declaration that we use as base.
7135   if (Bases.empty() && UseImplicitBase) {
7136     D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
7137     Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7138     BaseD->setImplicit(true);
7139     if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7140       Bases.push_back(BaseTemplD->getTemplatedDecl());
7141     else
7142       Bases.push_back(cast<FunctionDecl>(BaseD));
7143   }
7144 
7145   std::string MangledName;
7146   MangledName += D.getIdentifier()->getName();
7147   MangledName += getOpenMPVariantManglingSeparatorStr();
7148   MangledName += DVScope.NameSuffix;
7149   IdentifierInfo &VariantII = getASTContext().Idents.get(MangledName);
7150 
7151   VariantII.setMangledOpenMPVariantName(true);
7152   D.SetIdentifier(&VariantII, D.getBeginLoc());
7153 }
7154 
ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(Decl * D,SmallVectorImpl<FunctionDecl * > & Bases)7155 void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
7156     Decl *D, SmallVectorImpl<FunctionDecl *> &Bases) {
7157   // Do not mark function as is used to prevent its emission if this is the
7158   // only place where it is used.
7159   EnterExpressionEvaluationContext Unevaluated(
7160       SemaRef, Sema::ExpressionEvaluationContext::Unevaluated);
7161 
7162   FunctionDecl *FD = nullptr;
7163   if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7164     FD = UTemplDecl->getTemplatedDecl();
7165   else
7166     FD = cast<FunctionDecl>(D);
7167   auto *VariantFuncRef = DeclRefExpr::Create(
7168       getASTContext(), NestedNameSpecifierLoc(), SourceLocation(), FD,
7169       /* RefersToEnclosingVariableOrCapture */ false,
7170       /* NameLoc */ FD->getLocation(), FD->getType(),
7171       ExprValueKind::VK_PRValue);
7172 
7173   OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7174   auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7175       getASTContext(), VariantFuncRef, DVScope.TI,
7176       /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7177       /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7178       /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7179   for (FunctionDecl *BaseFD : Bases)
7180     BaseFD->addAttr(OMPDeclareVariantA);
7181 }
7182 
ActOnOpenMPCall(ExprResult Call,Scope * Scope,SourceLocation LParenLoc,MultiExprArg ArgExprs,SourceLocation RParenLoc,Expr * ExecConfig)7183 ExprResult SemaOpenMP::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
7184                                        SourceLocation LParenLoc,
7185                                        MultiExprArg ArgExprs,
7186                                        SourceLocation RParenLoc,
7187                                        Expr *ExecConfig) {
7188   // The common case is a regular call we do not want to specialize at all. Try
7189   // to make that case fast by bailing early.
7190   CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7191   if (!CE)
7192     return Call;
7193 
7194   FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7195   if (!CalleeFnDecl)
7196     return Call;
7197 
7198   if (getLangOpts().OpenMP >= 51 && CalleeFnDecl->getIdentifier() &&
7199       CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7200     // checking for any calls inside an Order region
7201     if (Scope && Scope->isOpenMPOrderClauseScope())
7202       Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7203   }
7204 
7205   if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7206     return Call;
7207 
7208   ASTContext &Context = getASTContext();
7209   std::function<void(StringRef)> DiagUnknownTrait = [this,
7210                                                      CE](StringRef ISATrait) {
7211     // TODO Track the selector locations in a way that is accessible here to
7212     // improve the diagnostic location.
7213     Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7214         << ISATrait;
7215   };
7216   TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7217                           SemaRef.getCurFunctionDecl(),
7218                           DSAStack->getConstructTraits());
7219 
7220   QualType CalleeFnType = CalleeFnDecl->getType();
7221 
7222   SmallVector<Expr *, 4> Exprs;
7223   SmallVector<VariantMatchInfo, 4> VMIs;
7224   while (CalleeFnDecl) {
7225     for (OMPDeclareVariantAttr *A :
7226          CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7227       Expr *VariantRef = A->getVariantFuncRef();
7228 
7229       VariantMatchInfo VMI;
7230       OMPTraitInfo &TI = A->getTraitInfo();
7231       TI.getAsVariantMatchInfo(Context, VMI);
7232       if (!isVariantApplicableInContext(VMI, OMPCtx,
7233                                         /* DeviceSetOnly */ false))
7234         continue;
7235 
7236       VMIs.push_back(VMI);
7237       Exprs.push_back(VariantRef);
7238     }
7239 
7240     CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7241   }
7242 
7243   ExprResult NewCall;
7244   do {
7245     int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7246     if (BestIdx < 0)
7247       return Call;
7248     Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7249     Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7250 
7251     {
7252       // Try to build a (member) call expression for the current best applicable
7253       // variant expression. We allow this to fail in which case we continue
7254       // with the next best variant expression. The fail case is part of the
7255       // implementation defined behavior in the OpenMP standard when it talks
7256       // about what differences in the function prototypes: "Any differences
7257       // that the specific OpenMP context requires in the prototype of the
7258       // variant from the base function prototype are implementation defined."
7259       // This wording is there to allow the specialized variant to have a
7260       // different type than the base function. This is intended and OK but if
7261       // we cannot create a call the difference is not in the "implementation
7262       // defined range" we allow.
7263       Sema::TentativeAnalysisScope Trap(SemaRef);
7264 
7265       if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7266         auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7267         BestExpr = MemberExpr::CreateImplicit(
7268             Context, MemberCall->getImplicitObjectArgument(),
7269             /* IsArrow */ false, SpecializedMethod, Context.BoundMemberTy,
7270             MemberCall->getValueKind(), MemberCall->getObjectKind());
7271       }
7272       NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs,
7273                                       RParenLoc, ExecConfig);
7274       if (NewCall.isUsable()) {
7275         if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7276           FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7277           QualType NewType = getASTContext().mergeFunctionTypes(
7278               CalleeFnType, NewCalleeFnDecl->getType(),
7279               /* OfBlockPointer */ false,
7280               /* Unqualified */ false, /* AllowCXX */ true);
7281           if (!NewType.isNull())
7282             break;
7283           // Don't use the call if the function type was not compatible.
7284           NewCall = nullptr;
7285         }
7286       }
7287     }
7288 
7289     VMIs.erase(VMIs.begin() + BestIdx);
7290     Exprs.erase(Exprs.begin() + BestIdx);
7291   } while (!VMIs.empty());
7292 
7293   if (!NewCall.isUsable())
7294     return Call;
7295   return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
7296 }
7297 
7298 std::optional<std::pair<FunctionDecl *, Expr *>>
checkOpenMPDeclareVariantFunction(SemaOpenMP::DeclGroupPtrTy DG,Expr * VariantRef,OMPTraitInfo & TI,unsigned NumAppendArgs,SourceRange SR)7299 SemaOpenMP::checkOpenMPDeclareVariantFunction(SemaOpenMP::DeclGroupPtrTy DG,
7300                                               Expr *VariantRef,
7301                                               OMPTraitInfo &TI,
7302                                               unsigned NumAppendArgs,
7303                                               SourceRange SR) {
7304   ASTContext &Context = getASTContext();
7305   if (!DG || DG.get().isNull())
7306     return std::nullopt;
7307 
7308   const int VariantId = 1;
7309   // Must be applied only to single decl.
7310   if (!DG.get().isSingleDecl()) {
7311     Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7312         << VariantId << SR;
7313     return std::nullopt;
7314   }
7315   Decl *ADecl = DG.get().getSingleDecl();
7316   if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7317     ADecl = FTD->getTemplatedDecl();
7318 
7319   // Decl must be a function.
7320   auto *FD = dyn_cast<FunctionDecl>(ADecl);
7321   if (!FD) {
7322     Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7323         << VariantId << SR;
7324     return std::nullopt;
7325   }
7326 
7327   auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7328     // The 'target' attribute needs to be separately checked because it does
7329     // not always signify a multiversion function declaration.
7330     return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7331   };
7332   // OpenMP is not compatible with multiversion function attributes.
7333   if (HasMultiVersionAttributes(FD)) {
7334     Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7335         << SR;
7336     return std::nullopt;
7337   }
7338 
7339   // Allow #pragma omp declare variant only if the function is not used.
7340   if (FD->isUsed(false))
7341     Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7342         << FD->getLocation();
7343 
7344   // Check if the function was emitted already.
7345   const FunctionDecl *Definition;
7346   if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7347       (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7348     Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7349         << FD->getLocation();
7350 
7351   // The VariantRef must point to function.
7352   if (!VariantRef) {
7353     Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7354     return std::nullopt;
7355   }
7356 
7357   auto ShouldDelayChecks = [](Expr *&E, bool) {
7358     return E && (E->isTypeDependent() || E->isValueDependent() ||
7359                  E->containsUnexpandedParameterPack() ||
7360                  E->isInstantiationDependent());
7361   };
7362   // Do not check templates, wait until instantiation.
7363   if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7364       TI.anyScoreOrCondition(ShouldDelayChecks))
7365     return std::make_pair(FD, VariantRef);
7366 
7367   // Deal with non-constant score and user condition expressions.
7368   auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7369                                                      bool IsScore) -> bool {
7370     if (!E || E->isIntegerConstantExpr(getASTContext()))
7371       return false;
7372 
7373     if (IsScore) {
7374       // We warn on non-constant scores and pretend they were not present.
7375       Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7376           << E;
7377       E = nullptr;
7378     } else {
7379       // We could replace a non-constant user condition with "false" but we
7380       // will soon need to handle these anyway for the dynamic version of
7381       // OpenMP context selectors.
7382       Diag(E->getExprLoc(),
7383            diag::err_omp_declare_variant_user_condition_not_constant)
7384           << E;
7385     }
7386     return true;
7387   };
7388   if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7389     return std::nullopt;
7390 
7391   QualType AdjustedFnType = FD->getType();
7392   if (NumAppendArgs) {
7393     const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7394     if (!PTy) {
7395       Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7396           << SR;
7397       return std::nullopt;
7398     }
7399     // Adjust the function type to account for an extra omp_interop_t for each
7400     // specified in the append_args clause.
7401     const TypeDecl *TD = nullptr;
7402     LookupResult Result(SemaRef, &Context.Idents.get("omp_interop_t"),
7403                         SR.getBegin(), Sema::LookupOrdinaryName);
7404     if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
7405       NamedDecl *ND = Result.getFoundDecl();
7406       TD = dyn_cast_or_null<TypeDecl>(ND);
7407     }
7408     if (!TD) {
7409       Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7410       return std::nullopt;
7411     }
7412     QualType InteropType = Context.getTypeDeclType(TD);
7413     if (PTy->isVariadic()) {
7414       Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7415       return std::nullopt;
7416     }
7417     llvm::SmallVector<QualType, 8> Params;
7418     Params.append(PTy->param_type_begin(), PTy->param_type_end());
7419     Params.insert(Params.end(), NumAppendArgs, InteropType);
7420     AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7421                                              PTy->getExtProtoInfo());
7422   }
7423 
7424   // Convert VariantRef expression to the type of the original function to
7425   // resolve possible conflicts.
7426   ExprResult VariantRefCast = VariantRef;
7427   if (getLangOpts().CPlusPlus) {
7428     QualType FnPtrType;
7429     auto *Method = dyn_cast<CXXMethodDecl>(FD);
7430     if (Method && !Method->isStatic()) {
7431       const Type *ClassType =
7432           Context.getTypeDeclType(Method->getParent()).getTypePtr();
7433       FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType);
7434       ExprResult ER;
7435       {
7436         // Build addr_of unary op to correctly handle type checks for member
7437         // functions.
7438         Sema::TentativeAnalysisScope Trap(SemaRef);
7439         ER = SemaRef.CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7440                                           VariantRef);
7441       }
7442       if (!ER.isUsable()) {
7443         Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7444             << VariantId << VariantRef->getSourceRange();
7445         return std::nullopt;
7446       }
7447       VariantRef = ER.get();
7448     } else {
7449       FnPtrType = Context.getPointerType(AdjustedFnType);
7450     }
7451     QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7452     if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7453       ImplicitConversionSequence ICS = SemaRef.TryImplicitConversion(
7454           VariantRef, FnPtrType.getUnqualifiedType(),
7455           /*SuppressUserConversions=*/false, Sema::AllowedExplicit::None,
7456           /*InOverloadResolution=*/false,
7457           /*CStyle=*/false,
7458           /*AllowObjCWritebackConversion=*/false);
7459       if (ICS.isFailure()) {
7460         Diag(VariantRef->getExprLoc(),
7461              diag::err_omp_declare_variant_incompat_types)
7462             << VariantRef->getType()
7463             << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7464             << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7465         return std::nullopt;
7466       }
7467       VariantRefCast = SemaRef.PerformImplicitConversion(
7468           VariantRef, FnPtrType.getUnqualifiedType(), Sema::AA_Converting);
7469       if (!VariantRefCast.isUsable())
7470         return std::nullopt;
7471     }
7472     // Drop previously built artificial addr_of unary op for member functions.
7473     if (Method && !Method->isStatic()) {
7474       Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7475       if (auto *UO = dyn_cast<UnaryOperator>(
7476               PossibleAddrOfVariantRef->IgnoreImplicit()))
7477         VariantRefCast = UO->getSubExpr();
7478     }
7479   }
7480 
7481   ExprResult ER = SemaRef.CheckPlaceholderExpr(VariantRefCast.get());
7482   if (!ER.isUsable() ||
7483       !ER.get()->IgnoreParenImpCasts()->getType()->isFunctionType()) {
7484     Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7485         << VariantId << VariantRef->getSourceRange();
7486     return std::nullopt;
7487   }
7488 
7489   // The VariantRef must point to function.
7490   auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7491   if (!DRE) {
7492     Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7493         << VariantId << VariantRef->getSourceRange();
7494     return std::nullopt;
7495   }
7496   auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7497   if (!NewFD) {
7498     Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7499         << VariantId << VariantRef->getSourceRange();
7500     return std::nullopt;
7501   }
7502 
7503   if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7504     Diag(VariantRef->getExprLoc(),
7505          diag::err_omp_declare_variant_same_base_function)
7506         << VariantRef->getSourceRange();
7507     return std::nullopt;
7508   }
7509 
7510   // Check if function types are compatible in C.
7511   if (!getLangOpts().CPlusPlus) {
7512     QualType NewType =
7513         Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7514     if (NewType.isNull()) {
7515       Diag(VariantRef->getExprLoc(),
7516            diag::err_omp_declare_variant_incompat_types)
7517           << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7518           << VariantRef->getSourceRange();
7519       return std::nullopt;
7520     }
7521     if (NewType->isFunctionProtoType()) {
7522       if (FD->getType()->isFunctionNoProtoType())
7523         setPrototype(SemaRef, FD, NewFD, NewType);
7524       else if (NewFD->getType()->isFunctionNoProtoType())
7525         setPrototype(SemaRef, NewFD, FD, NewType);
7526     }
7527   }
7528 
7529   // Check if variant function is not marked with declare variant directive.
7530   if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7531     Diag(VariantRef->getExprLoc(),
7532          diag::warn_omp_declare_variant_marked_as_declare_variant)
7533         << VariantRef->getSourceRange();
7534     SourceRange SR =
7535         NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7536     Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7537     return std::nullopt;
7538   }
7539 
7540   enum DoesntSupport {
7541     VirtFuncs = 1,
7542     Constructors = 3,
7543     Destructors = 4,
7544     DeletedFuncs = 5,
7545     DefaultedFuncs = 6,
7546     ConstexprFuncs = 7,
7547     ConstevalFuncs = 8,
7548   };
7549   if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7550     if (CXXFD->isVirtual()) {
7551       Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7552           << VirtFuncs;
7553       return std::nullopt;
7554     }
7555 
7556     if (isa<CXXConstructorDecl>(FD)) {
7557       Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7558           << Constructors;
7559       return std::nullopt;
7560     }
7561 
7562     if (isa<CXXDestructorDecl>(FD)) {
7563       Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7564           << Destructors;
7565       return std::nullopt;
7566     }
7567   }
7568 
7569   if (FD->isDeleted()) {
7570     Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7571         << DeletedFuncs;
7572     return std::nullopt;
7573   }
7574 
7575   if (FD->isDefaulted()) {
7576     Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7577         << DefaultedFuncs;
7578     return std::nullopt;
7579   }
7580 
7581   if (FD->isConstexpr()) {
7582     Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7583         << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7584     return std::nullopt;
7585   }
7586 
7587   // Check general compatibility.
7588   if (SemaRef.areMultiversionVariantFunctionsCompatible(
7589           FD, NewFD, PartialDiagnostic::NullDiagnostic(),
7590           PartialDiagnosticAt(SourceLocation(),
7591                               PartialDiagnostic::NullDiagnostic()),
7592           PartialDiagnosticAt(
7593               VariantRef->getExprLoc(),
7594               PDiag(diag::err_omp_declare_variant_doesnt_support)),
7595           PartialDiagnosticAt(VariantRef->getExprLoc(),
7596                               PDiag(diag::err_omp_declare_variant_diff)
7597                                   << FD->getLocation()),
7598           /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7599           /*CLinkageMayDiffer=*/true))
7600     return std::nullopt;
7601   return std::make_pair(FD, cast<Expr>(DRE));
7602 }
7603 
ActOnOpenMPDeclareVariantDirective(FunctionDecl * FD,Expr * VariantRef,OMPTraitInfo & TI,ArrayRef<Expr * > AdjustArgsNothing,ArrayRef<Expr * > AdjustArgsNeedDevicePtr,ArrayRef<OMPInteropInfo> AppendArgs,SourceLocation AdjustArgsLoc,SourceLocation AppendArgsLoc,SourceRange SR)7604 void SemaOpenMP::ActOnOpenMPDeclareVariantDirective(
7605     FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7606     ArrayRef<Expr *> AdjustArgsNothing,
7607     ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7608     ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7609     SourceLocation AppendArgsLoc, SourceRange SR) {
7610 
7611   // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7612   // An adjust_args clause or append_args clause can only be specified if the
7613   // dispatch selector of the construct selector set appears in the match
7614   // clause.
7615 
7616   SmallVector<Expr *, 8> AllAdjustArgs;
7617   llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7618   llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7619 
7620   if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7621     VariantMatchInfo VMI;
7622     TI.getAsVariantMatchInfo(getASTContext(), VMI);
7623     if (!llvm::is_contained(
7624             VMI.ConstructTraits,
7625             llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7626       if (!AllAdjustArgs.empty())
7627         Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7628             << getOpenMPClauseName(OMPC_adjust_args);
7629       if (!AppendArgs.empty())
7630         Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7631             << getOpenMPClauseName(OMPC_append_args);
7632       return;
7633     }
7634   }
7635 
7636   // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7637   // Each argument can only appear in a single adjust_args clause for each
7638   // declare variant directive.
7639   llvm::SmallPtrSet<const VarDecl *, 4> AdjustVars;
7640 
7641   for (Expr *E : AllAdjustArgs) {
7642     E = E->IgnoreParenImpCasts();
7643     if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7644       if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7645         const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7646         if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7647             FD->getParamDecl(PVD->getFunctionScopeIndex())
7648                     ->getCanonicalDecl() == CanonPVD) {
7649           // It's a parameter of the function, check duplicates.
7650           if (!AdjustVars.insert(CanonPVD).second) {
7651             Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7652                 << PVD;
7653             return;
7654           }
7655           continue;
7656         }
7657       }
7658     }
7659     // Anything that is not a function parameter is an error.
7660     Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7661     return;
7662   }
7663 
7664   auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7665       getASTContext(), VariantRef, &TI,
7666       const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7667       const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7668       AdjustArgsNeedDevicePtr.size(),
7669       const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7670   FD->addAttr(NewAttr);
7671 }
7672 
7673 static CapturedStmt *
setBranchProtectedScope(Sema & SemaRef,OpenMPDirectiveKind DKind,Stmt * AStmt)7674 setBranchProtectedScope(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt) {
7675   auto *CS = dyn_cast<CapturedStmt>(AStmt);
7676   assert(CS && "Captured statement expected");
7677   // 1.2.2 OpenMP Language Terminology
7678   // Structured block - An executable statement with a single entry at the
7679   // top and a single exit at the bottom.
7680   // The point of exit cannot be a branch out of the structured block.
7681   // longjmp() and throw() must not violate the entry/exit criteria.
7682   CS->getCapturedDecl()->setNothrow();
7683 
7684   for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
7685        ThisCaptureLevel > 1; --ThisCaptureLevel) {
7686     CS = cast<CapturedStmt>(CS->getCapturedStmt());
7687     // 1.2.2 OpenMP Language Terminology
7688     // Structured block - An executable statement with a single entry at the
7689     // top and a single exit at the bottom.
7690     // The point of exit cannot be a branch out of the structured block.
7691     // longjmp() and throw() must not violate the entry/exit criteria.
7692     CS->getCapturedDecl()->setNothrow();
7693   }
7694   SemaRef.setFunctionHasBranchProtectedScope();
7695   return CS;
7696 }
7697 
7698 StmtResult
ActOnOpenMPParallelDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)7699 SemaOpenMP::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
7700                                          Stmt *AStmt, SourceLocation StartLoc,
7701                                          SourceLocation EndLoc) {
7702   if (!AStmt)
7703     return StmtError();
7704 
7705   setBranchProtectedScope(SemaRef, OMPD_parallel, AStmt);
7706 
7707   return OMPParallelDirective::Create(
7708       getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
7709       DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
7710 }
7711 
7712 namespace {
7713 /// Iteration space of a single for loop.
7714 struct LoopIterationSpace final {
7715   /// True if the condition operator is the strict compare operator (<, > or
7716   /// !=).
7717   bool IsStrictCompare = false;
7718   /// Condition of the loop.
7719   Expr *PreCond = nullptr;
7720   /// This expression calculates the number of iterations in the loop.
7721   /// It is always possible to calculate it before starting the loop.
7722   Expr *NumIterations = nullptr;
7723   /// The loop counter variable.
7724   Expr *CounterVar = nullptr;
7725   /// Private loop counter variable.
7726   Expr *PrivateCounterVar = nullptr;
7727   /// This is initializer for the initial value of #CounterVar.
7728   Expr *CounterInit = nullptr;
7729   /// This is step for the #CounterVar used to generate its update:
7730   /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7731   Expr *CounterStep = nullptr;
7732   /// Should step be subtracted?
7733   bool Subtract = false;
7734   /// Source range of the loop init.
7735   SourceRange InitSrcRange;
7736   /// Source range of the loop condition.
7737   SourceRange CondSrcRange;
7738   /// Source range of the loop increment.
7739   SourceRange IncSrcRange;
7740   /// Minimum value that can have the loop control variable. Used to support
7741   /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7742   /// since only such variables can be used in non-loop invariant expressions.
7743   Expr *MinValue = nullptr;
7744   /// Maximum value that can have the loop control variable. Used to support
7745   /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7746   /// since only such variables can be used in non-loop invariant expressions.
7747   Expr *MaxValue = nullptr;
7748   /// true, if the lower bound depends on the outer loop control var.
7749   bool IsNonRectangularLB = false;
7750   /// true, if the upper bound depends on the outer loop control var.
7751   bool IsNonRectangularUB = false;
7752   /// Index of the loop this loop depends on and forms non-rectangular loop
7753   /// nest.
7754   unsigned LoopDependentIdx = 0;
7755   /// Final condition for the non-rectangular loop nest support. It is used to
7756   /// check that the number of iterations for this particular counter must be
7757   /// finished.
7758   Expr *FinalCondition = nullptr;
7759 };
7760 
7761 /// Helper class for checking canonical form of the OpenMP loops and
7762 /// extracting iteration space of each loop in the loop nest, that will be used
7763 /// for IR generation.
7764 class OpenMPIterationSpaceChecker {
7765   /// Reference to Sema.
7766   Sema &SemaRef;
7767   /// Does the loop associated directive support non-rectangular loops?
7768   bool SupportsNonRectangular;
7769   /// Data-sharing stack.
7770   DSAStackTy &Stack;
7771   /// A location for diagnostics (when there is no some better location).
7772   SourceLocation DefaultLoc;
7773   /// A location for diagnostics (when increment is not compatible).
7774   SourceLocation ConditionLoc;
7775   /// A source location for referring to loop init later.
7776   SourceRange InitSrcRange;
7777   /// A source location for referring to condition later.
7778   SourceRange ConditionSrcRange;
7779   /// A source location for referring to increment later.
7780   SourceRange IncrementSrcRange;
7781   /// Loop variable.
7782   ValueDecl *LCDecl = nullptr;
7783   /// Reference to loop variable.
7784   Expr *LCRef = nullptr;
7785   /// Lower bound (initializer for the var).
7786   Expr *LB = nullptr;
7787   /// Upper bound.
7788   Expr *UB = nullptr;
7789   /// Loop step (increment).
7790   Expr *Step = nullptr;
7791   /// This flag is true when condition is one of:
7792   ///   Var <  UB
7793   ///   Var <= UB
7794   ///   UB  >  Var
7795   ///   UB  >= Var
7796   /// This will have no value when the condition is !=
7797   std::optional<bool> TestIsLessOp;
7798   /// This flag is true when condition is strict ( < or > ).
7799   bool TestIsStrictOp = false;
7800   /// This flag is true when step is subtracted on each iteration.
7801   bool SubtractStep = false;
7802   /// The outer loop counter this loop depends on (if any).
7803   const ValueDecl *DepDecl = nullptr;
7804   /// Contains number of loop (starts from 1) on which loop counter init
7805   /// expression of this loop depends on.
7806   std::optional<unsigned> InitDependOnLC;
7807   /// Contains number of loop (starts from 1) on which loop counter condition
7808   /// expression of this loop depends on.
7809   std::optional<unsigned> CondDependOnLC;
7810   /// Checks if the provide statement depends on the loop counter.
7811   std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
7812                                                   bool IsInitializer);
7813   /// Original condition required for checking of the exit condition for
7814   /// non-rectangular loop.
7815   Expr *Condition = nullptr;
7816 
7817 public:
OpenMPIterationSpaceChecker(Sema & SemaRef,bool SupportsNonRectangular,DSAStackTy & Stack,SourceLocation DefaultLoc)7818   OpenMPIterationSpaceChecker(Sema &SemaRef, bool SupportsNonRectangular,
7819                               DSAStackTy &Stack, SourceLocation DefaultLoc)
7820       : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7821         Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {}
7822   /// Check init-expr for canonical loop form and save loop counter
7823   /// variable - #Var and its initialization value - #LB.
7824   bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
7825   /// Check test-expr for canonical form, save upper-bound (#UB), flags
7826   /// for less/greater and for strict/non-strict comparison.
7827   bool checkAndSetCond(Expr *S);
7828   /// Check incr-expr for canonical loop form and return true if it
7829   /// does not conform, otherwise save loop step (#Step).
7830   bool checkAndSetInc(Expr *S);
7831   /// Return the loop counter variable.
getLoopDecl() const7832   ValueDecl *getLoopDecl() const { return LCDecl; }
7833   /// Return the reference expression to loop counter variable.
getLoopDeclRefExpr() const7834   Expr *getLoopDeclRefExpr() const { return LCRef; }
7835   /// Source range of the loop init.
getInitSrcRange() const7836   SourceRange getInitSrcRange() const { return InitSrcRange; }
7837   /// Source range of the loop condition.
getConditionSrcRange() const7838   SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
7839   /// Source range of the loop increment.
getIncrementSrcRange() const7840   SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
7841   /// True if the step should be subtracted.
shouldSubtractStep() const7842   bool shouldSubtractStep() const { return SubtractStep; }
7843   /// True, if the compare operator is strict (<, > or !=).
isStrictTestOp() const7844   bool isStrictTestOp() const { return TestIsStrictOp; }
7845   /// Build the expression to calculate the number of iterations.
7846   Expr *buildNumIterations(
7847       Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
7848       llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7849   /// Build the precondition expression for the loops.
7850   Expr *
7851   buildPreCond(Scope *S, Expr *Cond,
7852                llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7853   /// Build reference expression to the counter be used for codegen.
7854   DeclRefExpr *
7855   buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7856                   DSAStackTy &DSA) const;
7857   /// Build reference expression to the private counter be used for
7858   /// codegen.
7859   Expr *buildPrivateCounterVar() const;
7860   /// Build initialization of the counter be used for codegen.
7861   Expr *buildCounterInit() const;
7862   /// Build step of the counter be used for codegen.
7863   Expr *buildCounterStep() const;
7864   /// Build loop data with counter value for depend clauses in ordered
7865   /// directives.
7866   Expr *
7867   buildOrderedLoopData(Scope *S, Expr *Counter,
7868                        llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7869                        SourceLocation Loc, Expr *Inc = nullptr,
7870                        OverloadedOperatorKind OOK = OO_Amp);
7871   /// Builds the minimum value for the loop counter.
7872   std::pair<Expr *, Expr *> buildMinMaxValues(
7873       Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7874   /// Builds final condition for the non-rectangular loops.
7875   Expr *buildFinalCondition(Scope *S) const;
7876   /// Return true if any expression is dependent.
7877   bool dependent() const;
7878   /// Returns true if the initializer forms non-rectangular loop.
doesInitDependOnLC() const7879   bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
7880   /// Returns true if the condition forms non-rectangular loop.
doesCondDependOnLC() const7881   bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
7882   /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
getLoopDependentIdx() const7883   unsigned getLoopDependentIdx() const {
7884     return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
7885   }
7886 
7887 private:
7888   /// Check the right-hand side of an assignment in the increment
7889   /// expression.
7890   bool checkAndSetIncRHS(Expr *RHS);
7891   /// Helper to set loop counter variable and its initializer.
7892   bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
7893                       bool EmitDiags);
7894   /// Helper to set upper bound.
7895   bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
7896              SourceRange SR, SourceLocation SL);
7897   /// Helper to set loop increment.
7898   bool setStep(Expr *NewStep, bool Subtract);
7899 };
7900 
dependent() const7901 bool OpenMPIterationSpaceChecker::dependent() const {
7902   if (!LCDecl) {
7903     assert(!LB && !UB && !Step);
7904     return false;
7905   }
7906   return LCDecl->getType()->isDependentType() ||
7907          (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
7908          (Step && Step->isValueDependent());
7909 }
7910 
setLCDeclAndLB(ValueDecl * NewLCDecl,Expr * NewLCRefExpr,Expr * NewLB,bool EmitDiags)7911 bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
7912                                                  Expr *NewLCRefExpr,
7913                                                  Expr *NewLB, bool EmitDiags) {
7914   // State consistency checking to ensure correct usage.
7915   assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
7916          UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7917   if (!NewLCDecl || !NewLB || NewLB->containsErrors())
7918     return true;
7919   LCDecl = getCanonicalDecl(NewLCDecl);
7920   LCRef = NewLCRefExpr;
7921   if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
7922     if (const CXXConstructorDecl *Ctor = CE->getConstructor())
7923       if ((Ctor->isCopyOrMoveConstructor() ||
7924            Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
7925           CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
7926         NewLB = CE->getArg(0)->IgnoreParenImpCasts();
7927   LB = NewLB;
7928   if (EmitDiags)
7929     InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
7930   return false;
7931 }
7932 
setUB(Expr * NewUB,std::optional<bool> LessOp,bool StrictOp,SourceRange SR,SourceLocation SL)7933 bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
7934                                         bool StrictOp, SourceRange SR,
7935                                         SourceLocation SL) {
7936   // State consistency checking to ensure correct usage.
7937   assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
7938          Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7939   if (!NewUB || NewUB->containsErrors())
7940     return true;
7941   UB = NewUB;
7942   if (LessOp)
7943     TestIsLessOp = LessOp;
7944   TestIsStrictOp = StrictOp;
7945   ConditionSrcRange = SR;
7946   ConditionLoc = SL;
7947   CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
7948   return false;
7949 }
7950 
setStep(Expr * NewStep,bool Subtract)7951 bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
7952   // State consistency checking to ensure correct usage.
7953   assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
7954   if (!NewStep || NewStep->containsErrors())
7955     return true;
7956   if (!NewStep->isValueDependent()) {
7957     // Check that the step is integer expression.
7958     SourceLocation StepLoc = NewStep->getBeginLoc();
7959     ExprResult Val = SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(
7960         StepLoc, getExprAsWritten(NewStep));
7961     if (Val.isInvalid())
7962       return true;
7963     NewStep = Val.get();
7964 
7965     // OpenMP [2.6, Canonical Loop Form, Restrictions]
7966     //  If test-expr is of form var relational-op b and relational-op is < or
7967     //  <= then incr-expr must cause var to increase on each iteration of the
7968     //  loop. If test-expr is of form var relational-op b and relational-op is
7969     //  > or >= then incr-expr must cause var to decrease on each iteration of
7970     //  the loop.
7971     //  If test-expr is of form b relational-op var and relational-op is < or
7972     //  <= then incr-expr must cause var to decrease on each iteration of the
7973     //  loop. If test-expr is of form b relational-op var and relational-op is
7974     //  > or >= then incr-expr must cause var to increase on each iteration of
7975     //  the loop.
7976     std::optional<llvm::APSInt> Result =
7977         NewStep->getIntegerConstantExpr(SemaRef.Context);
7978     bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
7979     bool IsConstNeg =
7980         Result && Result->isSigned() && (Subtract != Result->isNegative());
7981     bool IsConstPos =
7982         Result && Result->isSigned() && (Subtract == Result->isNegative());
7983     bool IsConstZero = Result && !Result->getBoolValue();
7984 
7985     // != with increment is treated as <; != with decrement is treated as >
7986     if (!TestIsLessOp)
7987       TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
7988     if (UB && (IsConstZero ||
7989                (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
7990                               : (IsConstPos || (IsUnsigned && !Subtract))))) {
7991       SemaRef.Diag(NewStep->getExprLoc(),
7992                    diag::err_omp_loop_incr_not_compatible)
7993           << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
7994       SemaRef.Diag(ConditionLoc,
7995                    diag::note_omp_loop_cond_requires_compatible_incr)
7996           << *TestIsLessOp << ConditionSrcRange;
7997       return true;
7998     }
7999     if (*TestIsLessOp == Subtract) {
8000       NewStep =
8001           SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
8002               .get();
8003       Subtract = !Subtract;
8004     }
8005   }
8006 
8007   Step = NewStep;
8008   SubtractStep = Subtract;
8009   return false;
8010 }
8011 
8012 namespace {
8013 /// Checker for the non-rectangular loops. Checks if the initializer or
8014 /// condition expression references loop counter variable.
8015 class LoopCounterRefChecker final
8016     : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8017   Sema &SemaRef;
8018   DSAStackTy &Stack;
8019   const ValueDecl *CurLCDecl = nullptr;
8020   const ValueDecl *DepDecl = nullptr;
8021   const ValueDecl *PrevDepDecl = nullptr;
8022   bool IsInitializer = true;
8023   bool SupportsNonRectangular;
8024   unsigned BaseLoopId = 0;
checkDecl(const Expr * E,const ValueDecl * VD)8025   bool checkDecl(const Expr *E, const ValueDecl *VD) {
8026     if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
8027       SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8028           << (IsInitializer ? 0 : 1);
8029       return false;
8030     }
8031     const auto &&Data = Stack.isLoopControlVariable(VD);
8032     // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8033     // The type of the loop iterator on which we depend may not have a random
8034     // access iterator type.
8035     if (Data.first && VD->getType()->isRecordType()) {
8036       SmallString<128> Name;
8037       llvm::raw_svector_ostream OS(Name);
8038       VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8039                                /*Qualified=*/true);
8040       SemaRef.Diag(E->getExprLoc(),
8041                    diag::err_omp_wrong_dependency_iterator_type)
8042           << OS.str();
8043       SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8044       return false;
8045     }
8046     if (Data.first && !SupportsNonRectangular) {
8047       SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8048       return false;
8049     }
8050     if (Data.first &&
8051         (DepDecl || (PrevDepDecl &&
8052                      getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8053       if (!DepDecl && PrevDepDecl)
8054         DepDecl = PrevDepDecl;
8055       SmallString<128> Name;
8056       llvm::raw_svector_ostream OS(Name);
8057       DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8058                                     /*Qualified=*/true);
8059       SemaRef.Diag(E->getExprLoc(),
8060                    diag::err_omp_invariant_or_linear_dependency)
8061           << OS.str();
8062       return false;
8063     }
8064     if (Data.first) {
8065       DepDecl = VD;
8066       BaseLoopId = Data.first;
8067     }
8068     return Data.first;
8069   }
8070 
8071 public:
VisitDeclRefExpr(const DeclRefExpr * E)8072   bool VisitDeclRefExpr(const DeclRefExpr *E) {
8073     const ValueDecl *VD = E->getDecl();
8074     if (isa<VarDecl>(VD))
8075       return checkDecl(E, VD);
8076     return false;
8077   }
VisitMemberExpr(const MemberExpr * E)8078   bool VisitMemberExpr(const MemberExpr *E) {
8079     if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8080       const ValueDecl *VD = E->getMemberDecl();
8081       if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8082         return checkDecl(E, VD);
8083     }
8084     return false;
8085   }
VisitStmt(const Stmt * S)8086   bool VisitStmt(const Stmt *S) {
8087     bool Res = false;
8088     for (const Stmt *Child : S->children())
8089       Res = (Child && Visit(Child)) || Res;
8090     return Res;
8091   }
LoopCounterRefChecker(Sema & SemaRef,DSAStackTy & Stack,const ValueDecl * CurLCDecl,bool IsInitializer,const ValueDecl * PrevDepDecl=nullptr,bool SupportsNonRectangular=true)8092   explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8093                                  const ValueDecl *CurLCDecl, bool IsInitializer,
8094                                  const ValueDecl *PrevDepDecl = nullptr,
8095                                  bool SupportsNonRectangular = true)
8096       : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8097         PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8098         SupportsNonRectangular(SupportsNonRectangular) {}
getBaseLoopId() const8099   unsigned getBaseLoopId() const {
8100     assert(CurLCDecl && "Expected loop dependency.");
8101     return BaseLoopId;
8102   }
getDepDecl() const8103   const ValueDecl *getDepDecl() const {
8104     assert(CurLCDecl && "Expected loop dependency.");
8105     return DepDecl;
8106   }
8107 };
8108 } // namespace
8109 
8110 std::optional<unsigned>
doesDependOnLoopCounter(const Stmt * S,bool IsInitializer)8111 OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8112                                                      bool IsInitializer) {
8113   // Check for the non-rectangular loops.
8114   LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8115                                         DepDecl, SupportsNonRectangular);
8116   if (LoopStmtChecker.Visit(S)) {
8117     DepDecl = LoopStmtChecker.getDepDecl();
8118     return LoopStmtChecker.getBaseLoopId();
8119   }
8120   return std::nullopt;
8121 }
8122 
checkAndSetInit(Stmt * S,bool EmitDiags)8123 bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8124   // Check init-expr for canonical loop form and save loop counter
8125   // variable - #Var and its initialization value - #LB.
8126   // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8127   //   var = lb
8128   //   integer-type var = lb
8129   //   random-access-iterator-type var = lb
8130   //   pointer-type var = lb
8131   //
8132   if (!S) {
8133     if (EmitDiags) {
8134       SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8135     }
8136     return true;
8137   }
8138   if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8139     if (!ExprTemp->cleanupsHaveSideEffects())
8140       S = ExprTemp->getSubExpr();
8141 
8142   InitSrcRange = S->getSourceRange();
8143   if (Expr *E = dyn_cast<Expr>(S))
8144     S = E->IgnoreParens();
8145   if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8146     if (BO->getOpcode() == BO_Assign) {
8147       Expr *LHS = BO->getLHS()->IgnoreParens();
8148       if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8149         if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8150           if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8151             return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8152                                   EmitDiags);
8153         return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8154       }
8155       if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8156         if (ME->isArrow() &&
8157             isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8158           return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8159                                 EmitDiags);
8160       }
8161     }
8162   } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8163     if (DS->isSingleDecl()) {
8164       if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8165         if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8166           // Accept non-canonical init form here but emit ext. warning.
8167           if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8168             SemaRef.Diag(S->getBeginLoc(),
8169                          diag::ext_omp_loop_not_canonical_init)
8170                 << S->getSourceRange();
8171           return setLCDeclAndLB(
8172               Var,
8173               buildDeclRefExpr(SemaRef, Var,
8174                                Var->getType().getNonReferenceType(),
8175                                DS->getBeginLoc()),
8176               Var->getInit(), EmitDiags);
8177         }
8178       }
8179     }
8180   } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8181     if (CE->getOperator() == OO_Equal) {
8182       Expr *LHS = CE->getArg(0);
8183       if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8184         if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8185           if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8186             return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8187                                   EmitDiags);
8188         return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8189       }
8190       if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8191         if (ME->isArrow() &&
8192             isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8193           return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8194                                 EmitDiags);
8195       }
8196     }
8197   }
8198 
8199   if (dependent() || SemaRef.CurContext->isDependentContext())
8200     return false;
8201   if (EmitDiags) {
8202     SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8203         << S->getSourceRange();
8204   }
8205   return true;
8206 }
8207 
8208 /// Ignore parenthesizes, implicit casts, copy constructor and return the
8209 /// variable (which may be the loop variable) if possible.
getInitLCDecl(const Expr * E)8210 static const ValueDecl *getInitLCDecl(const Expr *E) {
8211   if (!E)
8212     return nullptr;
8213   E = getExprAsWritten(E);
8214   if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8215     if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8216       if ((Ctor->isCopyOrMoveConstructor() ||
8217            Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8218           CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8219         E = CE->getArg(0)->IgnoreParenImpCasts();
8220   if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8221     if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8222       return getCanonicalDecl(VD);
8223   }
8224   if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8225     if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8226       return getCanonicalDecl(ME->getMemberDecl());
8227   return nullptr;
8228 }
8229 
checkAndSetCond(Expr * S)8230 bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8231   // Check test-expr for canonical form, save upper-bound UB, flags for
8232   // less/greater and for strict/non-strict comparison.
8233   // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8234   //   var relational-op b
8235   //   b relational-op var
8236   //
8237   bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8238   if (!S) {
8239     SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8240         << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8241     return true;
8242   }
8243   Condition = S;
8244   S = getExprAsWritten(S);
8245   SourceLocation CondLoc = S->getBeginLoc();
8246   auto &&CheckAndSetCond =
8247       [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8248                                   const Expr *RHS, SourceRange SR,
8249                                   SourceLocation OpLoc) -> std::optional<bool> {
8250     if (BinaryOperator::isRelationalOp(Opcode)) {
8251       if (getInitLCDecl(LHS) == LCDecl)
8252         return setUB(const_cast<Expr *>(RHS),
8253                      (Opcode == BO_LT || Opcode == BO_LE),
8254                      (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8255       if (getInitLCDecl(RHS) == LCDecl)
8256         return setUB(const_cast<Expr *>(LHS),
8257                      (Opcode == BO_GT || Opcode == BO_GE),
8258                      (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8259     } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8260       return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8261                    /*LessOp=*/std::nullopt,
8262                    /*StrictOp=*/true, SR, OpLoc);
8263     }
8264     return std::nullopt;
8265   };
8266   std::optional<bool> Res;
8267   if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8268     CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8269     Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8270                           RBO->getOperatorLoc());
8271   } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8272     Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8273                           BO->getSourceRange(), BO->getOperatorLoc());
8274   } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8275     if (CE->getNumArgs() == 2) {
8276       Res = CheckAndSetCond(
8277           BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8278           CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8279     }
8280   }
8281   if (Res)
8282     return *Res;
8283   if (dependent() || SemaRef.CurContext->isDependentContext())
8284     return false;
8285   SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8286       << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8287   return true;
8288 }
8289 
checkAndSetIncRHS(Expr * RHS)8290 bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8291   // RHS of canonical loop form increment can be:
8292   //   var + incr
8293   //   incr + var
8294   //   var - incr
8295   //
8296   RHS = RHS->IgnoreParenImpCasts();
8297   if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8298     if (BO->isAdditiveOp()) {
8299       bool IsAdd = BO->getOpcode() == BO_Add;
8300       if (getInitLCDecl(BO->getLHS()) == LCDecl)
8301         return setStep(BO->getRHS(), !IsAdd);
8302       if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8303         return setStep(BO->getLHS(), /*Subtract=*/false);
8304     }
8305   } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8306     bool IsAdd = CE->getOperator() == OO_Plus;
8307     if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8308       if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8309         return setStep(CE->getArg(1), !IsAdd);
8310       if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8311         return setStep(CE->getArg(0), /*Subtract=*/false);
8312     }
8313   }
8314   if (dependent() || SemaRef.CurContext->isDependentContext())
8315     return false;
8316   SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8317       << RHS->getSourceRange() << LCDecl;
8318   return true;
8319 }
8320 
checkAndSetInc(Expr * S)8321 bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8322   // Check incr-expr for canonical loop form and return true if it
8323   // does not conform.
8324   // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8325   //   ++var
8326   //   var++
8327   //   --var
8328   //   var--
8329   //   var += incr
8330   //   var -= incr
8331   //   var = var + incr
8332   //   var = incr + var
8333   //   var = var - incr
8334   //
8335   if (!S) {
8336     SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8337     return true;
8338   }
8339   if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8340     if (!ExprTemp->cleanupsHaveSideEffects())
8341       S = ExprTemp->getSubExpr();
8342 
8343   IncrementSrcRange = S->getSourceRange();
8344   S = S->IgnoreParens();
8345   if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8346     if (UO->isIncrementDecrementOp() &&
8347         getInitLCDecl(UO->getSubExpr()) == LCDecl)
8348       return setStep(SemaRef
8349                          .ActOnIntegerConstant(UO->getBeginLoc(),
8350                                                (UO->isDecrementOp() ? -1 : 1))
8351                          .get(),
8352                      /*Subtract=*/false);
8353   } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8354     switch (BO->getOpcode()) {
8355     case BO_AddAssign:
8356     case BO_SubAssign:
8357       if (getInitLCDecl(BO->getLHS()) == LCDecl)
8358         return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8359       break;
8360     case BO_Assign:
8361       if (getInitLCDecl(BO->getLHS()) == LCDecl)
8362         return checkAndSetIncRHS(BO->getRHS());
8363       break;
8364     default:
8365       break;
8366     }
8367   } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8368     switch (CE->getOperator()) {
8369     case OO_PlusPlus:
8370     case OO_MinusMinus:
8371       if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8372         return setStep(SemaRef
8373                            .ActOnIntegerConstant(
8374                                CE->getBeginLoc(),
8375                                ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8376                            .get(),
8377                        /*Subtract=*/false);
8378       break;
8379     case OO_PlusEqual:
8380     case OO_MinusEqual:
8381       if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8382         return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8383       break;
8384     case OO_Equal:
8385       if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8386         return checkAndSetIncRHS(CE->getArg(1));
8387       break;
8388     default:
8389       break;
8390     }
8391   }
8392   if (dependent() || SemaRef.CurContext->isDependentContext())
8393     return false;
8394   SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8395       << S->getSourceRange() << LCDecl;
8396   return true;
8397 }
8398 
8399 static ExprResult
tryBuildCapture(Sema & SemaRef,Expr * Capture,llvm::MapVector<const Expr *,DeclRefExpr * > & Captures,StringRef Name=".capture_expr.")8400 tryBuildCapture(Sema &SemaRef, Expr *Capture,
8401                 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8402                 StringRef Name = ".capture_expr.") {
8403   if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8404     return Capture;
8405   if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8406     return SemaRef.PerformImplicitConversion(
8407         Capture->IgnoreImpCasts(), Capture->getType(), Sema::AA_Converting,
8408         /*AllowExplicit=*/true);
8409   auto I = Captures.find(Capture);
8410   if (I != Captures.end())
8411     return buildCapture(SemaRef, Capture, I->second, Name);
8412   DeclRefExpr *Ref = nullptr;
8413   ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8414   Captures[Capture] = Ref;
8415   return Res;
8416 }
8417 
8418 /// Calculate number of iterations, transforming to unsigned, if number of
8419 /// iterations may be larger than the original type.
8420 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)8421 calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8422                   Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8423                   bool TestIsStrictOp, bool RoundToStep,
8424                   llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8425   ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8426   if (!NewStep.isUsable())
8427     return nullptr;
8428   llvm::APSInt LRes, SRes;
8429   bool IsLowerConst = false, IsStepConst = false;
8430   if (std::optional<llvm::APSInt> Res =
8431           Lower->getIntegerConstantExpr(SemaRef.Context)) {
8432     LRes = *Res;
8433     IsLowerConst = true;
8434   }
8435   if (std::optional<llvm::APSInt> Res =
8436           Step->getIntegerConstantExpr(SemaRef.Context)) {
8437     SRes = *Res;
8438     IsStepConst = true;
8439   }
8440   bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8441                          ((!TestIsStrictOp && LRes.isNonNegative()) ||
8442                           (TestIsStrictOp && LRes.isStrictlyPositive()));
8443   bool NeedToReorganize = false;
8444   // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8445   if (!NoNeedToConvert && IsLowerConst &&
8446       (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8447     NoNeedToConvert = true;
8448     if (RoundToStep) {
8449       unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8450                         ? LRes.getBitWidth()
8451                         : SRes.getBitWidth();
8452       LRes = LRes.extend(BW + 1);
8453       LRes.setIsSigned(true);
8454       SRes = SRes.extend(BW + 1);
8455       SRes.setIsSigned(true);
8456       LRes -= SRes;
8457       NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8458       LRes = LRes.trunc(BW);
8459     }
8460     if (TestIsStrictOp) {
8461       unsigned BW = LRes.getBitWidth();
8462       LRes = LRes.extend(BW + 1);
8463       LRes.setIsSigned(true);
8464       ++LRes;
8465       NoNeedToConvert =
8466           NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8467       // truncate to the original bitwidth.
8468       LRes = LRes.trunc(BW);
8469     }
8470     NeedToReorganize = NoNeedToConvert;
8471   }
8472   llvm::APSInt URes;
8473   bool IsUpperConst = false;
8474   if (std::optional<llvm::APSInt> Res =
8475           Upper->getIntegerConstantExpr(SemaRef.Context)) {
8476     URes = *Res;
8477     IsUpperConst = true;
8478   }
8479   if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8480       (!RoundToStep || IsStepConst)) {
8481     unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8482                                                           : URes.getBitWidth();
8483     LRes = LRes.extend(BW + 1);
8484     LRes.setIsSigned(true);
8485     URes = URes.extend(BW + 1);
8486     URes.setIsSigned(true);
8487     URes -= LRes;
8488     NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8489     NeedToReorganize = NoNeedToConvert;
8490   }
8491   // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8492   // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8493   // unsigned.
8494   if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8495       !LCTy->isDependentType() && LCTy->isIntegerType()) {
8496     QualType LowerTy = Lower->getType();
8497     QualType UpperTy = Upper->getType();
8498     uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8499     uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8500     if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8501         (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8502       QualType CastType = SemaRef.Context.getIntTypeForBitwidth(
8503           LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8504       Upper =
8505           SemaRef
8506               .PerformImplicitConversion(
8507                   SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8508                   CastType, Sema::AA_Converting)
8509               .get();
8510       Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8511       NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8512     }
8513   }
8514   if (!Lower || !Upper || NewStep.isInvalid())
8515     return nullptr;
8516 
8517   ExprResult Diff;
8518   // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8519   // 1]).
8520   if (NeedToReorganize) {
8521     Diff = Lower;
8522 
8523     if (RoundToStep) {
8524       // Lower - Step
8525       Diff =
8526           SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8527       if (!Diff.isUsable())
8528         return nullptr;
8529     }
8530 
8531     // Lower - Step [+ 1]
8532     if (TestIsStrictOp)
8533       Diff = SemaRef.BuildBinOp(
8534           S, DefaultLoc, BO_Add, Diff.get(),
8535           SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8536     if (!Diff.isUsable())
8537       return nullptr;
8538 
8539     Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8540     if (!Diff.isUsable())
8541       return nullptr;
8542 
8543     // Upper - (Lower - Step [+ 1]).
8544     Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8545     if (!Diff.isUsable())
8546       return nullptr;
8547   } else {
8548     Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8549 
8550     if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8551       // BuildBinOp already emitted error, this one is to point user to upper
8552       // and lower bound, and to tell what is passed to 'operator-'.
8553       SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8554           << Upper->getSourceRange() << Lower->getSourceRange();
8555       return nullptr;
8556     }
8557 
8558     if (!Diff.isUsable())
8559       return nullptr;
8560 
8561     // Upper - Lower [- 1]
8562     if (TestIsStrictOp)
8563       Diff = SemaRef.BuildBinOp(
8564           S, DefaultLoc, BO_Sub, Diff.get(),
8565           SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8566     if (!Diff.isUsable())
8567       return nullptr;
8568 
8569     if (RoundToStep) {
8570       // Upper - Lower [- 1] + Step
8571       Diff =
8572           SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8573       if (!Diff.isUsable())
8574         return nullptr;
8575     }
8576   }
8577 
8578   // Parentheses (for dumping/debugging purposes only).
8579   Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8580   if (!Diff.isUsable())
8581     return nullptr;
8582 
8583   // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8584   Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8585   if (!Diff.isUsable())
8586     return nullptr;
8587 
8588   return Diff.get();
8589 }
8590 
8591 /// Build the expression to calculate the number of iterations.
buildNumIterations(Scope * S,ArrayRef<LoopIterationSpace> ResultIterSpaces,bool LimitedType,llvm::MapVector<const Expr *,DeclRefExpr * > & Captures) const8592 Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8593     Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8594     llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8595   QualType VarType = LCDecl->getType().getNonReferenceType();
8596   if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8597       !SemaRef.getLangOpts().CPlusPlus)
8598     return nullptr;
8599   Expr *LBVal = LB;
8600   Expr *UBVal = UB;
8601   // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8602   // max(LB(MinVal), LB(MaxVal)))
8603   if (InitDependOnLC) {
8604     const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8605     if (!IS.MinValue || !IS.MaxValue)
8606       return nullptr;
8607     // OuterVar = Min
8608     ExprResult MinValue =
8609         SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8610     if (!MinValue.isUsable())
8611       return nullptr;
8612 
8613     ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8614                                              IS.CounterVar, MinValue.get());
8615     if (!LBMinVal.isUsable())
8616       return nullptr;
8617     // OuterVar = Min, LBVal
8618     LBMinVal =
8619         SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8620     if (!LBMinVal.isUsable())
8621       return nullptr;
8622     // (OuterVar = Min, LBVal)
8623     LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8624     if (!LBMinVal.isUsable())
8625       return nullptr;
8626 
8627     // OuterVar = Max
8628     ExprResult MaxValue =
8629         SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8630     if (!MaxValue.isUsable())
8631       return nullptr;
8632 
8633     ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8634                                              IS.CounterVar, MaxValue.get());
8635     if (!LBMaxVal.isUsable())
8636       return nullptr;
8637     // OuterVar = Max, LBVal
8638     LBMaxVal =
8639         SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8640     if (!LBMaxVal.isUsable())
8641       return nullptr;
8642     // (OuterVar = Max, LBVal)
8643     LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8644     if (!LBMaxVal.isUsable())
8645       return nullptr;
8646 
8647     Expr *LBMin =
8648         tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
8649     Expr *LBMax =
8650         tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
8651     if (!LBMin || !LBMax)
8652       return nullptr;
8653     // LB(MinVal) < LB(MaxVal)
8654     ExprResult MinLessMaxRes =
8655         SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8656     if (!MinLessMaxRes.isUsable())
8657       return nullptr;
8658     Expr *MinLessMax =
8659         tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
8660             .get();
8661     if (!MinLessMax)
8662       return nullptr;
8663     if (*TestIsLessOp) {
8664       // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8665       // LB(MaxVal))
8666       ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8667                                                     MinLessMax, LBMin, LBMax);
8668       if (!MinLB.isUsable())
8669         return nullptr;
8670       LBVal = MinLB.get();
8671     } else {
8672       // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8673       // LB(MaxVal))
8674       ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8675                                                     MinLessMax, LBMax, LBMin);
8676       if (!MaxLB.isUsable())
8677         return nullptr;
8678       LBVal = MaxLB.get();
8679     }
8680     // OuterVar = LB
8681     LBMinVal =
8682         SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8683     if (!LBMinVal.isUsable())
8684       return nullptr;
8685     LBVal = LBMinVal.get();
8686   }
8687   // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8688   // min(UB(MinVal), UB(MaxVal))
8689   if (CondDependOnLC) {
8690     const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8691     if (!IS.MinValue || !IS.MaxValue)
8692       return nullptr;
8693     // OuterVar = Min
8694     ExprResult MinValue =
8695         SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8696     if (!MinValue.isUsable())
8697       return nullptr;
8698 
8699     ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8700                                              IS.CounterVar, MinValue.get());
8701     if (!UBMinVal.isUsable())
8702       return nullptr;
8703     // OuterVar = Min, UBVal
8704     UBMinVal =
8705         SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
8706     if (!UBMinVal.isUsable())
8707       return nullptr;
8708     // (OuterVar = Min, UBVal)
8709     UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
8710     if (!UBMinVal.isUsable())
8711       return nullptr;
8712 
8713     // OuterVar = Max
8714     ExprResult MaxValue =
8715         SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8716     if (!MaxValue.isUsable())
8717       return nullptr;
8718 
8719     ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8720                                              IS.CounterVar, MaxValue.get());
8721     if (!UBMaxVal.isUsable())
8722       return nullptr;
8723     // OuterVar = Max, UBVal
8724     UBMaxVal =
8725         SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
8726     if (!UBMaxVal.isUsable())
8727       return nullptr;
8728     // (OuterVar = Max, UBVal)
8729     UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
8730     if (!UBMaxVal.isUsable())
8731       return nullptr;
8732 
8733     Expr *UBMin =
8734         tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
8735     Expr *UBMax =
8736         tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
8737     if (!UBMin || !UBMax)
8738       return nullptr;
8739     // UB(MinVal) > UB(MaxVal)
8740     ExprResult MinGreaterMaxRes =
8741         SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8742     if (!MinGreaterMaxRes.isUsable())
8743       return nullptr;
8744     Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
8745                                           Captures, ".min_greater_max")
8746                               .get();
8747     if (!MinGreaterMax)
8748       return nullptr;
8749     if (*TestIsLessOp) {
8750       // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8751       // UB(MaxVal))
8752       ExprResult MaxUB = SemaRef.ActOnConditionalOp(
8753           DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8754       if (!MaxUB.isUsable())
8755         return nullptr;
8756       UBVal = MaxUB.get();
8757     } else {
8758       // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
8759       // UB(MaxVal))
8760       ExprResult MinUB = SemaRef.ActOnConditionalOp(
8761           DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
8762       if (!MinUB.isUsable())
8763         return nullptr;
8764       UBVal = MinUB.get();
8765     }
8766   }
8767   Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
8768   Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
8769   Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
8770   Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
8771   if (!Upper || !Lower)
8772     return nullptr;
8773 
8774   ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8775                                       Step, VarType, TestIsStrictOp,
8776                                       /*RoundToStep=*/true, Captures);
8777   if (!Diff.isUsable())
8778     return nullptr;
8779 
8780   // OpenMP runtime requires 32-bit or 64-bit loop variables.
8781   QualType Type = Diff.get()->getType();
8782   ASTContext &C = SemaRef.Context;
8783   bool UseVarType = VarType->hasIntegerRepresentation() &&
8784                     C.getTypeSize(Type) > C.getTypeSize(VarType);
8785   if (!Type->isIntegerType() || UseVarType) {
8786     unsigned NewSize =
8787         UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
8788     bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
8789                                : Type->hasSignedIntegerRepresentation();
8790     Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
8791     if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
8792       Diff = SemaRef.PerformImplicitConversion(
8793           Diff.get(), Type, Sema::AA_Converting, /*AllowExplicit=*/true);
8794       if (!Diff.isUsable())
8795         return nullptr;
8796     }
8797   }
8798   if (LimitedType) {
8799     unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
8800     if (NewSize != C.getTypeSize(Type)) {
8801       if (NewSize < C.getTypeSize(Type)) {
8802         assert(NewSize == 64 && "incorrect loop var size");
8803         SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8804             << InitSrcRange << ConditionSrcRange;
8805       }
8806       QualType NewType = C.getIntTypeForBitwidth(
8807           NewSize, Type->hasSignedIntegerRepresentation() ||
8808                        C.getTypeSize(Type) < NewSize);
8809       if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
8810         Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
8811                                                  Sema::AA_Converting, true);
8812         if (!Diff.isUsable())
8813           return nullptr;
8814       }
8815     }
8816   }
8817 
8818   return Diff.get();
8819 }
8820 
buildMinMaxValues(Scope * S,llvm::MapVector<const Expr *,DeclRefExpr * > & Captures) const8821 std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
8822     Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8823   // Do not build for iterators, they cannot be used in non-rectangular loop
8824   // nests.
8825   if (LCDecl->getType()->isRecordType())
8826     return std::make_pair(nullptr, nullptr);
8827   // If we subtract, the min is in the condition, otherwise the min is in the
8828   // init value.
8829   Expr *MinExpr = nullptr;
8830   Expr *MaxExpr = nullptr;
8831   Expr *LBExpr = *TestIsLessOp ? LB : UB;
8832   Expr *UBExpr = *TestIsLessOp ? UB : LB;
8833   bool LBNonRect =
8834       *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
8835   bool UBNonRect =
8836       *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
8837   Expr *Lower =
8838       LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
8839   Expr *Upper =
8840       UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
8841   if (!Upper || !Lower)
8842     return std::make_pair(nullptr, nullptr);
8843 
8844   if (*TestIsLessOp)
8845     MinExpr = Lower;
8846   else
8847     MaxExpr = Upper;
8848 
8849   // Build minimum/maximum value based on number of iterations.
8850   QualType VarType = LCDecl->getType().getNonReferenceType();
8851 
8852   ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8853                                       Step, VarType, TestIsStrictOp,
8854                                       /*RoundToStep=*/false, Captures);
8855   if (!Diff.isUsable())
8856     return std::make_pair(nullptr, nullptr);
8857 
8858   // ((Upper - Lower [- 1]) / Step) * Step
8859   // Parentheses (for dumping/debugging purposes only).
8860   Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8861   if (!Diff.isUsable())
8862     return std::make_pair(nullptr, nullptr);
8863 
8864   ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8865   if (!NewStep.isUsable())
8866     return std::make_pair(nullptr, nullptr);
8867   Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
8868   if (!Diff.isUsable())
8869     return std::make_pair(nullptr, nullptr);
8870 
8871   // Parentheses (for dumping/debugging purposes only).
8872   Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8873   if (!Diff.isUsable())
8874     return std::make_pair(nullptr, nullptr);
8875 
8876   // Convert to the ptrdiff_t, if original type is pointer.
8877   if (VarType->isAnyPointerType() &&
8878       !SemaRef.Context.hasSameType(
8879           Diff.get()->getType(),
8880           SemaRef.Context.getUnsignedPointerDiffType())) {
8881     Diff = SemaRef.PerformImplicitConversion(
8882         Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
8883         Sema::AA_Converting, /*AllowExplicit=*/true);
8884   }
8885   if (!Diff.isUsable())
8886     return std::make_pair(nullptr, nullptr);
8887 
8888   if (*TestIsLessOp) {
8889     // MinExpr = Lower;
8890     // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
8891     Diff = SemaRef.BuildBinOp(
8892         S, DefaultLoc, BO_Add,
8893         SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
8894         Diff.get());
8895     if (!Diff.isUsable())
8896       return std::make_pair(nullptr, nullptr);
8897   } else {
8898     // MaxExpr = Upper;
8899     // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
8900     Diff = SemaRef.BuildBinOp(
8901         S, DefaultLoc, BO_Sub,
8902         SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8903         Diff.get());
8904     if (!Diff.isUsable())
8905       return std::make_pair(nullptr, nullptr);
8906   }
8907 
8908   // Convert to the original type.
8909   if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
8910     Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
8911                                              Sema::AA_Converting,
8912                                              /*AllowExplicit=*/true);
8913   if (!Diff.isUsable())
8914     return std::make_pair(nullptr, nullptr);
8915 
8916   Sema::TentativeAnalysisScope Trap(SemaRef);
8917   Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
8918   if (!Diff.isUsable())
8919     return std::make_pair(nullptr, nullptr);
8920 
8921   if (*TestIsLessOp)
8922     MaxExpr = Diff.get();
8923   else
8924     MinExpr = Diff.get();
8925 
8926   return std::make_pair(MinExpr, MaxExpr);
8927 }
8928 
buildFinalCondition(Scope * S) const8929 Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
8930   if (InitDependOnLC || CondDependOnLC)
8931     return Condition;
8932   return nullptr;
8933 }
8934 
buildPreCond(Scope * S,Expr * Cond,llvm::MapVector<const Expr *,DeclRefExpr * > & Captures) const8935 Expr *OpenMPIterationSpaceChecker::buildPreCond(
8936     Scope *S, Expr *Cond,
8937     llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8938   // Do not build a precondition when the condition/initialization is dependent
8939   // to prevent pessimistic early loop exit.
8940   // TODO: this can be improved by calculating min/max values but not sure that
8941   // it will be very effective.
8942   if (CondDependOnLC || InitDependOnLC)
8943     return SemaRef
8944         .PerformImplicitConversion(
8945             SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
8946             SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
8947             /*AllowExplicit=*/true)
8948         .get();
8949 
8950   // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
8951   Sema::TentativeAnalysisScope Trap(SemaRef);
8952 
8953   ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
8954   ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
8955   if (!NewLB.isUsable() || !NewUB.isUsable())
8956     return nullptr;
8957 
8958   ExprResult CondExpr =
8959       SemaRef.BuildBinOp(S, DefaultLoc,
8960                          *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
8961                                        : (TestIsStrictOp ? BO_GT : BO_GE),
8962                          NewLB.get(), NewUB.get());
8963   if (CondExpr.isUsable()) {
8964     if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
8965                                                 SemaRef.Context.BoolTy))
8966       CondExpr = SemaRef.PerformImplicitConversion(
8967           CondExpr.get(), SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
8968           /*AllowExplicit=*/true);
8969   }
8970 
8971   // Otherwise use original loop condition and evaluate it in runtime.
8972   return CondExpr.isUsable() ? CondExpr.get() : Cond;
8973 }
8974 
8975 /// Build reference expression to the counter be used for codegen.
buildCounterVar(llvm::MapVector<const Expr *,DeclRefExpr * > & Captures,DSAStackTy & DSA) const8976 DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
8977     llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8978     DSAStackTy &DSA) const {
8979   auto *VD = dyn_cast<VarDecl>(LCDecl);
8980   if (!VD) {
8981     VD = SemaRef.OpenMP().isOpenMPCapturedDecl(LCDecl);
8982     DeclRefExpr *Ref = buildDeclRefExpr(
8983         SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
8984     const DSAStackTy::DSAVarData Data =
8985         DSA.getTopDSA(LCDecl, /*FromParent=*/false);
8986     // If the loop control decl is explicitly marked as private, do not mark it
8987     // as captured again.
8988     if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
8989       Captures.insert(std::make_pair(LCRef, Ref));
8990     return Ref;
8991   }
8992   return cast<DeclRefExpr>(LCRef);
8993 }
8994 
buildPrivateCounterVar() const8995 Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
8996   if (LCDecl && !LCDecl->isInvalidDecl()) {
8997     QualType Type = LCDecl->getType().getNonReferenceType();
8998     VarDecl *PrivateVar = buildVarDecl(
8999         SemaRef, DefaultLoc, Type, LCDecl->getName(),
9000         LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9001         isa<VarDecl>(LCDecl)
9002             ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
9003             : nullptr);
9004     if (PrivateVar->isInvalidDecl())
9005       return nullptr;
9006     return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
9007   }
9008   return nullptr;
9009 }
9010 
9011 /// Build initialization of the counter to be used for codegen.
buildCounterInit() const9012 Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9013 
9014 /// Build step of the counter be used for codegen.
buildCounterStep() const9015 Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9016 
buildOrderedLoopData(Scope * S,Expr * Counter,llvm::MapVector<const Expr *,DeclRefExpr * > & Captures,SourceLocation Loc,Expr * Inc,OverloadedOperatorKind OOK)9017 Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9018     Scope *S, Expr *Counter,
9019     llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9020     Expr *Inc, OverloadedOperatorKind OOK) {
9021   Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
9022   if (!Cnt)
9023     return nullptr;
9024   if (Inc) {
9025     assert((OOK == OO_Plus || OOK == OO_Minus) &&
9026            "Expected only + or - operations for depend clauses.");
9027     BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9028     Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
9029     if (!Cnt)
9030       return nullptr;
9031   }
9032   QualType VarType = LCDecl->getType().getNonReferenceType();
9033   if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9034       !SemaRef.getLangOpts().CPlusPlus)
9035     return nullptr;
9036   // Upper - Lower
9037   Expr *Upper =
9038       *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9039   Expr *Lower =
9040       *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9041   if (!Upper || !Lower)
9042     return nullptr;
9043 
9044   ExprResult Diff = calculateNumIters(
9045       SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9046       /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9047   if (!Diff.isUsable())
9048     return nullptr;
9049 
9050   return Diff.get();
9051 }
9052 } // namespace
9053 
ActOnOpenMPLoopInitialization(SourceLocation ForLoc,Stmt * Init)9054 void SemaOpenMP::ActOnOpenMPLoopInitialization(SourceLocation ForLoc,
9055                                                Stmt *Init) {
9056   assert(getLangOpts().OpenMP && "OpenMP is not active.");
9057   assert(Init && "Expected loop in canonical form.");
9058   unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9059   OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9060   if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
9061     return;
9062 
9063   DSAStack->loopStart();
9064   OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9065                                   *DSAStack, ForLoc);
9066   if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9067     if (ValueDecl *D = ISC.getLoopDecl()) {
9068       auto *VD = dyn_cast<VarDecl>(D);
9069       DeclRefExpr *PrivateRef = nullptr;
9070       if (!VD) {
9071         if (VarDecl *Private = isOpenMPCapturedDecl(D)) {
9072           VD = Private;
9073         } else {
9074           PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(),
9075                                     /*WithInit=*/false);
9076           VD = cast<VarDecl>(PrivateRef->getDecl());
9077         }
9078       }
9079       DSAStack->addLoopControlVariable(D, VD);
9080       const Decl *LD = DSAStack->getPossiblyLoopCounter();
9081       if (LD != D->getCanonicalDecl()) {
9082         DSAStack->resetPossibleLoopCounter();
9083         if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9084           SemaRef.MarkDeclarationsReferencedInExpr(buildDeclRefExpr(
9085               SemaRef, const_cast<VarDecl *>(Var),
9086               Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
9087               /*RefersToCapture=*/true));
9088       }
9089       // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9090       // Referenced in a Construct, C/C++]. The loop iteration variable in the
9091       // associated for-loop of a simd construct with just one associated
9092       // for-loop may be listed in a linear clause with a constant-linear-step
9093       // that is the increment of the associated for-loop. The loop iteration
9094       // variable(s) in the associated for-loop(s) of a for or parallel for
9095       // construct may be listed in a private or lastprivate clause.
9096       DSAStackTy::DSAVarData DVar =
9097           DSAStack->getTopDSA(D, /*FromParent=*/false);
9098       // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9099       // is declared in the loop and it is predetermined as a private.
9100       Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9101       OpenMPClauseKind PredeterminedCKind =
9102           isOpenMPSimdDirective(DKind)
9103               ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9104               : OMPC_private;
9105       auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
9106         return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9107       };
9108       if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9109             DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9110             (getLangOpts().OpenMP <= 45 ||
9111              (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9112            ((isOpenMPWorksharingDirective(DKind) ||
9113              IsOpenMPTaskloopDirective(DKind) ||
9114              isOpenMPDistributeDirective(DKind)) &&
9115             !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9116             DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9117           (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9118         Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9119             << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind)
9120             << getOpenMPClauseName(PredeterminedCKind);
9121         if (DVar.RefExpr == nullptr)
9122           DVar.CKind = PredeterminedCKind;
9123         reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
9124       } else if (LoopDeclRefExpr) {
9125         // Make the loop iteration variable private (for worksharing
9126         // constructs), linear (for simd directives with the only one
9127         // associated loop) or lastprivate (for simd directives with several
9128         // collapsed or ordered loops).
9129         if (DVar.CKind == OMPC_unknown)
9130           DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9131       }
9132     }
9133   }
9134   DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9135 }
9136 
9137 namespace {
9138 // Utility for OpenMP doacross clause kind
9139 class OMPDoacrossKind {
9140 public:
isSource(const OMPDoacrossClause * C)9141   bool isSource(const OMPDoacrossClause *C) {
9142     return C->getDependenceType() == OMPC_DOACROSS_source ||
9143            C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9144   }
isSink(const OMPDoacrossClause * C)9145   bool isSink(const OMPDoacrossClause *C) {
9146     return C->getDependenceType() == OMPC_DOACROSS_sink;
9147   }
isSinkIter(const OMPDoacrossClause * C)9148   bool isSinkIter(const OMPDoacrossClause *C) {
9149     return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9150   }
9151 };
9152 } // namespace
9153 /// Called on a for stmt to check and extract its iteration space
9154 /// 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)9155 static bool checkOpenMPIterationSpace(
9156     OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9157     unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9158     unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9159     Expr *OrderedLoopCountExpr,
9160     SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9161     llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces,
9162     llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9163   bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9164   // OpenMP [2.9.1, Canonical Loop Form]
9165   //   for (init-expr; test-expr; incr-expr) structured-block
9166   //   for (range-decl: range-expr) structured-block
9167   if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9168     S = CanonLoop->getLoopStmt();
9169   auto *For = dyn_cast_or_null<ForStmt>(S);
9170   auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9171   // Ranged for is supported only in OpenMP 5.0.
9172   if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9173     OpenMPDirectiveKind DK = (SemaRef.getLangOpts().OpenMP < 50 ||
9174                               DSA.getMappedDirective() == OMPD_unknown)
9175                                  ? DKind
9176                                  : DSA.getMappedDirective();
9177     SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9178         << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9179         << getOpenMPDirectiveName(DK) << TotalNestedLoopCount
9180         << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9181     if (TotalNestedLoopCount > 1) {
9182       if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9183         SemaRef.Diag(DSA.getConstructLoc(),
9184                      diag::note_omp_collapse_ordered_expr)
9185             << 2 << CollapseLoopCountExpr->getSourceRange()
9186             << OrderedLoopCountExpr->getSourceRange();
9187       else if (CollapseLoopCountExpr)
9188         SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9189                      diag::note_omp_collapse_ordered_expr)
9190             << 0 << CollapseLoopCountExpr->getSourceRange();
9191       else
9192         SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9193                      diag::note_omp_collapse_ordered_expr)
9194             << 1 << OrderedLoopCountExpr->getSourceRange();
9195     }
9196     return true;
9197   }
9198   assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9199          "No loop body.");
9200   // Postpone analysis in dependent contexts for ranged for loops.
9201   if (CXXFor && SemaRef.CurContext->isDependentContext())
9202     return false;
9203 
9204   OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9205                                   For ? For->getForLoc() : CXXFor->getForLoc());
9206 
9207   // Check init.
9208   Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9209   if (ISC.checkAndSetInit(Init))
9210     return true;
9211 
9212   bool HasErrors = false;
9213 
9214   // Check loop variable's type.
9215   if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9216     // OpenMP [2.6, Canonical Loop Form]
9217     // Var is one of the following:
9218     //   A variable of signed or unsigned integer type.
9219     //   For C++, a variable of a random access iterator type.
9220     //   For C, a variable of a pointer type.
9221     QualType VarType = LCDecl->getType().getNonReferenceType();
9222     if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9223         !VarType->isPointerType() &&
9224         !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9225       SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9226           << SemaRef.getLangOpts().CPlusPlus;
9227       HasErrors = true;
9228     }
9229 
9230     // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9231     // a Construct
9232     // The loop iteration variable(s) in the associated for-loop(s) of a for or
9233     // parallel for construct is (are) private.
9234     // The loop iteration variable in the associated for-loop of a simd
9235     // construct with just one associated for-loop is linear with a
9236     // constant-linear-step that is the increment of the associated for-loop.
9237     // Exclude loop var from the list of variables with implicitly defined data
9238     // sharing attributes.
9239     VarsWithImplicitDSA.erase(LCDecl);
9240 
9241     assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
9242 
9243     // Check test-expr.
9244     HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9245 
9246     // Check incr-expr.
9247     HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9248   }
9249 
9250   if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9251     return HasErrors;
9252 
9253   // Build the loop's iteration space representation.
9254   ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9255       DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9256   ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9257       ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9258                              (isOpenMPWorksharingDirective(DKind) ||
9259                               isOpenMPGenericLoopDirective(DKind) ||
9260                               isOpenMPTaskLoopDirective(DKind) ||
9261                               isOpenMPDistributeDirective(DKind) ||
9262                               isOpenMPLoopTransformationDirective(DKind)),
9263                              Captures);
9264   ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9265       ISC.buildCounterVar(Captures, DSA);
9266   ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9267       ISC.buildPrivateCounterVar();
9268   ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9269   ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9270   ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9271   ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9272       ISC.getConditionSrcRange();
9273   ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9274       ISC.getIncrementSrcRange();
9275   ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9276   ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9277       ISC.isStrictTestOp();
9278   std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9279            ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9280       ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9281   ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9282       ISC.buildFinalCondition(DSA.getCurScope());
9283   ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9284       ISC.doesInitDependOnLC();
9285   ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9286       ISC.doesCondDependOnLC();
9287   ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9288       ISC.getLoopDependentIdx();
9289 
9290   HasErrors |=
9291       (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9292        ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9293        ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9294        ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9295        ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9296        ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9297   if (!HasErrors && DSA.isOrderedRegion()) {
9298     if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9299       if (CurrentNestedLoopCount <
9300           DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9301         DSA.getOrderedRegionParam().second->setLoopNumIterations(
9302             CurrentNestedLoopCount,
9303             ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9304         DSA.getOrderedRegionParam().second->setLoopCounter(
9305             CurrentNestedLoopCount,
9306             ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9307       }
9308     }
9309     for (auto &Pair : DSA.getDoacrossDependClauses()) {
9310       auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9311       auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9312       unsigned NumLoops =
9313           DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9314       if (CurrentNestedLoopCount >= NumLoops) {
9315         // Erroneous case - clause has some problems.
9316         continue;
9317       }
9318       if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9319           Pair.second.size() <= CurrentNestedLoopCount) {
9320         // Erroneous case - clause has some problems.
9321         DependC->setLoopData(CurrentNestedLoopCount, nullptr);
9322         continue;
9323       }
9324       OMPDoacrossKind ODK;
9325       if (DoacrossC && ODK.isSink(DoacrossC) &&
9326           Pair.second.size() <= CurrentNestedLoopCount) {
9327         // Erroneous case - clause has some problems.
9328         DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
9329         continue;
9330       }
9331       Expr *CntValue;
9332       SourceLocation DepLoc =
9333           DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9334       if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9335           (DoacrossC && ODK.isSource(DoacrossC)))
9336         CntValue = ISC.buildOrderedLoopData(
9337             DSA.getCurScope(),
9338             ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9339             DepLoc);
9340       else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9341         Expr *Cnt = SemaRef
9342                         .DefaultLvalueConversion(
9343                             ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9344                         .get();
9345         if (!Cnt)
9346           continue;
9347         // build CounterVar - 1
9348         Expr *Inc =
9349             SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
9350                 .get();
9351         CntValue = ISC.buildOrderedLoopData(
9352             DSA.getCurScope(),
9353             ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9354             DepLoc, Inc, clang::OO_Minus);
9355       } else
9356         CntValue = ISC.buildOrderedLoopData(
9357             DSA.getCurScope(),
9358             ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9359             DepLoc, Pair.second[CurrentNestedLoopCount].first,
9360             Pair.second[CurrentNestedLoopCount].second);
9361       if (DependC)
9362         DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9363       else
9364         DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9365     }
9366   }
9367 
9368   return HasErrors;
9369 }
9370 
9371 /// Build 'VarRef = Start.
9372 static ExprResult
buildCounterInit(Sema & SemaRef,Scope * S,SourceLocation Loc,ExprResult VarRef,ExprResult Start,bool IsNonRectangularLB,llvm::MapVector<const Expr *,DeclRefExpr * > & Captures)9373 buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9374                  ExprResult Start, bool IsNonRectangularLB,
9375                  llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9376   // Build 'VarRef = Start.
9377   ExprResult NewStart = IsNonRectangularLB
9378                             ? Start.get()
9379                             : tryBuildCapture(SemaRef, Start.get(), Captures);
9380   if (!NewStart.isUsable())
9381     return ExprError();
9382   if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9383                                    VarRef.get()->getType())) {
9384     NewStart = SemaRef.PerformImplicitConversion(
9385         NewStart.get(), VarRef.get()->getType(), Sema::AA_Converting,
9386         /*AllowExplicit=*/true);
9387     if (!NewStart.isUsable())
9388       return ExprError();
9389   }
9390 
9391   ExprResult Init =
9392       SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9393   return Init;
9394 }
9395 
9396 /// 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)9397 static ExprResult buildCounterUpdate(
9398     Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9399     ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9400     bool IsNonRectangularLB,
9401     llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9402   // Add parentheses (for debugging purposes only).
9403   Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9404   if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9405       !Step.isUsable())
9406     return ExprError();
9407 
9408   ExprResult NewStep = Step;
9409   if (Captures)
9410     NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9411   if (NewStep.isInvalid())
9412     return ExprError();
9413   ExprResult Update =
9414       SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9415   if (!Update.isUsable())
9416     return ExprError();
9417 
9418   // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9419   // 'VarRef = Start (+|-) Iter * Step'.
9420   if (!Start.isUsable())
9421     return ExprError();
9422   ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9423   if (!NewStart.isUsable())
9424     return ExprError();
9425   if (Captures && !IsNonRectangularLB)
9426     NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9427   if (NewStart.isInvalid())
9428     return ExprError();
9429 
9430   // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9431   ExprResult SavedUpdate = Update;
9432   ExprResult UpdateVal;
9433   if (VarRef.get()->getType()->isOverloadableType() ||
9434       NewStart.get()->getType()->isOverloadableType() ||
9435       Update.get()->getType()->isOverloadableType()) {
9436     Sema::TentativeAnalysisScope Trap(SemaRef);
9437 
9438     Update =
9439         SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9440     if (Update.isUsable()) {
9441       UpdateVal =
9442           SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9443                              VarRef.get(), SavedUpdate.get());
9444       if (UpdateVal.isUsable()) {
9445         Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9446                                             UpdateVal.get());
9447       }
9448     }
9449   }
9450 
9451   // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9452   if (!Update.isUsable() || !UpdateVal.isUsable()) {
9453     Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9454                                 NewStart.get(), SavedUpdate.get());
9455     if (!Update.isUsable())
9456       return ExprError();
9457 
9458     if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9459                                      VarRef.get()->getType())) {
9460       Update = SemaRef.PerformImplicitConversion(
9461           Update.get(), VarRef.get()->getType(), Sema::AA_Converting, true);
9462       if (!Update.isUsable())
9463         return ExprError();
9464     }
9465 
9466     Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9467   }
9468   return Update;
9469 }
9470 
9471 /// Convert integer expression \a E to make it have at least \a Bits
9472 /// bits.
widenIterationCount(unsigned Bits,Expr * E,Sema & SemaRef)9473 static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9474   if (E == nullptr)
9475     return ExprError();
9476   ASTContext &C = SemaRef.Context;
9477   QualType OldType = E->getType();
9478   unsigned HasBits = C.getTypeSize(OldType);
9479   if (HasBits >= Bits)
9480     return ExprResult(E);
9481   // OK to convert to signed, because new type has more bits than old.
9482   QualType NewType = C.getIntTypeForBitwidth(Bits, /* Signed */ true);
9483   return SemaRef.PerformImplicitConversion(E, NewType, Sema::AA_Converting,
9484                                            true);
9485 }
9486 
9487 /// Check if the given expression \a E is a constant integer that fits
9488 /// into \a Bits bits.
fitsInto(unsigned Bits,bool Signed,const Expr * E,Sema & SemaRef)9489 static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9490   if (E == nullptr)
9491     return false;
9492   if (std::optional<llvm::APSInt> Result =
9493           E->getIntegerConstantExpr(SemaRef.Context))
9494     return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9495   return false;
9496 }
9497 
9498 /// Build preinits statement for the given declarations.
buildPreInits(ASTContext & Context,MutableArrayRef<Decl * > PreInits)9499 static Stmt *buildPreInits(ASTContext &Context,
9500                            MutableArrayRef<Decl *> PreInits) {
9501   if (!PreInits.empty()) {
9502     return new (Context) DeclStmt(
9503         DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9504         SourceLocation(), SourceLocation());
9505   }
9506   return nullptr;
9507 }
9508 
9509 /// Append the \p Item or the content of a CompoundStmt to the list \p
9510 /// TargetList.
9511 ///
9512 /// A CompoundStmt is used as container in case multiple statements need to be
9513 /// stored in lieu of using an explicit list. Flattening is necessary because
9514 /// contained DeclStmts need to be visible after the execution of the list. Used
9515 /// for OpenMP pre-init declarations/statements.
appendFlattenedStmtList(SmallVectorImpl<Stmt * > & TargetList,Stmt * Item)9516 static void appendFlattenedStmtList(SmallVectorImpl<Stmt *> &TargetList,
9517                                      Stmt *Item) {
9518   // nullptr represents an empty list.
9519   if (!Item)
9520     return;
9521 
9522   if (auto *CS = dyn_cast<CompoundStmt>(Item))
9523     llvm::append_range(TargetList, CS->body());
9524   else
9525     TargetList.push_back(Item);
9526 }
9527 
9528 /// Build preinits statement for the given declarations.
9529 static Stmt *
buildPreInits(ASTContext & Context,const llvm::MapVector<const Expr *,DeclRefExpr * > & Captures)9530 buildPreInits(ASTContext &Context,
9531               const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9532   if (!Captures.empty()) {
9533     SmallVector<Decl *, 16> PreInits;
9534     for (const auto &Pair : Captures)
9535       PreInits.push_back(Pair.second->getDecl());
9536     return buildPreInits(Context, PreInits);
9537   }
9538   return nullptr;
9539 }
9540 
9541 /// Build pre-init statement for the given statements.
buildPreInits(ASTContext & Context,ArrayRef<Stmt * > PreInits)9542 static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
9543   if (PreInits.empty())
9544     return nullptr;
9545 
9546   SmallVector<Stmt *> Stmts;
9547   for (Stmt *S : PreInits)
9548     appendFlattenedStmtList(Stmts, S);
9549   return CompoundStmt::Create(Context, PreInits, FPOptionsOverride(), {}, {});
9550 }
9551 
9552 /// Build postupdate expression for the given list of postupdates expressions.
buildPostUpdate(Sema & S,ArrayRef<Expr * > PostUpdates)9553 static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9554   Expr *PostUpdate = nullptr;
9555   if (!PostUpdates.empty()) {
9556     for (Expr *E : PostUpdates) {
9557       Expr *ConvE = S.BuildCStyleCastExpr(
9558                          E->getExprLoc(),
9559                          S.Context.getTrivialTypeSourceInfo(S.Context.VoidTy),
9560                          E->getExprLoc(), E)
9561                         .get();
9562       PostUpdate = PostUpdate
9563                        ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9564                                               PostUpdate, ConvE)
9565                              .get()
9566                        : ConvE;
9567     }
9568   }
9569   return PostUpdate;
9570 }
9571 
9572 /// Called on a for stmt to check itself and nested loops (if any).
9573 /// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9574 /// number of collapsed loops otherwise.
9575 static unsigned
checkOpenMPLoop(OpenMPDirectiveKind DKind,Expr * CollapseLoopCountExpr,Expr * OrderedLoopCountExpr,Stmt * AStmt,Sema & SemaRef,DSAStackTy & DSA,SemaOpenMP::VarsWithInheritedDSAType & VarsWithImplicitDSA,OMPLoopBasedDirective::HelperExprs & Built)9576 checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9577                 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9578                 DSAStackTy &DSA,
9579                 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9580                 OMPLoopBasedDirective::HelperExprs &Built) {
9581   unsigned NestedLoopCount = 1;
9582   bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9583                                     !isOpenMPLoopTransformationDirective(DKind);
9584 
9585   if (CollapseLoopCountExpr) {
9586     // Found 'collapse' clause - calculate collapse number.
9587     Expr::EvalResult Result;
9588     if (!CollapseLoopCountExpr->isValueDependent() &&
9589         CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9590       NestedLoopCount = Result.Val.getInt().getLimitedValue();
9591     } else {
9592       Built.clear(/*Size=*/1);
9593       return 1;
9594     }
9595   }
9596   unsigned OrderedLoopCount = 1;
9597   if (OrderedLoopCountExpr) {
9598     // Found 'ordered' clause - calculate collapse number.
9599     Expr::EvalResult EVResult;
9600     if (!OrderedLoopCountExpr->isValueDependent() &&
9601         OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9602                                             SemaRef.getASTContext())) {
9603       llvm::APSInt Result = EVResult.Val.getInt();
9604       if (Result.getLimitedValue() < NestedLoopCount) {
9605         SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9606                      diag::err_omp_wrong_ordered_loop_count)
9607             << OrderedLoopCountExpr->getSourceRange();
9608         SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9609                      diag::note_collapse_loop_count)
9610             << CollapseLoopCountExpr->getSourceRange();
9611       }
9612       OrderedLoopCount = Result.getLimitedValue();
9613     } else {
9614       Built.clear(/*Size=*/1);
9615       return 1;
9616     }
9617   }
9618   // This is helper routine for loop directives (e.g., 'for', 'simd',
9619   // 'for simd', etc.).
9620   llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9621   unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9622   SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9623   if (!OMPLoopBasedDirective::doForAllLoops(
9624           AStmt->IgnoreContainers(!isOpenMPLoopTransformationDirective(DKind)),
9625           SupportsNonPerfectlyNested, NumLoops,
9626           [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9627            CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9628            &IterSpaces, &Captures](unsigned Cnt, Stmt *CurStmt) {
9629             if (checkOpenMPIterationSpace(
9630                     DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9631                     NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9632                     VarsWithImplicitDSA, IterSpaces, Captures))
9633               return true;
9634             if (Cnt > 0 && Cnt >= NestedLoopCount &&
9635                 IterSpaces[Cnt].CounterVar) {
9636               // Handle initialization of captured loop iterator variables.
9637               auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9638               if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9639                 Captures[DRE] = DRE;
9640               }
9641             }
9642             return false;
9643           },
9644           [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9645             Stmt *DependentPreInits = Transform->getPreInits();
9646             if (!DependentPreInits)
9647               return;
9648 
9649             // Search for pre-init declared variables that need to be captured
9650             // to be referenceable inside the directive.
9651             SmallVector<Stmt *> Constituents;
9652             appendFlattenedStmtList(Constituents, DependentPreInits);
9653             for (Stmt *S : Constituents) {
9654               if (auto *DC = dyn_cast<DeclStmt>(S)) {
9655                 for (Decl *C : DC->decls()) {
9656                   auto *D = cast<VarDecl>(C);
9657                   DeclRefExpr *Ref = buildDeclRefExpr(
9658                       SemaRef, D, D->getType().getNonReferenceType(),
9659                       Transform->getBeginLoc());
9660                   Captures[Ref] = Ref;
9661                 }
9662               }
9663             }
9664           }))
9665     return 0;
9666 
9667   Built.clear(/* size */ NestedLoopCount);
9668 
9669   if (SemaRef.CurContext->isDependentContext())
9670     return NestedLoopCount;
9671 
9672   // An example of what is generated for the following code:
9673   //
9674   //   #pragma omp simd collapse(2) ordered(2)
9675   //   for (i = 0; i < NI; ++i)
9676   //     for (k = 0; k < NK; ++k)
9677   //       for (j = J0; j < NJ; j+=2) {
9678   //         <loop body>
9679   //       }
9680   //
9681   // We generate the code below.
9682   // Note: the loop body may be outlined in CodeGen.
9683   // Note: some counters may be C++ classes, operator- is used to find number of
9684   // iterations and operator+= to calculate counter value.
9685   // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9686   // or i64 is currently supported).
9687   //
9688   //   #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9689   //   for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9690   //     .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9691   //     .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9692   //     // similar updates for vars in clauses (e.g. 'linear')
9693   //     <loop body (using local i and j)>
9694   //   }
9695   //   i = NI; // assign final values of counters
9696   //   j = NJ;
9697   //
9698 
9699   // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9700   // the iteration counts of the collapsed for loops.
9701   // Precondition tests if there is at least one iteration (all conditions are
9702   // true).
9703   auto PreCond = ExprResult(IterSpaces[0].PreCond);
9704   Expr *N0 = IterSpaces[0].NumIterations;
9705   ExprResult LastIteration32 =
9706       widenIterationCount(/*Bits=*/32,
9707                           SemaRef
9708                               .PerformImplicitConversion(
9709                                   N0->IgnoreImpCasts(), N0->getType(),
9710                                   Sema::AA_Converting, /*AllowExplicit=*/true)
9711                               .get(),
9712                           SemaRef);
9713   ExprResult LastIteration64 = widenIterationCount(
9714       /*Bits=*/64,
9715       SemaRef
9716           .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
9717                                      Sema::AA_Converting,
9718                                      /*AllowExplicit=*/true)
9719           .get(),
9720       SemaRef);
9721 
9722   if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
9723     return NestedLoopCount;
9724 
9725   ASTContext &C = SemaRef.Context;
9726   bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
9727 
9728   Scope *CurScope = DSA.getCurScope();
9729   for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9730     if (PreCond.isUsable()) {
9731       PreCond =
9732           SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
9733                              PreCond.get(), IterSpaces[Cnt].PreCond);
9734     }
9735     Expr *N = IterSpaces[Cnt].NumIterations;
9736     SourceLocation Loc = N->getExprLoc();
9737     AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
9738     if (LastIteration32.isUsable())
9739       LastIteration32 = SemaRef.BuildBinOp(
9740           CurScope, Loc, BO_Mul, LastIteration32.get(),
9741           SemaRef
9742               .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
9743                                          Sema::AA_Converting,
9744                                          /*AllowExplicit=*/true)
9745               .get());
9746     if (LastIteration64.isUsable())
9747       LastIteration64 = SemaRef.BuildBinOp(
9748           CurScope, Loc, BO_Mul, LastIteration64.get(),
9749           SemaRef
9750               .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
9751                                          Sema::AA_Converting,
9752                                          /*AllowExplicit=*/true)
9753               .get());
9754   }
9755 
9756   // Choose either the 32-bit or 64-bit version.
9757   ExprResult LastIteration = LastIteration64;
9758   if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
9759       (LastIteration32.isUsable() &&
9760        C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
9761        (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9762         fitsInto(
9763             /*Bits=*/32,
9764             LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
9765             LastIteration64.get(), SemaRef))))
9766     LastIteration = LastIteration32;
9767   QualType VType = LastIteration.get()->getType();
9768   QualType RealVType = VType;
9769   QualType StrideVType = VType;
9770   if (isOpenMPTaskLoopDirective(DKind)) {
9771     VType =
9772         SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9773     StrideVType =
9774         SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9775   }
9776 
9777   if (!LastIteration.isUsable())
9778     return 0;
9779 
9780   // Save the number of iterations.
9781   ExprResult NumIterations = LastIteration;
9782   {
9783     LastIteration = SemaRef.BuildBinOp(
9784         CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
9785         LastIteration.get(),
9786         SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9787     if (!LastIteration.isUsable())
9788       return 0;
9789   }
9790 
9791   // Calculate the last iteration number beforehand instead of doing this on
9792   // each iteration. Do not do this if the number of iterations may be kfold-ed.
9793   bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
9794   ExprResult CalcLastIteration;
9795   if (!IsConstant) {
9796     ExprResult SaveRef =
9797         tryBuildCapture(SemaRef, LastIteration.get(), Captures);
9798     LastIteration = SaveRef;
9799 
9800     // Prepare SaveRef + 1.
9801     NumIterations = SemaRef.BuildBinOp(
9802         CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
9803         SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9804     if (!NumIterations.isUsable())
9805       return 0;
9806   }
9807 
9808   SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
9809 
9810   // Build variables passed into runtime, necessary for worksharing directives.
9811   ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9812   if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
9813       isOpenMPDistributeDirective(DKind) ||
9814       isOpenMPGenericLoopDirective(DKind) ||
9815       isOpenMPLoopTransformationDirective(DKind)) {
9816     // Lower bound variable, initialized with zero.
9817     VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
9818     LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
9819     SemaRef.AddInitializerToDecl(LBDecl,
9820                                  SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9821                                  /*DirectInit*/ false);
9822 
9823     // Upper bound variable, initialized with last iteration number.
9824     VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
9825     UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
9826     SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
9827                                  /*DirectInit*/ false);
9828 
9829     // A 32-bit variable-flag where runtime returns 1 for the last iteration.
9830     // This will be used to implement clause 'lastprivate'.
9831     QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
9832     VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
9833     IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
9834     SemaRef.AddInitializerToDecl(ILDecl,
9835                                  SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9836                                  /*DirectInit*/ false);
9837 
9838     // Stride variable returned by runtime (we initialize it to 1 by default).
9839     VarDecl *STDecl =
9840         buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
9841     ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
9842     SemaRef.AddInitializerToDecl(STDecl,
9843                                  SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
9844                                  /*DirectInit*/ false);
9845 
9846     // Build expression: UB = min(UB, LastIteration)
9847     // It is necessary for CodeGen of directives with static scheduling.
9848     ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
9849                                                 UB.get(), LastIteration.get());
9850     ExprResult CondOp = SemaRef.ActOnConditionalOp(
9851         LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
9852         LastIteration.get(), UB.get());
9853     EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
9854                              CondOp.get());
9855     EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false);
9856 
9857     // If we have a combined directive that combines 'distribute', 'for' or
9858     // 'simd' we need to be able to access the bounds of the schedule of the
9859     // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
9860     // by scheduling 'distribute' have to be passed to the schedule of 'for'.
9861     if (isOpenMPLoopBoundSharingDirective(DKind)) {
9862       // Lower bound variable, initialized with zero.
9863       VarDecl *CombLBDecl =
9864           buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
9865       CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
9866       SemaRef.AddInitializerToDecl(
9867           CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9868           /*DirectInit*/ false);
9869 
9870       // Upper bound variable, initialized with last iteration number.
9871       VarDecl *CombUBDecl =
9872           buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
9873       CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
9874       SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
9875                                    /*DirectInit*/ false);
9876 
9877       ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
9878           CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
9879       ExprResult CombCondOp =
9880           SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
9881                                      LastIteration.get(), CombUB.get());
9882       CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
9883                                    CombCondOp.get());
9884       CombEUB =
9885           SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false);
9886 
9887       const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
9888       // We expect to have at least 2 more parameters than the 'parallel'
9889       // directive does - the lower and upper bounds of the previous schedule.
9890       assert(CD->getNumParams() >= 4 &&
9891              "Unexpected number of parameters in loop combined directive");
9892 
9893       // Set the proper type for the bounds given what we learned from the
9894       // enclosed loops.
9895       ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
9896       ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
9897 
9898       // Previous lower and upper bounds are obtained from the region
9899       // parameters.
9900       PrevLB =
9901           buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
9902       PrevUB =
9903           buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
9904     }
9905   }
9906 
9907   // Build the iteration variable and its initialization before loop.
9908   ExprResult IV;
9909   ExprResult Init, CombInit;
9910   {
9911     VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
9912     IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
9913     Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
9914                  isOpenMPGenericLoopDirective(DKind) ||
9915                  isOpenMPTaskLoopDirective(DKind) ||
9916                  isOpenMPDistributeDirective(DKind) ||
9917                  isOpenMPLoopTransformationDirective(DKind))
9918                     ? LB.get()
9919                     : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
9920     Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
9921     Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false);
9922 
9923     if (isOpenMPLoopBoundSharingDirective(DKind)) {
9924       Expr *CombRHS =
9925           (isOpenMPWorksharingDirective(DKind) ||
9926            isOpenMPGenericLoopDirective(DKind) ||
9927            isOpenMPTaskLoopDirective(DKind) ||
9928            isOpenMPDistributeDirective(DKind))
9929               ? CombLB.get()
9930               : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
9931       CombInit =
9932           SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
9933       CombInit =
9934           SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false);
9935     }
9936   }
9937 
9938   bool UseStrictCompare =
9939       RealVType->hasUnsignedIntegerRepresentation() &&
9940       llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
9941         return LIS.IsStrictCompare;
9942       });
9943   // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
9944   // unsigned IV)) for worksharing loops.
9945   SourceLocation CondLoc = AStmt->getBeginLoc();
9946   Expr *BoundUB = UB.get();
9947   if (UseStrictCompare) {
9948     BoundUB =
9949         SemaRef
9950             .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
9951                         SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
9952             .get();
9953     BoundUB =
9954         SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue*/ false).get();
9955   }
9956   ExprResult Cond =
9957       (isOpenMPWorksharingDirective(DKind) ||
9958        isOpenMPGenericLoopDirective(DKind) ||
9959        isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind) ||
9960        isOpenMPLoopTransformationDirective(DKind))
9961           ? SemaRef.BuildBinOp(CurScope, CondLoc,
9962                                UseStrictCompare ? BO_LT : BO_LE, IV.get(),
9963                                BoundUB)
9964           : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
9965                                NumIterations.get());
9966   ExprResult CombDistCond;
9967   if (isOpenMPLoopBoundSharingDirective(DKind)) {
9968     CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
9969                                       NumIterations.get());
9970   }
9971 
9972   ExprResult CombCond;
9973   if (isOpenMPLoopBoundSharingDirective(DKind)) {
9974     Expr *BoundCombUB = CombUB.get();
9975     if (UseStrictCompare) {
9976       BoundCombUB =
9977           SemaRef
9978               .BuildBinOp(
9979                   CurScope, CondLoc, BO_Add, BoundCombUB,
9980                   SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
9981               .get();
9982       BoundCombUB =
9983           SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue*/ false)
9984               .get();
9985     }
9986     CombCond =
9987         SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
9988                            IV.get(), BoundCombUB);
9989   }
9990   // Loop increment (IV = IV + 1)
9991   SourceLocation IncLoc = AStmt->getBeginLoc();
9992   ExprResult Inc =
9993       SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
9994                          SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
9995   if (!Inc.isUsable())
9996     return 0;
9997   Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
9998   Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false);
9999   if (!Inc.isUsable())
10000     return 0;
10001 
10002   // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10003   // Used for directives with static scheduling.
10004   // In combined construct, add combined version that use CombLB and CombUB
10005   // base variables for the update
10006   ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10007   if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
10008       isOpenMPGenericLoopDirective(DKind) ||
10009       isOpenMPDistributeDirective(DKind) ||
10010       isOpenMPLoopTransformationDirective(DKind)) {
10011     // LB + ST
10012     NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
10013     if (!NextLB.isUsable())
10014       return 0;
10015     // LB = LB + ST
10016     NextLB =
10017         SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
10018     NextLB =
10019         SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false);
10020     if (!NextLB.isUsable())
10021       return 0;
10022     // UB + ST
10023     NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
10024     if (!NextUB.isUsable())
10025       return 0;
10026     // UB = UB + ST
10027     NextUB =
10028         SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
10029     NextUB =
10030         SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false);
10031     if (!NextUB.isUsable())
10032       return 0;
10033     if (isOpenMPLoopBoundSharingDirective(DKind)) {
10034       CombNextLB =
10035           SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
10036       if (!NextLB.isUsable())
10037         return 0;
10038       // LB = LB + ST
10039       CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
10040                                       CombNextLB.get());
10041       CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
10042                                                /*DiscardedValue*/ false);
10043       if (!CombNextLB.isUsable())
10044         return 0;
10045       // UB + ST
10046       CombNextUB =
10047           SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
10048       if (!CombNextUB.isUsable())
10049         return 0;
10050       // UB = UB + ST
10051       CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
10052                                       CombNextUB.get());
10053       CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
10054                                                /*DiscardedValue*/ false);
10055       if (!CombNextUB.isUsable())
10056         return 0;
10057     }
10058   }
10059 
10060   // Create increment expression for distribute loop when combined in a same
10061   // directive with for as IV = IV + ST; ensure upper bound expression based
10062   // on PrevUB instead of NumIterations - used to implement 'for' when found
10063   // in combination with 'distribute', like in 'distribute parallel for'
10064   SourceLocation DistIncLoc = AStmt->getBeginLoc();
10065   ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10066   if (isOpenMPLoopBoundSharingDirective(DKind)) {
10067     DistCond = SemaRef.BuildBinOp(
10068         CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10069     assert(DistCond.isUsable() && "distribute cond expr was not built");
10070 
10071     DistInc =
10072         SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10073     assert(DistInc.isUsable() && "distribute inc expr was not built");
10074     DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10075                                  DistInc.get());
10076     DistInc =
10077         SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false);
10078     assert(DistInc.isUsable() && "distribute inc expr was not built");
10079 
10080     // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10081     // construct
10082     ExprResult NewPrevUB = PrevUB;
10083     SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10084     if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10085                                      PrevUB.get()->getType())) {
10086       NewPrevUB = SemaRef.BuildCStyleCastExpr(
10087           DistEUBLoc,
10088           SemaRef.Context.getTrivialTypeSourceInfo(UB.get()->getType()),
10089           DistEUBLoc, NewPrevUB.get());
10090       if (!NewPrevUB.isUsable())
10091         return 0;
10092     }
10093     ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10094                                                 UB.get(), NewPrevUB.get());
10095     ExprResult CondOp = SemaRef.ActOnConditionalOp(
10096         DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10097     PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10098                                  CondOp.get());
10099     PrevEUB =
10100         SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false);
10101 
10102     // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10103     // parallel for is in combination with a distribute directive with
10104     // schedule(static, 1)
10105     Expr *BoundPrevUB = PrevUB.get();
10106     if (UseStrictCompare) {
10107       BoundPrevUB =
10108           SemaRef
10109               .BuildBinOp(
10110                   CurScope, CondLoc, BO_Add, BoundPrevUB,
10111                   SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10112               .get();
10113       BoundPrevUB =
10114           SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue*/ false)
10115               .get();
10116     }
10117     ParForInDistCond =
10118         SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10119                            IV.get(), BoundPrevUB);
10120   }
10121 
10122   // Build updates and final values of the loop counters.
10123   bool HasErrors = false;
10124   Built.Counters.resize(NestedLoopCount);
10125   Built.Inits.resize(NestedLoopCount);
10126   Built.Updates.resize(NestedLoopCount);
10127   Built.Finals.resize(NestedLoopCount);
10128   Built.DependentCounters.resize(NestedLoopCount);
10129   Built.DependentInits.resize(NestedLoopCount);
10130   Built.FinalsConditions.resize(NestedLoopCount);
10131   {
10132     // We implement the following algorithm for obtaining the
10133     // original loop iteration variable values based on the
10134     // value of the collapsed loop iteration variable IV.
10135     //
10136     // Let n+1 be the number of collapsed loops in the nest.
10137     // Iteration variables (I0, I1, .... In)
10138     // Iteration counts (N0, N1, ... Nn)
10139     //
10140     // Acc = IV;
10141     //
10142     // To compute Ik for loop k, 0 <= k <= n, generate:
10143     //    Prod = N(k+1) * N(k+2) * ... * Nn;
10144     //    Ik = Acc / Prod;
10145     //    Acc -= Ik * Prod;
10146     //
10147     ExprResult Acc = IV;
10148     for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10149       LoopIterationSpace &IS = IterSpaces[Cnt];
10150       SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10151       ExprResult Iter;
10152 
10153       // Compute prod
10154       ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10155       for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10156         Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10157                                   IterSpaces[K].NumIterations);
10158 
10159       // Iter = Acc / Prod
10160       // If there is at least one more inner loop to avoid
10161       // multiplication by 1.
10162       if (Cnt + 1 < NestedLoopCount)
10163         Iter =
10164             SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10165       else
10166         Iter = Acc;
10167       if (!Iter.isUsable()) {
10168         HasErrors = true;
10169         break;
10170       }
10171 
10172       // Update Acc:
10173       // Acc -= Iter * Prod
10174       // Check if there is at least one more inner loop to avoid
10175       // multiplication by 1.
10176       if (Cnt + 1 < NestedLoopCount)
10177         Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10178                                   Prod.get());
10179       else
10180         Prod = Iter;
10181       Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10182 
10183       // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10184       auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10185       DeclRefExpr *CounterVar = buildDeclRefExpr(
10186           SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10187           /*RefersToCapture=*/true);
10188       ExprResult Init =
10189           buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10190                            IS.CounterInit, IS.IsNonRectangularLB, Captures);
10191       if (!Init.isUsable()) {
10192         HasErrors = true;
10193         break;
10194       }
10195       ExprResult Update = buildCounterUpdate(
10196           SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10197           IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10198       if (!Update.isUsable()) {
10199         HasErrors = true;
10200         break;
10201       }
10202 
10203       // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10204       ExprResult Final =
10205           buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10206                              IS.CounterInit, IS.NumIterations, IS.CounterStep,
10207                              IS.Subtract, IS.IsNonRectangularLB, &Captures);
10208       if (!Final.isUsable()) {
10209         HasErrors = true;
10210         break;
10211       }
10212 
10213       if (!Update.isUsable() || !Final.isUsable()) {
10214         HasErrors = true;
10215         break;
10216       }
10217       // Save results
10218       Built.Counters[Cnt] = IS.CounterVar;
10219       Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10220       Built.Inits[Cnt] = Init.get();
10221       Built.Updates[Cnt] = Update.get();
10222       Built.Finals[Cnt] = Final.get();
10223       Built.DependentCounters[Cnt] = nullptr;
10224       Built.DependentInits[Cnt] = nullptr;
10225       Built.FinalsConditions[Cnt] = nullptr;
10226       if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10227         Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10228         Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10229         Built.FinalsConditions[Cnt] = IS.FinalCondition;
10230       }
10231     }
10232   }
10233 
10234   if (HasErrors)
10235     return 0;
10236 
10237   // Save results
10238   Built.IterationVarRef = IV.get();
10239   Built.LastIteration = LastIteration.get();
10240   Built.NumIterations = NumIterations.get();
10241   Built.CalcLastIteration = SemaRef
10242                                 .ActOnFinishFullExpr(CalcLastIteration.get(),
10243                                                      /*DiscardedValue=*/false)
10244                                 .get();
10245   Built.PreCond = PreCond.get();
10246   Built.PreInits = buildPreInits(C, Captures);
10247   Built.Cond = Cond.get();
10248   Built.Init = Init.get();
10249   Built.Inc = Inc.get();
10250   Built.LB = LB.get();
10251   Built.UB = UB.get();
10252   Built.IL = IL.get();
10253   Built.ST = ST.get();
10254   Built.EUB = EUB.get();
10255   Built.NLB = NextLB.get();
10256   Built.NUB = NextUB.get();
10257   Built.PrevLB = PrevLB.get();
10258   Built.PrevUB = PrevUB.get();
10259   Built.DistInc = DistInc.get();
10260   Built.PrevEUB = PrevEUB.get();
10261   Built.DistCombinedFields.LB = CombLB.get();
10262   Built.DistCombinedFields.UB = CombUB.get();
10263   Built.DistCombinedFields.EUB = CombEUB.get();
10264   Built.DistCombinedFields.Init = CombInit.get();
10265   Built.DistCombinedFields.Cond = CombCond.get();
10266   Built.DistCombinedFields.NLB = CombNextLB.get();
10267   Built.DistCombinedFields.NUB = CombNextUB.get();
10268   Built.DistCombinedFields.DistCond = CombDistCond.get();
10269   Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10270 
10271   return NestedLoopCount;
10272 }
10273 
getCollapseNumberExpr(ArrayRef<OMPClause * > Clauses)10274 static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {
10275   auto CollapseClauses =
10276       OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10277   if (CollapseClauses.begin() != CollapseClauses.end())
10278     return (*CollapseClauses.begin())->getNumForLoops();
10279   return nullptr;
10280 }
10281 
getOrderedNumberExpr(ArrayRef<OMPClause * > Clauses)10282 static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) {
10283   auto OrderedClauses =
10284       OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10285   if (OrderedClauses.begin() != OrderedClauses.end())
10286     return (*OrderedClauses.begin())->getNumForLoops();
10287   return nullptr;
10288 }
10289 
checkSimdlenSafelenSpecified(Sema & S,const ArrayRef<OMPClause * > Clauses)10290 static bool checkSimdlenSafelenSpecified(Sema &S,
10291                                          const ArrayRef<OMPClause *> Clauses) {
10292   const OMPSafelenClause *Safelen = nullptr;
10293   const OMPSimdlenClause *Simdlen = nullptr;
10294 
10295   for (const OMPClause *Clause : Clauses) {
10296     if (Clause->getClauseKind() == OMPC_safelen)
10297       Safelen = cast<OMPSafelenClause>(Clause);
10298     else if (Clause->getClauseKind() == OMPC_simdlen)
10299       Simdlen = cast<OMPSimdlenClause>(Clause);
10300     if (Safelen && Simdlen)
10301       break;
10302   }
10303 
10304   if (Simdlen && Safelen) {
10305     const Expr *SimdlenLength = Simdlen->getSimdlen();
10306     const Expr *SafelenLength = Safelen->getSafelen();
10307     if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10308         SimdlenLength->isInstantiationDependent() ||
10309         SimdlenLength->containsUnexpandedParameterPack())
10310       return false;
10311     if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10312         SafelenLength->isInstantiationDependent() ||
10313         SafelenLength->containsUnexpandedParameterPack())
10314       return false;
10315     Expr::EvalResult SimdlenResult, SafelenResult;
10316     SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10317     SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10318     llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10319     llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10320     // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10321     // If both simdlen and safelen clauses are specified, the value of the
10322     // simdlen parameter must be less than or equal to the value of the safelen
10323     // parameter.
10324     if (SimdlenRes > SafelenRes) {
10325       S.Diag(SimdlenLength->getExprLoc(),
10326              diag::err_omp_wrong_simdlen_safelen_values)
10327           << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10328       return true;
10329     }
10330   }
10331   return false;
10332 }
10333 
10334 static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses,
10335                                         OpenMPDirectiveKind K,
10336                                         DSAStackTy *Stack);
10337 
checkLastPrivateForMappedDirectives(ArrayRef<OMPClause * > Clauses)10338 bool SemaOpenMP::checkLastPrivateForMappedDirectives(
10339     ArrayRef<OMPClause *> Clauses) {
10340 
10341   // Check for syntax of lastprivate
10342   // Param of the lastprivate have different meanings in the mapped directives
10343   // e.g. "omp loop" Only loop iteration vars are allowed in lastprivate clause
10344   //      "omp for"  lastprivate vars must be shared
10345   if (getLangOpts().OpenMP >= 50 &&
10346       DSAStack->getMappedDirective() == OMPD_loop &&
10347       checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack)) {
10348     return false;
10349   }
10350   return true;
10351 }
10352 
ActOnOpenMPSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10353 StmtResult SemaOpenMP::ActOnOpenMPSimdDirective(
10354     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10355     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10356   if (!AStmt)
10357     return StmtError();
10358 
10359   if (!checkLastPrivateForMappedDirectives(Clauses))
10360     return StmtError();
10361 
10362   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10363   OMPLoopBasedDirective::HelperExprs B;
10364   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10365   // define the nested loops number.
10366   unsigned NestedLoopCount = checkOpenMPLoop(
10367       OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10368       AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10369   if (NestedLoopCount == 0)
10370     return StmtError();
10371 
10372   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10373     return StmtError();
10374 
10375   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
10376     return StmtError();
10377 
10378   SemaRef.setFunctionHasBranchProtectedScope();
10379   auto *SimdDirective = OMPSimdDirective::Create(
10380       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10381       DSAStack->getMappedDirective());
10382   return SimdDirective;
10383 }
10384 
ActOnOpenMPForDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10385 StmtResult SemaOpenMP::ActOnOpenMPForDirective(
10386     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10387     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10388   if (!AStmt)
10389     return StmtError();
10390 
10391   if (!checkLastPrivateForMappedDirectives(Clauses))
10392     return StmtError();
10393 
10394   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10395   OMPLoopBasedDirective::HelperExprs B;
10396   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10397   // define the nested loops number.
10398   unsigned NestedLoopCount = checkOpenMPLoop(
10399       OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10400       AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10401   if (NestedLoopCount == 0)
10402     return StmtError();
10403 
10404   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10405     return StmtError();
10406 
10407   auto *ForDirective = OMPForDirective::Create(
10408       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10409       DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion(),
10410       DSAStack->getMappedDirective());
10411   return ForDirective;
10412 }
10413 
ActOnOpenMPForSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10414 StmtResult SemaOpenMP::ActOnOpenMPForSimdDirective(
10415     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10416     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10417   if (!AStmt)
10418     return StmtError();
10419 
10420   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10421   OMPLoopBasedDirective::HelperExprs B;
10422   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10423   // define the nested loops number.
10424   unsigned NestedLoopCount =
10425       checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10426                       getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
10427                       VarsWithImplicitDSA, B);
10428   if (NestedLoopCount == 0)
10429     return StmtError();
10430 
10431   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10432     return StmtError();
10433 
10434   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
10435     return StmtError();
10436 
10437   SemaRef.setFunctionHasBranchProtectedScope();
10438   return OMPForSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
10439                                      NestedLoopCount, Clauses, AStmt, B);
10440 }
10441 
checkSectionsDirective(Sema & SemaRef,OpenMPDirectiveKind DKind,Stmt * AStmt,DSAStackTy * Stack)10442 static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind,
10443                                    Stmt *AStmt, DSAStackTy *Stack) {
10444   if (!AStmt)
10445     return true;
10446 
10447   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10448   auto BaseStmt = AStmt;
10449   while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10450     BaseStmt = CS->getCapturedStmt();
10451   if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10452     auto S = C->children();
10453     if (S.begin() == S.end())
10454       return true;
10455     // All associated statements must be '#pragma omp section' except for
10456     // the first one.
10457     for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10458       if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10459         if (SectionStmt)
10460           SemaRef.Diag(SectionStmt->getBeginLoc(),
10461                        diag::err_omp_sections_substmt_not_section)
10462               << getOpenMPDirectiveName(DKind);
10463         return true;
10464       }
10465       cast<OMPSectionDirective>(SectionStmt)
10466           ->setHasCancel(Stack->isCancelRegion());
10467     }
10468   } else {
10469     SemaRef.Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10470         << getOpenMPDirectiveName(DKind);
10471     return true;
10472   }
10473   return false;
10474 }
10475 
10476 StmtResult
ActOnOpenMPSectionsDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10477 SemaOpenMP::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
10478                                          Stmt *AStmt, SourceLocation StartLoc,
10479                                          SourceLocation EndLoc) {
10480   if (checkSectionsDirective(SemaRef, OMPD_sections, AStmt, DSAStack))
10481     return StmtError();
10482 
10483   SemaRef.setFunctionHasBranchProtectedScope();
10484 
10485   return OMPSectionsDirective::Create(
10486       getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10487       DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10488 }
10489 
ActOnOpenMPSectionDirective(Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10490 StmtResult SemaOpenMP::ActOnOpenMPSectionDirective(Stmt *AStmt,
10491                                                    SourceLocation StartLoc,
10492                                                    SourceLocation EndLoc) {
10493   if (!AStmt)
10494     return StmtError();
10495 
10496   SemaRef.setFunctionHasBranchProtectedScope();
10497   DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10498 
10499   return OMPSectionDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt,
10500                                      DSAStack->isCancelRegion());
10501 }
10502 
getDirectCallExpr(Expr * E)10503 static Expr *getDirectCallExpr(Expr *E) {
10504   E = E->IgnoreParenCasts()->IgnoreImplicit();
10505   if (auto *CE = dyn_cast<CallExpr>(E))
10506     if (CE->getDirectCallee())
10507       return E;
10508   return nullptr;
10509 }
10510 
10511 StmtResult
ActOnOpenMPDispatchDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10512 SemaOpenMP::ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses,
10513                                          Stmt *AStmt, SourceLocation StartLoc,
10514                                          SourceLocation EndLoc) {
10515   if (!AStmt)
10516     return StmtError();
10517 
10518   Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10519 
10520   // 5.1 OpenMP
10521   // expression-stmt : an expression statement with one of the following forms:
10522   //   expression = target-call ( [expression-list] );
10523   //   target-call ( [expression-list] );
10524 
10525   SourceLocation TargetCallLoc;
10526 
10527   if (!SemaRef.CurContext->isDependentContext()) {
10528     Expr *TargetCall = nullptr;
10529 
10530     auto *E = dyn_cast<Expr>(S);
10531     if (!E) {
10532       Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10533       return StmtError();
10534     }
10535 
10536     E = E->IgnoreParenCasts()->IgnoreImplicit();
10537 
10538     if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10539       if (BO->getOpcode() == BO_Assign)
10540         TargetCall = getDirectCallExpr(BO->getRHS());
10541     } else {
10542       if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10543         if (COCE->getOperator() == OO_Equal)
10544           TargetCall = getDirectCallExpr(COCE->getArg(1));
10545       if (!TargetCall)
10546         TargetCall = getDirectCallExpr(E);
10547     }
10548     if (!TargetCall) {
10549       Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10550       return StmtError();
10551     }
10552     TargetCallLoc = TargetCall->getExprLoc();
10553   }
10554 
10555   SemaRef.setFunctionHasBranchProtectedScope();
10556 
10557   return OMPDispatchDirective::Create(getASTContext(), StartLoc, EndLoc,
10558                                       Clauses, AStmt, TargetCallLoc);
10559 }
10560 
checkGenericLoopLastprivate(Sema & S,ArrayRef<OMPClause * > Clauses,OpenMPDirectiveKind K,DSAStackTy * Stack)10561 static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses,
10562                                         OpenMPDirectiveKind K,
10563                                         DSAStackTy *Stack) {
10564   bool ErrorFound = false;
10565   for (OMPClause *C : Clauses) {
10566     if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10567       for (Expr *RefExpr : LPC->varlists()) {
10568         SourceLocation ELoc;
10569         SourceRange ERange;
10570         Expr *SimpleRefExpr = RefExpr;
10571         auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10572         if (ValueDecl *D = Res.first) {
10573           auto &&Info = Stack->isLoopControlVariable(D);
10574           if (!Info.first) {
10575             S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10576                 << getOpenMPDirectiveName(K);
10577             ErrorFound = true;
10578           }
10579         }
10580       }
10581     }
10582   }
10583   return ErrorFound;
10584 }
10585 
ActOnOpenMPGenericLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10586 StmtResult SemaOpenMP::ActOnOpenMPGenericLoopDirective(
10587     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10588     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10589   if (!AStmt)
10590     return StmtError();
10591 
10592   // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10593   // A list item may not appear in a lastprivate clause unless it is the
10594   // loop iteration variable of a loop that is associated with the construct.
10595   if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack))
10596     return StmtError();
10597 
10598   setBranchProtectedScope(SemaRef, OMPD_loop, AStmt);
10599 
10600   OMPLoopDirective::HelperExprs B;
10601   // In presence of clause 'collapse', it will define the nested loops number.
10602   unsigned NestedLoopCount = checkOpenMPLoop(
10603       OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10604       AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10605   if (NestedLoopCount == 0)
10606     return StmtError();
10607 
10608   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10609          "omp loop exprs were not built");
10610 
10611   return OMPGenericLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
10612                                          NestedLoopCount, Clauses, AStmt, B);
10613 }
10614 
ActOnOpenMPTeamsGenericLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10615 StmtResult SemaOpenMP::ActOnOpenMPTeamsGenericLoopDirective(
10616     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10617     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10618   if (!AStmt)
10619     return StmtError();
10620 
10621   // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10622   // A list item may not appear in a lastprivate clause unless it is the
10623   // loop iteration variable of a loop that is associated with the construct.
10624   if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack))
10625     return StmtError();
10626 
10627   CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_teams_loop, AStmt);
10628 
10629   OMPLoopDirective::HelperExprs B;
10630   // In presence of clause 'collapse', it will define the nested loops number.
10631   unsigned NestedLoopCount =
10632       checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10633                       /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10634                       VarsWithImplicitDSA, B);
10635   if (NestedLoopCount == 0)
10636     return StmtError();
10637 
10638   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10639          "omp loop exprs were not built");
10640 
10641   DSAStack->setParentTeamsRegionLoc(StartLoc);
10642 
10643   return OMPTeamsGenericLoopDirective::Create(
10644       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10645 }
10646 
ActOnOpenMPTargetTeamsGenericLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10647 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsGenericLoopDirective(
10648     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10649     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10650   if (!AStmt)
10651     return StmtError();
10652 
10653   // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10654   // A list item may not appear in a lastprivate clause unless it is the
10655   // loop iteration variable of a loop that is associated with the construct.
10656   if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop,
10657                                   DSAStack))
10658     return StmtError();
10659 
10660   CapturedStmt *CS =
10661       setBranchProtectedScope(SemaRef, OMPD_target_teams_loop, AStmt);
10662 
10663   OMPLoopDirective::HelperExprs B;
10664   // In presence of clause 'collapse', it will define the nested loops number.
10665   unsigned NestedLoopCount =
10666       checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10667                       /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10668                       VarsWithImplicitDSA, B);
10669   if (NestedLoopCount == 0)
10670     return StmtError();
10671 
10672   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10673          "omp loop exprs were not built");
10674 
10675   return OMPTargetTeamsGenericLoopDirective::Create(
10676       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10677       teamsLoopCanBeParallelFor(AStmt, SemaRef));
10678 }
10679 
ActOnOpenMPParallelGenericLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10680 StmtResult SemaOpenMP::ActOnOpenMPParallelGenericLoopDirective(
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_parallel_loop,
10690                                   DSAStack))
10691     return StmtError();
10692 
10693   CapturedStmt *CS =
10694       setBranchProtectedScope(SemaRef, OMPD_parallel_loop, AStmt);
10695 
10696   OMPLoopDirective::HelperExprs B;
10697   // In presence of clause 'collapse', it will define the nested loops number.
10698   unsigned NestedLoopCount =
10699       checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
10700                       /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10701                       VarsWithImplicitDSA, B);
10702   if (NestedLoopCount == 0)
10703     return StmtError();
10704 
10705   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10706          "omp loop exprs were not built");
10707 
10708   return OMPParallelGenericLoopDirective::Create(
10709       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10710 }
10711 
ActOnOpenMPTargetParallelGenericLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10712 StmtResult SemaOpenMP::ActOnOpenMPTargetParallelGenericLoopDirective(
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_parallel_loop,
10722                                   DSAStack))
10723     return StmtError();
10724 
10725   CapturedStmt *CS =
10726       setBranchProtectedScope(SemaRef, OMPD_target_parallel_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_parallel_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 OMPTargetParallelGenericLoopDirective::Create(
10741       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10742 }
10743 
ActOnOpenMPSingleDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10744 StmtResult SemaOpenMP::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
10745                                                   Stmt *AStmt,
10746                                                   SourceLocation StartLoc,
10747                                                   SourceLocation EndLoc) {
10748   if (!AStmt)
10749     return StmtError();
10750 
10751   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10752 
10753   SemaRef.setFunctionHasBranchProtectedScope();
10754 
10755   // OpenMP [2.7.3, single Construct, Restrictions]
10756   // The copyprivate clause must not be used with the nowait clause.
10757   const OMPClause *Nowait = nullptr;
10758   const OMPClause *Copyprivate = nullptr;
10759   for (const OMPClause *Clause : Clauses) {
10760     if (Clause->getClauseKind() == OMPC_nowait)
10761       Nowait = Clause;
10762     else if (Clause->getClauseKind() == OMPC_copyprivate)
10763       Copyprivate = Clause;
10764     if (Copyprivate && Nowait) {
10765       Diag(Copyprivate->getBeginLoc(),
10766            diag::err_omp_single_copyprivate_with_nowait);
10767       Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
10768       return StmtError();
10769     }
10770   }
10771 
10772   return OMPSingleDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
10773                                     AStmt);
10774 }
10775 
ActOnOpenMPMasterDirective(Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10776 StmtResult SemaOpenMP::ActOnOpenMPMasterDirective(Stmt *AStmt,
10777                                                   SourceLocation StartLoc,
10778                                                   SourceLocation EndLoc) {
10779   if (!AStmt)
10780     return StmtError();
10781 
10782   SemaRef.setFunctionHasBranchProtectedScope();
10783 
10784   return OMPMasterDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt);
10785 }
10786 
ActOnOpenMPMaskedDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10787 StmtResult SemaOpenMP::ActOnOpenMPMaskedDirective(ArrayRef<OMPClause *> Clauses,
10788                                                   Stmt *AStmt,
10789                                                   SourceLocation StartLoc,
10790                                                   SourceLocation EndLoc) {
10791   if (!AStmt)
10792     return StmtError();
10793 
10794   SemaRef.setFunctionHasBranchProtectedScope();
10795 
10796   return OMPMaskedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
10797                                     AStmt);
10798 }
10799 
ActOnOpenMPCriticalDirective(const DeclarationNameInfo & DirName,ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10800 StmtResult SemaOpenMP::ActOnOpenMPCriticalDirective(
10801     const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
10802     Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
10803   if (!AStmt)
10804     return StmtError();
10805 
10806   bool ErrorFound = false;
10807   llvm::APSInt Hint;
10808   SourceLocation HintLoc;
10809   bool DependentHint = false;
10810   for (const OMPClause *C : Clauses) {
10811     if (C->getClauseKind() == OMPC_hint) {
10812       if (!DirName.getName()) {
10813         Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
10814         ErrorFound = true;
10815       }
10816       Expr *E = cast<OMPHintClause>(C)->getHint();
10817       if (E->isTypeDependent() || E->isValueDependent() ||
10818           E->isInstantiationDependent()) {
10819         DependentHint = true;
10820       } else {
10821         Hint = E->EvaluateKnownConstInt(getASTContext());
10822         HintLoc = C->getBeginLoc();
10823       }
10824     }
10825   }
10826   if (ErrorFound)
10827     return StmtError();
10828   const auto Pair = DSAStack->getCriticalWithHint(DirName);
10829   if (Pair.first && DirName.getName() && !DependentHint) {
10830     if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
10831       Diag(StartLoc, diag::err_omp_critical_with_hint);
10832       if (HintLoc.isValid())
10833         Diag(HintLoc, diag::note_omp_critical_hint_here)
10834             << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
10835       else
10836         Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
10837       if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
10838         Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
10839             << 1
10840             << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()),
10841                         /*Radix=*/10, /*Signed=*/false);
10842       } else {
10843         Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
10844       }
10845     }
10846   }
10847 
10848   SemaRef.setFunctionHasBranchProtectedScope();
10849 
10850   auto *Dir = OMPCriticalDirective::Create(getASTContext(), DirName, StartLoc,
10851                                            EndLoc, Clauses, AStmt);
10852   if (!Pair.first && DirName.getName() && !DependentHint)
10853     DSAStack->addCriticalWithHint(Dir, Hint);
10854   return Dir;
10855 }
10856 
ActOnOpenMPParallelForDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10857 StmtResult SemaOpenMP::ActOnOpenMPParallelForDirective(
10858     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10859     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10860   if (!AStmt)
10861     return StmtError();
10862 
10863   setBranchProtectedScope(SemaRef, OMPD_parallel_for, AStmt);
10864 
10865   OMPLoopBasedDirective::HelperExprs B;
10866   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10867   // define the nested loops number.
10868   unsigned NestedLoopCount =
10869       checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
10870                       getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
10871                       VarsWithImplicitDSA, B);
10872   if (NestedLoopCount == 0)
10873     return StmtError();
10874 
10875   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10876     return StmtError();
10877 
10878   return OMPParallelForDirective::Create(
10879       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10880       DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10881 }
10882 
ActOnOpenMPParallelForSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10883 StmtResult SemaOpenMP::ActOnOpenMPParallelForSimdDirective(
10884     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10885     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10886   if (!AStmt)
10887     return StmtError();
10888 
10889   setBranchProtectedScope(SemaRef, OMPD_parallel_for_simd, AStmt);
10890 
10891   OMPLoopBasedDirective::HelperExprs B;
10892   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10893   // define the nested loops number.
10894   unsigned NestedLoopCount =
10895       checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
10896                       getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
10897                       VarsWithImplicitDSA, B);
10898   if (NestedLoopCount == 0)
10899     return StmtError();
10900 
10901   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10902     return StmtError();
10903 
10904   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
10905     return StmtError();
10906 
10907   return OMPParallelForSimdDirective::Create(
10908       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10909 }
10910 
ActOnOpenMPParallelMasterDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10911 StmtResult SemaOpenMP::ActOnOpenMPParallelMasterDirective(
10912     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10913     SourceLocation EndLoc) {
10914   if (!AStmt)
10915     return StmtError();
10916 
10917   setBranchProtectedScope(SemaRef, OMPD_parallel_master, AStmt);
10918 
10919   return OMPParallelMasterDirective::Create(
10920       getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10921       DSAStack->getTaskgroupReductionRef());
10922 }
10923 
ActOnOpenMPParallelMaskedDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10924 StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedDirective(
10925     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10926     SourceLocation EndLoc) {
10927   if (!AStmt)
10928     return StmtError();
10929 
10930   setBranchProtectedScope(SemaRef, OMPD_parallel_masked, AStmt);
10931 
10932   return OMPParallelMaskedDirective::Create(
10933       getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10934       DSAStack->getTaskgroupReductionRef());
10935 }
10936 
ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10937 StmtResult SemaOpenMP::ActOnOpenMPParallelSectionsDirective(
10938     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10939     SourceLocation EndLoc) {
10940   if (checkSectionsDirective(SemaRef, OMPD_parallel_sections, AStmt, DSAStack))
10941     return StmtError();
10942 
10943   SemaRef.setFunctionHasBranchProtectedScope();
10944 
10945   return OMPParallelSectionsDirective::Create(
10946       getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10947       DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10948 }
10949 
10950 /// Find and diagnose mutually exclusive clause kinds.
checkMutuallyExclusiveClauses(Sema & S,ArrayRef<OMPClause * > Clauses,ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses)10951 static bool checkMutuallyExclusiveClauses(
10952     Sema &S, ArrayRef<OMPClause *> Clauses,
10953     ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
10954   const OMPClause *PrevClause = nullptr;
10955   bool ErrorFound = false;
10956   for (const OMPClause *C : Clauses) {
10957     if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
10958       if (!PrevClause) {
10959         PrevClause = C;
10960       } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
10961         S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
10962             << getOpenMPClauseName(C->getClauseKind())
10963             << getOpenMPClauseName(PrevClause->getClauseKind());
10964         S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
10965             << getOpenMPClauseName(PrevClause->getClauseKind());
10966         ErrorFound = true;
10967       }
10968     }
10969   }
10970   return ErrorFound;
10971 }
10972 
ActOnOpenMPTaskDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10973 StmtResult SemaOpenMP::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
10974                                                 Stmt *AStmt,
10975                                                 SourceLocation StartLoc,
10976                                                 SourceLocation EndLoc) {
10977   if (!AStmt)
10978     return StmtError();
10979 
10980   // OpenMP 5.0, 2.10.1 task Construct
10981   // If a detach clause appears on the directive, then a mergeable clause cannot
10982   // appear on the same directive.
10983   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
10984                                     {OMPC_detach, OMPC_mergeable}))
10985     return StmtError();
10986 
10987   setBranchProtectedScope(SemaRef, OMPD_task, AStmt);
10988 
10989   return OMPTaskDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
10990                                   AStmt, DSAStack->isCancelRegion());
10991 }
10992 
ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,SourceLocation EndLoc)10993 StmtResult SemaOpenMP::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
10994                                                      SourceLocation EndLoc) {
10995   return OMPTaskyieldDirective::Create(getASTContext(), StartLoc, EndLoc);
10996 }
10997 
ActOnOpenMPBarrierDirective(SourceLocation StartLoc,SourceLocation EndLoc)10998 StmtResult SemaOpenMP::ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
10999                                                    SourceLocation EndLoc) {
11000   return OMPBarrierDirective::Create(getASTContext(), StartLoc, EndLoc);
11001 }
11002 
ActOnOpenMPErrorDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc,bool InExContext)11003 StmtResult SemaOpenMP::ActOnOpenMPErrorDirective(ArrayRef<OMPClause *> Clauses,
11004                                                  SourceLocation StartLoc,
11005                                                  SourceLocation EndLoc,
11006                                                  bool InExContext) {
11007   const OMPAtClause *AtC =
11008       OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11009 
11010   if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11011     Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11012     return StmtError();
11013   }
11014 
11015   const OMPSeverityClause *SeverityC =
11016       OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11017   const OMPMessageClause *MessageC =
11018       OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11019   Expr *ME = MessageC ? MessageC->getMessageString() : nullptr;
11020 
11021   if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11022     if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11023       Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11024           << (ME ? cast<StringLiteral>(ME)->getString() : "WARNING");
11025     else
11026       Diag(StartLoc, diag::err_diagnose_if_succeeded)
11027           << (ME ? cast<StringLiteral>(ME)->getString() : "ERROR");
11028     if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11029       return StmtError();
11030   }
11031   return OMPErrorDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11032 }
11033 
11034 StmtResult
ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc)11035 SemaOpenMP::ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause *> Clauses,
11036                                          SourceLocation StartLoc,
11037                                          SourceLocation EndLoc) {
11038   const OMPNowaitClause *NowaitC =
11039       OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11040   bool HasDependC =
11041       !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11042            .empty();
11043   if (NowaitC && !HasDependC) {
11044     Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11045     return StmtError();
11046   }
11047 
11048   return OMPTaskwaitDirective::Create(getASTContext(), StartLoc, EndLoc,
11049                                       Clauses);
11050 }
11051 
11052 StmtResult
ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)11053 SemaOpenMP::ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
11054                                           Stmt *AStmt, SourceLocation StartLoc,
11055                                           SourceLocation EndLoc) {
11056   if (!AStmt)
11057     return StmtError();
11058 
11059   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11060 
11061   SemaRef.setFunctionHasBranchProtectedScope();
11062 
11063   return OMPTaskgroupDirective::Create(getASTContext(), StartLoc, EndLoc,
11064                                        Clauses, AStmt,
11065                                        DSAStack->getTaskgroupReductionRef());
11066 }
11067 
ActOnOpenMPFlushDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc)11068 StmtResult SemaOpenMP::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
11069                                                  SourceLocation StartLoc,
11070                                                  SourceLocation EndLoc) {
11071   OMPFlushClause *FC = nullptr;
11072   OMPClause *OrderClause = nullptr;
11073   for (OMPClause *C : Clauses) {
11074     if (C->getClauseKind() == OMPC_flush)
11075       FC = cast<OMPFlushClause>(C);
11076     else
11077       OrderClause = C;
11078   }
11079   OpenMPClauseKind MemOrderKind = OMPC_unknown;
11080   SourceLocation MemOrderLoc;
11081   for (const OMPClause *C : Clauses) {
11082     if (C->getClauseKind() == OMPC_acq_rel ||
11083         C->getClauseKind() == OMPC_acquire ||
11084         C->getClauseKind() == OMPC_release) {
11085       if (MemOrderKind != OMPC_unknown) {
11086         Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11087             << getOpenMPDirectiveName(OMPD_flush) << 1
11088             << SourceRange(C->getBeginLoc(), C->getEndLoc());
11089         Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11090             << getOpenMPClauseName(MemOrderKind);
11091       } else {
11092         MemOrderKind = C->getClauseKind();
11093         MemOrderLoc = C->getBeginLoc();
11094       }
11095     }
11096   }
11097   if (FC && OrderClause) {
11098     Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11099         << getOpenMPClauseName(OrderClause->getClauseKind());
11100     Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11101         << getOpenMPClauseName(OrderClause->getClauseKind());
11102     return StmtError();
11103   }
11104   return OMPFlushDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11105 }
11106 
ActOnOpenMPDepobjDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc)11107 StmtResult SemaOpenMP::ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses,
11108                                                   SourceLocation StartLoc,
11109                                                   SourceLocation EndLoc) {
11110   if (Clauses.empty()) {
11111     Diag(StartLoc, diag::err_omp_depobj_expected);
11112     return StmtError();
11113   } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11114     Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11115     return StmtError();
11116   }
11117   // Only depobj expression and another single clause is allowed.
11118   if (Clauses.size() > 2) {
11119     Diag(Clauses[2]->getBeginLoc(),
11120          diag::err_omp_depobj_single_clause_expected);
11121     return StmtError();
11122   } else if (Clauses.size() < 1) {
11123     Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11124     return StmtError();
11125   }
11126   return OMPDepobjDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11127 }
11128 
ActOnOpenMPScanDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc)11129 StmtResult SemaOpenMP::ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses,
11130                                                 SourceLocation StartLoc,
11131                                                 SourceLocation EndLoc) {
11132   // Check that exactly one clause is specified.
11133   if (Clauses.size() != 1) {
11134     Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11135          diag::err_omp_scan_single_clause_expected);
11136     return StmtError();
11137   }
11138   // Check that scan directive is used in the scope of the OpenMP loop body.
11139   if (Scope *S = DSAStack->getCurScope()) {
11140     Scope *ParentS = S->getParent();
11141     if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11142         !ParentS->getBreakParent()->isOpenMPLoopScope())
11143       return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11144                        << getOpenMPDirectiveName(OMPD_scan) << 5);
11145   }
11146   // Check that only one instance of scan directives is used in the same outer
11147   // region.
11148   if (DSAStack->doesParentHasScanDirective()) {
11149     Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11150     Diag(DSAStack->getParentScanDirectiveLoc(),
11151          diag::note_omp_previous_directive)
11152         << "scan";
11153     return StmtError();
11154   }
11155   DSAStack->setParentHasScanDirective(StartLoc);
11156   return OMPScanDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11157 }
11158 
11159 StmtResult
ActOnOpenMPOrderedDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)11160 SemaOpenMP::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
11161                                         Stmt *AStmt, SourceLocation StartLoc,
11162                                         SourceLocation EndLoc) {
11163   const OMPClause *DependFound = nullptr;
11164   const OMPClause *DependSourceClause = nullptr;
11165   const OMPClause *DependSinkClause = nullptr;
11166   const OMPClause *DoacrossFound = nullptr;
11167   const OMPClause *DoacrossSourceClause = nullptr;
11168   const OMPClause *DoacrossSinkClause = nullptr;
11169   bool ErrorFound = false;
11170   const OMPThreadsClause *TC = nullptr;
11171   const OMPSIMDClause *SC = nullptr;
11172   for (const OMPClause *C : Clauses) {
11173     auto DOC = dyn_cast<OMPDoacrossClause>(C);
11174     auto DC = dyn_cast<OMPDependClause>(C);
11175     if (DC || DOC) {
11176       DependFound = DC ? C : nullptr;
11177       DoacrossFound = DOC ? C : nullptr;
11178       OMPDoacrossKind ODK;
11179       if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11180           (DOC && (ODK.isSource(DOC)))) {
11181         if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11182           Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11183               << getOpenMPDirectiveName(OMPD_ordered)
11184               << getOpenMPClauseName(DC ? OMPC_depend : OMPC_doacross) << 2;
11185           ErrorFound = true;
11186         } else {
11187           if (DC)
11188             DependSourceClause = C;
11189           else
11190             DoacrossSourceClause = C;
11191         }
11192         if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11193           Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11194               << (DC ? "depend" : "doacross") << 0;
11195           ErrorFound = true;
11196         }
11197       } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11198                  (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11199         if (DependSourceClause || DoacrossSourceClause) {
11200           Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11201               << (DC ? "depend" : "doacross") << 1;
11202           ErrorFound = true;
11203         }
11204         if (DC)
11205           DependSinkClause = C;
11206         else
11207           DoacrossSinkClause = C;
11208       }
11209     } else if (C->getClauseKind() == OMPC_threads) {
11210       TC = cast<OMPThreadsClause>(C);
11211     } else if (C->getClauseKind() == OMPC_simd) {
11212       SC = cast<OMPSIMDClause>(C);
11213     }
11214   }
11215   if (!ErrorFound && !SC &&
11216       isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11217     // OpenMP [2.8.1,simd Construct, Restrictions]
11218     // An ordered construct with the simd clause is the only OpenMP construct
11219     // that can appear in the simd region.
11220     Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11221         << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11222     ErrorFound = true;
11223   } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11224     SourceLocation Loc =
11225         DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11226     Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11227         << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross)
11228         << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
11229     ErrorFound = true;
11230   } else if ((DependFound || DoacrossFound) &&
11231              !DSAStack->getParentOrderedRegionParam().first) {
11232     SourceLocation Loc =
11233         DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11234     Diag(Loc, diag::err_omp_ordered_directive_without_param)
11235         << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross);
11236     ErrorFound = true;
11237   } else if (TC || Clauses.empty()) {
11238     if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11239       SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11240       Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11241           << (TC != nullptr);
11242       Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11243       ErrorFound = true;
11244     }
11245   }
11246   if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11247     return StmtError();
11248 
11249   // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11250   // During execution of an iteration of a worksharing-loop or a loop nest
11251   // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11252   // must not execute more than one ordered region corresponding to an ordered
11253   // construct without a depend clause.
11254   if (!DependFound && !DoacrossFound) {
11255     if (DSAStack->doesParentHasOrderedDirective()) {
11256       Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11257       Diag(DSAStack->getParentOrderedDirectiveLoc(),
11258            diag::note_omp_previous_directive)
11259           << "ordered";
11260       return StmtError();
11261     }
11262     DSAStack->setParentHasOrderedDirective(StartLoc);
11263   }
11264 
11265   if (AStmt) {
11266     assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11267 
11268     SemaRef.setFunctionHasBranchProtectedScope();
11269   }
11270 
11271   return OMPOrderedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11272                                      AStmt);
11273 }
11274 
11275 namespace {
11276 /// Helper class for checking expression in 'omp atomic [update]'
11277 /// construct.
11278 class OpenMPAtomicUpdateChecker {
11279   /// Error results for atomic update expressions.
11280   enum ExprAnalysisErrorCode {
11281     /// A statement is not an expression statement.
11282     NotAnExpression,
11283     /// Expression is not builtin binary or unary operation.
11284     NotABinaryOrUnaryExpression,
11285     /// Unary operation is not post-/pre- increment/decrement operation.
11286     NotAnUnaryIncDecExpression,
11287     /// An expression is not of scalar type.
11288     NotAScalarType,
11289     /// A binary operation is not an assignment operation.
11290     NotAnAssignmentOp,
11291     /// RHS part of the binary operation is not a binary expression.
11292     NotABinaryExpression,
11293     /// RHS part is not additive/multiplicative/shift/bitwise binary
11294     /// expression.
11295     NotABinaryOperator,
11296     /// RHS binary operation does not have reference to the updated LHS
11297     /// part.
11298     NotAnUpdateExpression,
11299     /// An expression contains semantical error not related to
11300     /// 'omp atomic [update]'
11301     NotAValidExpression,
11302     /// No errors is found.
11303     NoError
11304   };
11305   /// Reference to Sema.
11306   Sema &SemaRef;
11307   /// A location for note diagnostics (when error is found).
11308   SourceLocation NoteLoc;
11309   /// 'x' lvalue part of the source atomic expression.
11310   Expr *X;
11311   /// 'expr' rvalue part of the source atomic expression.
11312   Expr *E;
11313   /// Helper expression of the form
11314   /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11315   /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11316   Expr *UpdateExpr;
11317   /// Is 'x' a LHS in a RHS part of full update expression. It is
11318   /// important for non-associative operations.
11319   bool IsXLHSInRHSPart;
11320   BinaryOperatorKind Op;
11321   SourceLocation OpLoc;
11322   /// true if the source expression is a postfix unary operation, false
11323   /// if it is a prefix unary operation.
11324   bool IsPostfixUpdate;
11325 
11326 public:
OpenMPAtomicUpdateChecker(Sema & SemaRef)11327   OpenMPAtomicUpdateChecker(Sema &SemaRef)
11328       : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11329         IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11330   /// Check specified statement that it is suitable for 'atomic update'
11331   /// constructs and extract 'x', 'expr' and Operation from the original
11332   /// expression. If DiagId and NoteId == 0, then only check is performed
11333   /// without error notification.
11334   /// \param DiagId Diagnostic which should be emitted if error is found.
11335   /// \param NoteId Diagnostic note for the main error message.
11336   /// \return true if statement is not an update expression, false otherwise.
11337   bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11338   /// Return the 'x' lvalue part of the source atomic expression.
getX() const11339   Expr *getX() const { return X; }
11340   /// Return the 'expr' rvalue part of the source atomic expression.
getExpr() const11341   Expr *getExpr() const { return E; }
11342   /// Return the update expression used in calculation of the updated
11343   /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11344   /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
getUpdateExpr() const11345   Expr *getUpdateExpr() const { return UpdateExpr; }
11346   /// Return true if 'x' is LHS in RHS part of full update expression,
11347   /// false otherwise.
isXLHSInRHSPart() const11348   bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11349 
11350   /// true if the source expression is a postfix unary operation, false
11351   /// if it is a prefix unary operation.
isPostfixUpdate() const11352   bool isPostfixUpdate() const { return IsPostfixUpdate; }
11353 
11354 private:
11355   bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11356                             unsigned NoteId = 0);
11357 };
11358 
checkBinaryOperation(BinaryOperator * AtomicBinOp,unsigned DiagId,unsigned NoteId)11359 bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11360     BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11361   ExprAnalysisErrorCode ErrorFound = NoError;
11362   SourceLocation ErrorLoc, NoteLoc;
11363   SourceRange ErrorRange, NoteRange;
11364   // Allowed constructs are:
11365   //  x = x binop expr;
11366   //  x = expr binop x;
11367   if (AtomicBinOp->getOpcode() == BO_Assign) {
11368     X = AtomicBinOp->getLHS();
11369     if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11370             AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11371       if (AtomicInnerBinOp->isMultiplicativeOp() ||
11372           AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11373           AtomicInnerBinOp->isBitwiseOp()) {
11374         Op = AtomicInnerBinOp->getOpcode();
11375         OpLoc = AtomicInnerBinOp->getOperatorLoc();
11376         Expr *LHS = AtomicInnerBinOp->getLHS();
11377         Expr *RHS = AtomicInnerBinOp->getRHS();
11378         llvm::FoldingSetNodeID XId, LHSId, RHSId;
11379         X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11380                                           /*Canonical=*/true);
11381         LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11382                                             /*Canonical=*/true);
11383         RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11384                                             /*Canonical=*/true);
11385         if (XId == LHSId) {
11386           E = RHS;
11387           IsXLHSInRHSPart = true;
11388         } else if (XId == RHSId) {
11389           E = LHS;
11390           IsXLHSInRHSPart = false;
11391         } else {
11392           ErrorLoc = AtomicInnerBinOp->getExprLoc();
11393           ErrorRange = AtomicInnerBinOp->getSourceRange();
11394           NoteLoc = X->getExprLoc();
11395           NoteRange = X->getSourceRange();
11396           ErrorFound = NotAnUpdateExpression;
11397         }
11398       } else {
11399         ErrorLoc = AtomicInnerBinOp->getExprLoc();
11400         ErrorRange = AtomicInnerBinOp->getSourceRange();
11401         NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11402         NoteRange = SourceRange(NoteLoc, NoteLoc);
11403         ErrorFound = NotABinaryOperator;
11404       }
11405     } else {
11406       NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11407       NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11408       ErrorFound = NotABinaryExpression;
11409     }
11410   } else {
11411     ErrorLoc = AtomicBinOp->getExprLoc();
11412     ErrorRange = AtomicBinOp->getSourceRange();
11413     NoteLoc = AtomicBinOp->getOperatorLoc();
11414     NoteRange = SourceRange(NoteLoc, NoteLoc);
11415     ErrorFound = NotAnAssignmentOp;
11416   }
11417   if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11418     SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11419     SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11420     return true;
11421   }
11422   if (SemaRef.CurContext->isDependentContext())
11423     E = X = UpdateExpr = nullptr;
11424   return ErrorFound != NoError;
11425 }
11426 
checkStatement(Stmt * S,unsigned DiagId,unsigned NoteId)11427 bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11428                                                unsigned NoteId) {
11429   ExprAnalysisErrorCode ErrorFound = NoError;
11430   SourceLocation ErrorLoc, NoteLoc;
11431   SourceRange ErrorRange, NoteRange;
11432   // Allowed constructs are:
11433   //  x++;
11434   //  x--;
11435   //  ++x;
11436   //  --x;
11437   //  x binop= expr;
11438   //  x = x binop expr;
11439   //  x = expr binop x;
11440   if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11441     AtomicBody = AtomicBody->IgnoreParenImpCasts();
11442     if (AtomicBody->getType()->isScalarType() ||
11443         AtomicBody->isInstantiationDependent()) {
11444       if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11445               AtomicBody->IgnoreParenImpCasts())) {
11446         // Check for Compound Assignment Operation
11447         Op = BinaryOperator::getOpForCompoundAssignment(
11448             AtomicCompAssignOp->getOpcode());
11449         OpLoc = AtomicCompAssignOp->getOperatorLoc();
11450         E = AtomicCompAssignOp->getRHS();
11451         X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11452         IsXLHSInRHSPart = true;
11453       } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11454                      AtomicBody->IgnoreParenImpCasts())) {
11455         // Check for Binary Operation
11456         if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11457           return true;
11458       } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11459                      AtomicBody->IgnoreParenImpCasts())) {
11460         // Check for Unary Operation
11461         if (AtomicUnaryOp->isIncrementDecrementOp()) {
11462           IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11463           Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11464           OpLoc = AtomicUnaryOp->getOperatorLoc();
11465           X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11466           E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11467           IsXLHSInRHSPart = true;
11468         } else {
11469           ErrorFound = NotAnUnaryIncDecExpression;
11470           ErrorLoc = AtomicUnaryOp->getExprLoc();
11471           ErrorRange = AtomicUnaryOp->getSourceRange();
11472           NoteLoc = AtomicUnaryOp->getOperatorLoc();
11473           NoteRange = SourceRange(NoteLoc, NoteLoc);
11474         }
11475       } else if (!AtomicBody->isInstantiationDependent()) {
11476         ErrorFound = NotABinaryOrUnaryExpression;
11477         NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11478         NoteRange = ErrorRange = AtomicBody->getSourceRange();
11479       } else if (AtomicBody->containsErrors()) {
11480         ErrorFound = NotAValidExpression;
11481         NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11482         NoteRange = ErrorRange = AtomicBody->getSourceRange();
11483       }
11484     } else {
11485       ErrorFound = NotAScalarType;
11486       NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11487       NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11488     }
11489   } else {
11490     ErrorFound = NotAnExpression;
11491     NoteLoc = ErrorLoc = S->getBeginLoc();
11492     NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11493   }
11494   if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11495     SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11496     SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11497     return true;
11498   }
11499   if (SemaRef.CurContext->isDependentContext())
11500     E = X = UpdateExpr = nullptr;
11501   if (ErrorFound == NoError && E && X) {
11502     // Build an update expression of form 'OpaqueValueExpr(x) binop
11503     // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11504     // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11505     auto *OVEX = new (SemaRef.getASTContext())
11506         OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11507     auto *OVEExpr = new (SemaRef.getASTContext())
11508         OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_PRValue);
11509     ExprResult Update =
11510         SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11511                                    IsXLHSInRHSPart ? OVEExpr : OVEX);
11512     if (Update.isInvalid())
11513       return true;
11514     Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11515                                                Sema::AA_Casting);
11516     if (Update.isInvalid())
11517       return true;
11518     UpdateExpr = Update.get();
11519   }
11520   return ErrorFound != NoError;
11521 }
11522 
11523 /// Get the node id of the fixed point of an expression \a S.
getNodeId(ASTContext & Context,const Expr * S)11524 llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11525   llvm::FoldingSetNodeID Id;
11526   S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11527   return Id;
11528 }
11529 
11530 /// Check if two expressions are same.
checkIfTwoExprsAreSame(ASTContext & Context,const Expr * LHS,const Expr * RHS)11531 bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11532                             const Expr *RHS) {
11533   return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11534 }
11535 
11536 class OpenMPAtomicCompareChecker {
11537 public:
11538   /// All kinds of errors that can occur in `atomic compare`
11539   enum ErrorTy {
11540     /// Empty compound statement.
11541     NoStmt = 0,
11542     /// More than one statement in a compound statement.
11543     MoreThanOneStmt,
11544     /// Not an assignment binary operator.
11545     NotAnAssignment,
11546     /// Not a conditional operator.
11547     NotCondOp,
11548     /// Wrong false expr. According to the spec, 'x' should be at the false
11549     /// expression of a conditional expression.
11550     WrongFalseExpr,
11551     /// The condition of a conditional expression is not a binary operator.
11552     NotABinaryOp,
11553     /// Invalid binary operator (not <, >, or ==).
11554     InvalidBinaryOp,
11555     /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11556     InvalidComparison,
11557     /// X is not a lvalue.
11558     XNotLValue,
11559     /// Not a scalar.
11560     NotScalar,
11561     /// Not an integer.
11562     NotInteger,
11563     /// 'else' statement is not expected.
11564     UnexpectedElse,
11565     /// Not an equality operator.
11566     NotEQ,
11567     /// Invalid assignment (not v == x).
11568     InvalidAssignment,
11569     /// Not if statement
11570     NotIfStmt,
11571     /// More than two statements in a compound statement.
11572     MoreThanTwoStmts,
11573     /// Not a compound statement.
11574     NotCompoundStmt,
11575     /// No else statement.
11576     NoElse,
11577     /// Not 'if (r)'.
11578     InvalidCondition,
11579     /// No error.
11580     NoError,
11581   };
11582 
11583   struct ErrorInfoTy {
11584     ErrorTy Error;
11585     SourceLocation ErrorLoc;
11586     SourceRange ErrorRange;
11587     SourceLocation NoteLoc;
11588     SourceRange NoteRange;
11589   };
11590 
OpenMPAtomicCompareChecker(Sema & S)11591   OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11592 
11593   /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11594   bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11595 
getX() const11596   Expr *getX() const { return X; }
getE() const11597   Expr *getE() const { return E; }
getD() const11598   Expr *getD() const { return D; }
getCond() const11599   Expr *getCond() const { return C; }
isXBinopExpr() const11600   bool isXBinopExpr() const { return IsXBinopExpr; }
11601 
11602 protected:
11603   /// Reference to ASTContext
11604   ASTContext &ContextRef;
11605   /// 'x' lvalue part of the source atomic expression.
11606   Expr *X = nullptr;
11607   /// 'expr' or 'e' rvalue part of the source atomic expression.
11608   Expr *E = nullptr;
11609   /// 'd' rvalue part of the source atomic expression.
11610   Expr *D = nullptr;
11611   /// 'cond' part of the source atomic expression. It is in one of the following
11612   /// forms:
11613   /// expr ordop x
11614   /// x ordop expr
11615   /// x == e
11616   /// e == x
11617   Expr *C = nullptr;
11618   /// True if the cond expr is in the form of 'x ordop expr'.
11619   bool IsXBinopExpr = true;
11620 
11621   /// Check if it is a valid conditional update statement (cond-update-stmt).
11622   bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11623 
11624   /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11625   bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11626 
11627   /// Check if all captured values have right type.
11628   bool checkType(ErrorInfoTy &ErrorInfo) const;
11629 
CheckValue(const Expr * E,ErrorInfoTy & ErrorInfo,bool ShouldBeLValue,bool ShouldBeInteger=false)11630   static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11631                          bool ShouldBeLValue, bool ShouldBeInteger = false) {
11632     if (E->isInstantiationDependent())
11633       return true;
11634 
11635     if (ShouldBeLValue && !E->isLValue()) {
11636       ErrorInfo.Error = ErrorTy::XNotLValue;
11637       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11638       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11639       return false;
11640     }
11641 
11642     QualType QTy = E->getType();
11643     if (!QTy->isScalarType()) {
11644       ErrorInfo.Error = ErrorTy::NotScalar;
11645       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11646       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11647       return false;
11648     }
11649     if (ShouldBeInteger && !QTy->isIntegerType()) {
11650       ErrorInfo.Error = ErrorTy::NotInteger;
11651       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11652       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11653       return false;
11654     }
11655 
11656     return true;
11657   }
11658 };
11659 
checkCondUpdateStmt(IfStmt * S,ErrorInfoTy & ErrorInfo)11660 bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11661                                                      ErrorInfoTy &ErrorInfo) {
11662   auto *Then = S->getThen();
11663   if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11664     if (CS->body_empty()) {
11665       ErrorInfo.Error = ErrorTy::NoStmt;
11666       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11667       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11668       return false;
11669     }
11670     if (CS->size() > 1) {
11671       ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11672       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11673       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11674       return false;
11675     }
11676     Then = CS->body_front();
11677   }
11678 
11679   auto *BO = dyn_cast<BinaryOperator>(Then);
11680   if (!BO) {
11681     ErrorInfo.Error = ErrorTy::NotAnAssignment;
11682     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11683     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11684     return false;
11685   }
11686   if (BO->getOpcode() != BO_Assign) {
11687     ErrorInfo.Error = ErrorTy::NotAnAssignment;
11688     ErrorInfo.ErrorLoc = BO->getExprLoc();
11689     ErrorInfo.NoteLoc = BO->getOperatorLoc();
11690     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11691     return false;
11692   }
11693 
11694   X = BO->getLHS();
11695 
11696   auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11697   if (!Cond) {
11698     ErrorInfo.Error = ErrorTy::NotABinaryOp;
11699     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11700     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11701     return false;
11702   }
11703 
11704   switch (Cond->getOpcode()) {
11705   case BO_EQ: {
11706     C = Cond;
11707     D = BO->getRHS();
11708     if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11709       E = Cond->getRHS();
11710     } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11711       E = Cond->getLHS();
11712     } else {
11713       ErrorInfo.Error = ErrorTy::InvalidComparison;
11714       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11715       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11716       return false;
11717     }
11718     break;
11719   }
11720   case BO_LT:
11721   case BO_GT: {
11722     E = BO->getRHS();
11723     if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
11724         checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
11725       C = Cond;
11726     } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
11727                checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11728       C = Cond;
11729       IsXBinopExpr = false;
11730     } else {
11731       ErrorInfo.Error = ErrorTy::InvalidComparison;
11732       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11733       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11734       return false;
11735     }
11736     break;
11737   }
11738   default:
11739     ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11740     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11741     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11742     return false;
11743   }
11744 
11745   if (S->getElse()) {
11746     ErrorInfo.Error = ErrorTy::UnexpectedElse;
11747     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
11748     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
11749     return false;
11750   }
11751 
11752   return true;
11753 }
11754 
checkCondExprStmt(Stmt * S,ErrorInfoTy & ErrorInfo)11755 bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
11756                                                    ErrorInfoTy &ErrorInfo) {
11757   auto *BO = dyn_cast<BinaryOperator>(S);
11758   if (!BO) {
11759     ErrorInfo.Error = ErrorTy::NotAnAssignment;
11760     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11761     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11762     return false;
11763   }
11764   if (BO->getOpcode() != BO_Assign) {
11765     ErrorInfo.Error = ErrorTy::NotAnAssignment;
11766     ErrorInfo.ErrorLoc = BO->getExprLoc();
11767     ErrorInfo.NoteLoc = BO->getOperatorLoc();
11768     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11769     return false;
11770   }
11771 
11772   X = BO->getLHS();
11773 
11774   auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
11775   if (!CO) {
11776     ErrorInfo.Error = ErrorTy::NotCondOp;
11777     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
11778     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
11779     return false;
11780   }
11781 
11782   if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
11783     ErrorInfo.Error = ErrorTy::WrongFalseExpr;
11784     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
11785     ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11786         CO->getFalseExpr()->getSourceRange();
11787     return false;
11788   }
11789 
11790   auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
11791   if (!Cond) {
11792     ErrorInfo.Error = ErrorTy::NotABinaryOp;
11793     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11794     ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11795         CO->getCond()->getSourceRange();
11796     return false;
11797   }
11798 
11799   switch (Cond->getOpcode()) {
11800   case BO_EQ: {
11801     C = Cond;
11802     D = CO->getTrueExpr();
11803     if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11804       E = Cond->getRHS();
11805     } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11806       E = Cond->getLHS();
11807     } else {
11808       ErrorInfo.Error = ErrorTy::InvalidComparison;
11809       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11810       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11811       return false;
11812     }
11813     break;
11814   }
11815   case BO_LT:
11816   case BO_GT: {
11817     E = CO->getTrueExpr();
11818     if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
11819         checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
11820       C = Cond;
11821     } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
11822                checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11823       C = Cond;
11824       IsXBinopExpr = false;
11825     } else {
11826       ErrorInfo.Error = ErrorTy::InvalidComparison;
11827       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11828       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11829       return false;
11830     }
11831     break;
11832   }
11833   default:
11834     ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11835     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11836     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11837     return false;
11838   }
11839 
11840   return true;
11841 }
11842 
checkType(ErrorInfoTy & ErrorInfo) const11843 bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
11844   // 'x' and 'e' cannot be nullptr
11845   assert(X && E && "X and E cannot be nullptr");
11846 
11847   if (!CheckValue(X, ErrorInfo, true))
11848     return false;
11849 
11850   if (!CheckValue(E, ErrorInfo, false))
11851     return false;
11852 
11853   if (D && !CheckValue(D, ErrorInfo, false))
11854     return false;
11855 
11856   return true;
11857 }
11858 
checkStmt(Stmt * S,OpenMPAtomicCompareChecker::ErrorInfoTy & ErrorInfo)11859 bool OpenMPAtomicCompareChecker::checkStmt(
11860     Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
11861   auto *CS = dyn_cast<CompoundStmt>(S);
11862   if (CS) {
11863     if (CS->body_empty()) {
11864       ErrorInfo.Error = ErrorTy::NoStmt;
11865       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11866       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11867       return false;
11868     }
11869 
11870     if (CS->size() != 1) {
11871       ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11872       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11873       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11874       return false;
11875     }
11876     S = CS->body_front();
11877   }
11878 
11879   auto Res = false;
11880 
11881   if (auto *IS = dyn_cast<IfStmt>(S)) {
11882     // Check if the statement is in one of the following forms
11883     // (cond-update-stmt):
11884     // if (expr ordop x) { x = expr; }
11885     // if (x ordop expr) { x = expr; }
11886     // if (x == e) { x = d; }
11887     Res = checkCondUpdateStmt(IS, ErrorInfo);
11888   } else {
11889     // Check if the statement is in one of the following forms (cond-expr-stmt):
11890     // x = expr ordop x ? expr : x;
11891     // x = x ordop expr ? expr : x;
11892     // x = x == e ? d : x;
11893     Res = checkCondExprStmt(S, ErrorInfo);
11894   }
11895 
11896   if (!Res)
11897     return false;
11898 
11899   return checkType(ErrorInfo);
11900 }
11901 
11902 class OpenMPAtomicCompareCaptureChecker final
11903     : public OpenMPAtomicCompareChecker {
11904 public:
OpenMPAtomicCompareCaptureChecker(Sema & S)11905   OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
11906 
getV() const11907   Expr *getV() const { return V; }
getR() const11908   Expr *getR() const { return R; }
isFailOnly() const11909   bool isFailOnly() const { return IsFailOnly; }
isPostfixUpdate() const11910   bool isPostfixUpdate() const { return IsPostfixUpdate; }
11911 
11912   /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
11913   bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11914 
11915 private:
11916   bool checkType(ErrorInfoTy &ErrorInfo);
11917 
11918   // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
11919   // form of 'conditional-update-capture-atomic' structured block on the v5.2
11920   // spec p.p. 82:
11921   // (1) { v = x; cond-update-stmt }
11922   // (2) { cond-update-stmt v = x; }
11923   // (3) if(x == e) { x = d; } else { v = x; }
11924   // (4) { r = x == e; if(r) { x = d; } }
11925   // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
11926 
11927   /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
11928   bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
11929 
11930   /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
11931   /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
11932   bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
11933 
11934   /// 'v' lvalue part of the source atomic expression.
11935   Expr *V = nullptr;
11936   /// 'r' lvalue part of the source atomic expression.
11937   Expr *R = nullptr;
11938   /// If 'v' is only updated when the comparison fails.
11939   bool IsFailOnly = false;
11940   /// If original value of 'x' must be stored in 'v', not an updated one.
11941   bool IsPostfixUpdate = false;
11942 };
11943 
checkType(ErrorInfoTy & ErrorInfo)11944 bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
11945   if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
11946     return false;
11947 
11948   if (V && !CheckValue(V, ErrorInfo, true))
11949     return false;
11950 
11951   if (R && !CheckValue(R, ErrorInfo, true, true))
11952     return false;
11953 
11954   return true;
11955 }
11956 
checkForm3(IfStmt * S,ErrorInfoTy & ErrorInfo)11957 bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
11958                                                    ErrorInfoTy &ErrorInfo) {
11959   IsFailOnly = true;
11960 
11961   auto *Then = S->getThen();
11962   if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11963     if (CS->body_empty()) {
11964       ErrorInfo.Error = ErrorTy::NoStmt;
11965       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11966       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11967       return false;
11968     }
11969     if (CS->size() > 1) {
11970       ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11971       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11972       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11973       return false;
11974     }
11975     Then = CS->body_front();
11976   }
11977 
11978   auto *BO = dyn_cast<BinaryOperator>(Then);
11979   if (!BO) {
11980     ErrorInfo.Error = ErrorTy::NotAnAssignment;
11981     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11982     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11983     return false;
11984   }
11985   if (BO->getOpcode() != BO_Assign) {
11986     ErrorInfo.Error = ErrorTy::NotAnAssignment;
11987     ErrorInfo.ErrorLoc = BO->getExprLoc();
11988     ErrorInfo.NoteLoc = BO->getOperatorLoc();
11989     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11990     return false;
11991   }
11992 
11993   X = BO->getLHS();
11994   D = BO->getRHS();
11995 
11996   auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11997   if (!Cond) {
11998     ErrorInfo.Error = ErrorTy::NotABinaryOp;
11999     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12000     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12001     return false;
12002   }
12003   if (Cond->getOpcode() != BO_EQ) {
12004     ErrorInfo.Error = ErrorTy::NotEQ;
12005     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12006     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12007     return false;
12008   }
12009 
12010   if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12011     E = Cond->getRHS();
12012   } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12013     E = Cond->getLHS();
12014   } else {
12015     ErrorInfo.Error = ErrorTy::InvalidComparison;
12016     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12017     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12018     return false;
12019   }
12020 
12021   C = Cond;
12022 
12023   if (!S->getElse()) {
12024     ErrorInfo.Error = ErrorTy::NoElse;
12025     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12026     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12027     return false;
12028   }
12029 
12030   auto *Else = S->getElse();
12031   if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12032     if (CS->body_empty()) {
12033       ErrorInfo.Error = ErrorTy::NoStmt;
12034       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12035       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12036       return false;
12037     }
12038     if (CS->size() > 1) {
12039       ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12040       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12041       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12042       return false;
12043     }
12044     Else = CS->body_front();
12045   }
12046 
12047   auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12048   if (!ElseBO) {
12049     ErrorInfo.Error = ErrorTy::NotAnAssignment;
12050     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12051     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12052     return false;
12053   }
12054   if (ElseBO->getOpcode() != BO_Assign) {
12055     ErrorInfo.Error = ErrorTy::NotAnAssignment;
12056     ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12057     ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12058     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12059     return false;
12060   }
12061 
12062   if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12063     ErrorInfo.Error = ErrorTy::InvalidAssignment;
12064     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12065     ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12066         ElseBO->getRHS()->getSourceRange();
12067     return false;
12068   }
12069 
12070   V = ElseBO->getLHS();
12071 
12072   return checkType(ErrorInfo);
12073 }
12074 
checkForm45(Stmt * S,ErrorInfoTy & ErrorInfo)12075 bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12076                                                     ErrorInfoTy &ErrorInfo) {
12077   // We don't check here as they should be already done before call this
12078   // function.
12079   auto *CS = cast<CompoundStmt>(S);
12080   assert(CS->size() == 2 && "CompoundStmt size is not expected");
12081   auto *S1 = cast<BinaryOperator>(CS->body_front());
12082   auto *S2 = cast<IfStmt>(CS->body_back());
12083   assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12084 
12085   if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12086     ErrorInfo.Error = ErrorTy::InvalidCondition;
12087     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12088     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12089     return false;
12090   }
12091 
12092   R = S1->getLHS();
12093 
12094   auto *Then = S2->getThen();
12095   if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12096     if (ThenCS->body_empty()) {
12097       ErrorInfo.Error = ErrorTy::NoStmt;
12098       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12099       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12100       return false;
12101     }
12102     if (ThenCS->size() > 1) {
12103       ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12104       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12105       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12106       return false;
12107     }
12108     Then = ThenCS->body_front();
12109   }
12110 
12111   auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12112   if (!ThenBO) {
12113     ErrorInfo.Error = ErrorTy::NotAnAssignment;
12114     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12115     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12116     return false;
12117   }
12118   if (ThenBO->getOpcode() != BO_Assign) {
12119     ErrorInfo.Error = ErrorTy::NotAnAssignment;
12120     ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12121     ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12122     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12123     return false;
12124   }
12125 
12126   X = ThenBO->getLHS();
12127   D = ThenBO->getRHS();
12128 
12129   auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12130   if (BO->getOpcode() != BO_EQ) {
12131     ErrorInfo.Error = ErrorTy::NotEQ;
12132     ErrorInfo.ErrorLoc = BO->getExprLoc();
12133     ErrorInfo.NoteLoc = BO->getOperatorLoc();
12134     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12135     return false;
12136   }
12137 
12138   C = BO;
12139 
12140   if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12141     E = BO->getRHS();
12142   } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12143     E = BO->getLHS();
12144   } else {
12145     ErrorInfo.Error = ErrorTy::InvalidComparison;
12146     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12147     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12148     return false;
12149   }
12150 
12151   if (S2->getElse()) {
12152     IsFailOnly = true;
12153 
12154     auto *Else = S2->getElse();
12155     if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12156       if (ElseCS->body_empty()) {
12157         ErrorInfo.Error = ErrorTy::NoStmt;
12158         ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12159         ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12160         return false;
12161       }
12162       if (ElseCS->size() > 1) {
12163         ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12164         ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12165         ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12166         return false;
12167       }
12168       Else = ElseCS->body_front();
12169     }
12170 
12171     auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12172     if (!ElseBO) {
12173       ErrorInfo.Error = ErrorTy::NotAnAssignment;
12174       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12175       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12176       return false;
12177     }
12178     if (ElseBO->getOpcode() != BO_Assign) {
12179       ErrorInfo.Error = ErrorTy::NotAnAssignment;
12180       ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12181       ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12182       ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12183       return false;
12184     }
12185     if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12186       ErrorInfo.Error = ErrorTy::InvalidAssignment;
12187       ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12188       ErrorInfo.NoteLoc = X->getExprLoc();
12189       ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12190       ErrorInfo.NoteRange = X->getSourceRange();
12191       return false;
12192     }
12193 
12194     V = ElseBO->getLHS();
12195   }
12196 
12197   return checkType(ErrorInfo);
12198 }
12199 
checkStmt(Stmt * S,ErrorInfoTy & ErrorInfo)12200 bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12201                                                   ErrorInfoTy &ErrorInfo) {
12202   // if(x == e) { x = d; } else { v = x; }
12203   if (auto *IS = dyn_cast<IfStmt>(S))
12204     return checkForm3(IS, ErrorInfo);
12205 
12206   auto *CS = dyn_cast<CompoundStmt>(S);
12207   if (!CS) {
12208     ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12209     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12210     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12211     return false;
12212   }
12213   if (CS->body_empty()) {
12214     ErrorInfo.Error = ErrorTy::NoStmt;
12215     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12216     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12217     return false;
12218   }
12219 
12220   // { if(x == e) { x = d; } else { v = x; } }
12221   if (CS->size() == 1) {
12222     auto *IS = dyn_cast<IfStmt>(CS->body_front());
12223     if (!IS) {
12224       ErrorInfo.Error = ErrorTy::NotIfStmt;
12225       ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12226       ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12227           CS->body_front()->getSourceRange();
12228       return false;
12229     }
12230 
12231     return checkForm3(IS, ErrorInfo);
12232   } else if (CS->size() == 2) {
12233     auto *S1 = CS->body_front();
12234     auto *S2 = CS->body_back();
12235 
12236     Stmt *UpdateStmt = nullptr;
12237     Stmt *CondUpdateStmt = nullptr;
12238     Stmt *CondExprStmt = nullptr;
12239 
12240     if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12241       // It could be one of the following cases:
12242       // { v = x; cond-update-stmt }
12243       // { v = x; cond-expr-stmt }
12244       // { cond-expr-stmt; v = x; }
12245       // form 45
12246       if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12247           isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12248         // check if form 45
12249         if (isa<IfStmt>(S2))
12250           return checkForm45(CS, ErrorInfo);
12251         // { cond-expr-stmt; v = x; }
12252         CondExprStmt = S1;
12253         UpdateStmt = S2;
12254       } else {
12255         IsPostfixUpdate = true;
12256         UpdateStmt = S1;
12257         if (isa<IfStmt>(S2)) {
12258           // { v = x; cond-update-stmt }
12259           CondUpdateStmt = S2;
12260         } else {
12261           // { v = x; cond-expr-stmt }
12262           CondExprStmt = S2;
12263         }
12264       }
12265     } else {
12266       // { cond-update-stmt v = x; }
12267       UpdateStmt = S2;
12268       CondUpdateStmt = S1;
12269     }
12270 
12271     auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12272       auto *IS = dyn_cast<IfStmt>(CUS);
12273       if (!IS) {
12274         ErrorInfo.Error = ErrorTy::NotIfStmt;
12275         ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12276         ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12277         return false;
12278       }
12279 
12280       return checkCondUpdateStmt(IS, ErrorInfo);
12281     };
12282 
12283     // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12284     auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12285       auto *BO = dyn_cast<BinaryOperator>(US);
12286       if (!BO) {
12287         ErrorInfo.Error = ErrorTy::NotAnAssignment;
12288         ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12289         ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12290         return false;
12291       }
12292       if (BO->getOpcode() != BO_Assign) {
12293         ErrorInfo.Error = ErrorTy::NotAnAssignment;
12294         ErrorInfo.ErrorLoc = BO->getExprLoc();
12295         ErrorInfo.NoteLoc = BO->getOperatorLoc();
12296         ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12297         return false;
12298       }
12299       if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12300         ErrorInfo.Error = ErrorTy::InvalidAssignment;
12301         ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12302         ErrorInfo.NoteLoc = this->X->getExprLoc();
12303         ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12304         ErrorInfo.NoteRange = this->X->getSourceRange();
12305         return false;
12306       }
12307 
12308       this->V = BO->getLHS();
12309 
12310       return true;
12311     };
12312 
12313     if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12314       return false;
12315     if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12316       return false;
12317     if (!CheckUpdateStmt(UpdateStmt))
12318       return false;
12319   } else {
12320     ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12321     ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12322     ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12323     return false;
12324   }
12325 
12326   return checkType(ErrorInfo);
12327 }
12328 } // namespace
12329 
ActOnOpenMPAtomicDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)12330 StmtResult SemaOpenMP::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
12331                                                   Stmt *AStmt,
12332                                                   SourceLocation StartLoc,
12333                                                   SourceLocation EndLoc) {
12334   ASTContext &Context = getASTContext();
12335   // Register location of the first atomic directive.
12336   DSAStack->addAtomicDirectiveLoc(StartLoc);
12337   if (!AStmt)
12338     return StmtError();
12339 
12340   // 1.2.2 OpenMP Language Terminology
12341   // Structured block - An executable statement with a single entry at the
12342   // top and a single exit at the bottom.
12343   // The point of exit cannot be a branch out of the structured block.
12344   // longjmp() and throw() must not violate the entry/exit criteria.
12345   OpenMPClauseKind AtomicKind = OMPC_unknown;
12346   SourceLocation AtomicKindLoc;
12347   OpenMPClauseKind MemOrderKind = OMPC_unknown;
12348   SourceLocation MemOrderLoc;
12349   bool MutexClauseEncountered = false;
12350   llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12351   for (const OMPClause *C : Clauses) {
12352     switch (C->getClauseKind()) {
12353     case OMPC_read:
12354     case OMPC_write:
12355     case OMPC_update:
12356       MutexClauseEncountered = true;
12357       [[fallthrough]];
12358     case OMPC_capture:
12359     case OMPC_compare: {
12360       if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12361         Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12362             << SourceRange(C->getBeginLoc(), C->getEndLoc());
12363         Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12364             << getOpenMPClauseName(AtomicKind);
12365       } else {
12366         AtomicKind = C->getClauseKind();
12367         AtomicKindLoc = C->getBeginLoc();
12368         if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12369           Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12370               << SourceRange(C->getBeginLoc(), C->getEndLoc());
12371           Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12372               << getOpenMPClauseName(AtomicKind);
12373         }
12374       }
12375       break;
12376     }
12377     case OMPC_weak:
12378     case OMPC_fail: {
12379       if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12380         Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12381             << getOpenMPClauseName(C->getClauseKind())
12382             << SourceRange(C->getBeginLoc(), C->getEndLoc());
12383         return StmtError();
12384       }
12385       break;
12386     }
12387     case OMPC_seq_cst:
12388     case OMPC_acq_rel:
12389     case OMPC_acquire:
12390     case OMPC_release:
12391     case OMPC_relaxed: {
12392       if (MemOrderKind != OMPC_unknown) {
12393         Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12394             << getOpenMPDirectiveName(OMPD_atomic) << 0
12395             << SourceRange(C->getBeginLoc(), C->getEndLoc());
12396         Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12397             << getOpenMPClauseName(MemOrderKind);
12398       } else {
12399         MemOrderKind = C->getClauseKind();
12400         MemOrderLoc = C->getBeginLoc();
12401       }
12402       break;
12403     }
12404     // The following clauses are allowed, but we don't need to do anything here.
12405     case OMPC_hint:
12406       break;
12407     default:
12408       llvm_unreachable("unknown clause is encountered");
12409     }
12410   }
12411   bool IsCompareCapture = false;
12412   if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12413       EncounteredAtomicKinds.contains(OMPC_capture)) {
12414     IsCompareCapture = true;
12415     AtomicKind = OMPC_compare;
12416   }
12417   // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12418   // If atomic-clause is read then memory-order-clause must not be acq_rel or
12419   // release.
12420   // If atomic-clause is write then memory-order-clause must not be acq_rel or
12421   // acquire.
12422   // If atomic-clause is update or not present then memory-order-clause must not
12423   // be acq_rel or acquire.
12424   if ((AtomicKind == OMPC_read &&
12425        (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12426       ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12427         AtomicKind == OMPC_unknown) &&
12428        (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12429     SourceLocation Loc = AtomicKindLoc;
12430     if (AtomicKind == OMPC_unknown)
12431       Loc = StartLoc;
12432     Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12433         << getOpenMPClauseName(AtomicKind)
12434         << (AtomicKind == OMPC_unknown ? 1 : 0)
12435         << getOpenMPClauseName(MemOrderKind);
12436     Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12437         << getOpenMPClauseName(MemOrderKind);
12438   }
12439 
12440   Stmt *Body = AStmt;
12441   if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12442     Body = EWC->getSubExpr();
12443 
12444   Expr *X = nullptr;
12445   Expr *V = nullptr;
12446   Expr *E = nullptr;
12447   Expr *UE = nullptr;
12448   Expr *D = nullptr;
12449   Expr *CE = nullptr;
12450   Expr *R = nullptr;
12451   bool IsXLHSInRHSPart = false;
12452   bool IsPostfixUpdate = false;
12453   bool IsFailOnly = false;
12454   // OpenMP [2.12.6, atomic Construct]
12455   // In the next expressions:
12456   // * x and v (as applicable) are both l-value expressions with scalar type.
12457   // * During the execution of an atomic region, multiple syntactic
12458   // occurrences of x must designate the same storage location.
12459   // * Neither of v and expr (as applicable) may access the storage location
12460   // designated by x.
12461   // * Neither of x and expr (as applicable) may access the storage location
12462   // designated by v.
12463   // * expr is an expression with scalar type.
12464   // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12465   // * binop, binop=, ++, and -- are not overloaded operators.
12466   // * The expression x binop expr must be numerically equivalent to x binop
12467   // (expr). This requirement is satisfied if the operators in expr have
12468   // precedence greater than binop, or by using parentheses around expr or
12469   // subexpressions of expr.
12470   // * The expression expr binop x must be numerically equivalent to (expr)
12471   // binop x. This requirement is satisfied if the operators in expr have
12472   // precedence equal to or greater than binop, or by using parentheses around
12473   // expr or subexpressions of expr.
12474   // * For forms that allow multiple occurrences of x, the number of times
12475   // that x is evaluated is unspecified.
12476   if (AtomicKind == OMPC_read) {
12477     enum {
12478       NotAnExpression,
12479       NotAnAssignmentOp,
12480       NotAScalarType,
12481       NotAnLValue,
12482       NoError
12483     } ErrorFound = NoError;
12484     SourceLocation ErrorLoc, NoteLoc;
12485     SourceRange ErrorRange, NoteRange;
12486     // If clause is read:
12487     //  v = x;
12488     if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12489       const auto *AtomicBinOp =
12490           dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12491       if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12492         X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12493         V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12494         if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12495             (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12496           if (!X->isLValue() || !V->isLValue()) {
12497             const Expr *NotLValueExpr = X->isLValue() ? V : X;
12498             ErrorFound = NotAnLValue;
12499             ErrorLoc = AtomicBinOp->getExprLoc();
12500             ErrorRange = AtomicBinOp->getSourceRange();
12501             NoteLoc = NotLValueExpr->getExprLoc();
12502             NoteRange = NotLValueExpr->getSourceRange();
12503           }
12504         } else if (!X->isInstantiationDependent() ||
12505                    !V->isInstantiationDependent()) {
12506           const Expr *NotScalarExpr =
12507               (X->isInstantiationDependent() || X->getType()->isScalarType())
12508                   ? V
12509                   : X;
12510           ErrorFound = NotAScalarType;
12511           ErrorLoc = AtomicBinOp->getExprLoc();
12512           ErrorRange = AtomicBinOp->getSourceRange();
12513           NoteLoc = NotScalarExpr->getExprLoc();
12514           NoteRange = NotScalarExpr->getSourceRange();
12515         }
12516       } else if (!AtomicBody->isInstantiationDependent()) {
12517         ErrorFound = NotAnAssignmentOp;
12518         ErrorLoc = AtomicBody->getExprLoc();
12519         ErrorRange = AtomicBody->getSourceRange();
12520         NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12521                               : AtomicBody->getExprLoc();
12522         NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12523                                 : AtomicBody->getSourceRange();
12524       }
12525     } else {
12526       ErrorFound = NotAnExpression;
12527       NoteLoc = ErrorLoc = Body->getBeginLoc();
12528       NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12529     }
12530     if (ErrorFound != NoError) {
12531       Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12532           << ErrorRange;
12533       Diag(NoteLoc, diag::note_omp_atomic_read_write)
12534           << ErrorFound << NoteRange;
12535       return StmtError();
12536     }
12537     if (SemaRef.CurContext->isDependentContext())
12538       V = X = nullptr;
12539   } else if (AtomicKind == OMPC_write) {
12540     enum {
12541       NotAnExpression,
12542       NotAnAssignmentOp,
12543       NotAScalarType,
12544       NotAnLValue,
12545       NoError
12546     } ErrorFound = NoError;
12547     SourceLocation ErrorLoc, NoteLoc;
12548     SourceRange ErrorRange, NoteRange;
12549     // If clause is write:
12550     //  x = expr;
12551     if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12552       const auto *AtomicBinOp =
12553           dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12554       if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12555         X = AtomicBinOp->getLHS();
12556         E = AtomicBinOp->getRHS();
12557         if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12558             (E->isInstantiationDependent() || E->getType()->isScalarType())) {
12559           if (!X->isLValue()) {
12560             ErrorFound = NotAnLValue;
12561             ErrorLoc = AtomicBinOp->getExprLoc();
12562             ErrorRange = AtomicBinOp->getSourceRange();
12563             NoteLoc = X->getExprLoc();
12564             NoteRange = X->getSourceRange();
12565           }
12566         } else if (!X->isInstantiationDependent() ||
12567                    !E->isInstantiationDependent()) {
12568           const Expr *NotScalarExpr =
12569               (X->isInstantiationDependent() || X->getType()->isScalarType())
12570                   ? E
12571                   : X;
12572           ErrorFound = NotAScalarType;
12573           ErrorLoc = AtomicBinOp->getExprLoc();
12574           ErrorRange = AtomicBinOp->getSourceRange();
12575           NoteLoc = NotScalarExpr->getExprLoc();
12576           NoteRange = NotScalarExpr->getSourceRange();
12577         }
12578       } else if (!AtomicBody->isInstantiationDependent()) {
12579         ErrorFound = NotAnAssignmentOp;
12580         ErrorLoc = AtomicBody->getExprLoc();
12581         ErrorRange = AtomicBody->getSourceRange();
12582         NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12583                               : AtomicBody->getExprLoc();
12584         NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12585                                 : AtomicBody->getSourceRange();
12586       }
12587     } else {
12588       ErrorFound = NotAnExpression;
12589       NoteLoc = ErrorLoc = Body->getBeginLoc();
12590       NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12591     }
12592     if (ErrorFound != NoError) {
12593       Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12594           << ErrorRange;
12595       Diag(NoteLoc, diag::note_omp_atomic_read_write)
12596           << ErrorFound << NoteRange;
12597       return StmtError();
12598     }
12599     if (SemaRef.CurContext->isDependentContext())
12600       E = X = nullptr;
12601   } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12602     // If clause is update:
12603     //  x++;
12604     //  x--;
12605     //  ++x;
12606     //  --x;
12607     //  x binop= expr;
12608     //  x = x binop expr;
12609     //  x = expr binop x;
12610     OpenMPAtomicUpdateChecker Checker(SemaRef);
12611     if (Checker.checkStatement(
12612             Body,
12613             (AtomicKind == OMPC_update)
12614                 ? diag::err_omp_atomic_update_not_expression_statement
12615                 : diag::err_omp_atomic_not_expression_statement,
12616             diag::note_omp_atomic_update))
12617       return StmtError();
12618     if (!SemaRef.CurContext->isDependentContext()) {
12619       E = Checker.getExpr();
12620       X = Checker.getX();
12621       UE = Checker.getUpdateExpr();
12622       IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12623     }
12624   } else if (AtomicKind == OMPC_capture) {
12625     enum {
12626       NotAnAssignmentOp,
12627       NotACompoundStatement,
12628       NotTwoSubstatements,
12629       NotASpecificExpression,
12630       NoError
12631     } ErrorFound = NoError;
12632     SourceLocation ErrorLoc, NoteLoc;
12633     SourceRange ErrorRange, NoteRange;
12634     if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12635       // If clause is a capture:
12636       //  v = x++;
12637       //  v = x--;
12638       //  v = ++x;
12639       //  v = --x;
12640       //  v = x binop= expr;
12641       //  v = x = x binop expr;
12642       //  v = x = expr binop x;
12643       const auto *AtomicBinOp =
12644           dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12645       if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12646         V = AtomicBinOp->getLHS();
12647         Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12648         OpenMPAtomicUpdateChecker Checker(SemaRef);
12649         if (Checker.checkStatement(
12650                 Body, diag::err_omp_atomic_capture_not_expression_statement,
12651                 diag::note_omp_atomic_update))
12652           return StmtError();
12653         E = Checker.getExpr();
12654         X = Checker.getX();
12655         UE = Checker.getUpdateExpr();
12656         IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12657         IsPostfixUpdate = Checker.isPostfixUpdate();
12658       } else if (!AtomicBody->isInstantiationDependent()) {
12659         ErrorLoc = AtomicBody->getExprLoc();
12660         ErrorRange = AtomicBody->getSourceRange();
12661         NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12662                               : AtomicBody->getExprLoc();
12663         NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12664                                 : AtomicBody->getSourceRange();
12665         ErrorFound = NotAnAssignmentOp;
12666       }
12667       if (ErrorFound != NoError) {
12668         Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12669             << ErrorRange;
12670         Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12671         return StmtError();
12672       }
12673       if (SemaRef.CurContext->isDependentContext())
12674         UE = V = E = X = nullptr;
12675     } else {
12676       // If clause is a capture:
12677       //  { v = x; x = expr; }
12678       //  { v = x; x++; }
12679       //  { v = x; x--; }
12680       //  { v = x; ++x; }
12681       //  { v = x; --x; }
12682       //  { v = x; x binop= expr; }
12683       //  { v = x; x = x binop expr; }
12684       //  { v = x; x = expr binop x; }
12685       //  { x++; v = x; }
12686       //  { x--; v = x; }
12687       //  { ++x; v = x; }
12688       //  { --x; v = x; }
12689       //  { x binop= expr; v = x; }
12690       //  { x = x binop expr; v = x; }
12691       //  { x = expr binop x; v = x; }
12692       if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
12693         // Check that this is { expr1; expr2; }
12694         if (CS->size() == 2) {
12695           Stmt *First = CS->body_front();
12696           Stmt *Second = CS->body_back();
12697           if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
12698             First = EWC->getSubExpr()->IgnoreParenImpCasts();
12699           if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
12700             Second = EWC->getSubExpr()->IgnoreParenImpCasts();
12701           // Need to find what subexpression is 'v' and what is 'x'.
12702           OpenMPAtomicUpdateChecker Checker(SemaRef);
12703           bool IsUpdateExprFound = !Checker.checkStatement(Second);
12704           BinaryOperator *BinOp = nullptr;
12705           if (IsUpdateExprFound) {
12706             BinOp = dyn_cast<BinaryOperator>(First);
12707             IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12708           }
12709           if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
12710             //  { v = x; x++; }
12711             //  { v = x; x--; }
12712             //  { v = x; ++x; }
12713             //  { v = x; --x; }
12714             //  { v = x; x binop= expr; }
12715             //  { v = x; x = x binop expr; }
12716             //  { v = x; x = expr binop x; }
12717             // Check that the first expression has form v = x.
12718             Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12719             llvm::FoldingSetNodeID XId, PossibleXId;
12720             Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12721             PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12722             IsUpdateExprFound = XId == PossibleXId;
12723             if (IsUpdateExprFound) {
12724               V = BinOp->getLHS();
12725               X = Checker.getX();
12726               E = Checker.getExpr();
12727               UE = Checker.getUpdateExpr();
12728               IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12729               IsPostfixUpdate = true;
12730             }
12731           }
12732           if (!IsUpdateExprFound) {
12733             IsUpdateExprFound = !Checker.checkStatement(First);
12734             BinOp = nullptr;
12735             if (IsUpdateExprFound) {
12736               BinOp = dyn_cast<BinaryOperator>(Second);
12737               IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12738             }
12739             if (IsUpdateExprFound &&
12740                 !SemaRef.CurContext->isDependentContext()) {
12741               //  { x++; v = x; }
12742               //  { x--; v = x; }
12743               //  { ++x; v = x; }
12744               //  { --x; v = x; }
12745               //  { x binop= expr; v = x; }
12746               //  { x = x binop expr; v = x; }
12747               //  { x = expr binop x; v = x; }
12748               // Check that the second expression has form v = x.
12749               Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12750               llvm::FoldingSetNodeID XId, PossibleXId;
12751               Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12752               PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12753               IsUpdateExprFound = XId == PossibleXId;
12754               if (IsUpdateExprFound) {
12755                 V = BinOp->getLHS();
12756                 X = Checker.getX();
12757                 E = Checker.getExpr();
12758                 UE = Checker.getUpdateExpr();
12759                 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12760                 IsPostfixUpdate = false;
12761               }
12762             }
12763           }
12764           if (!IsUpdateExprFound) {
12765             //  { v = x; x = expr; }
12766             auto *FirstExpr = dyn_cast<Expr>(First);
12767             auto *SecondExpr = dyn_cast<Expr>(Second);
12768             if (!FirstExpr || !SecondExpr ||
12769                 !(FirstExpr->isInstantiationDependent() ||
12770                   SecondExpr->isInstantiationDependent())) {
12771               auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
12772               if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
12773                 ErrorFound = NotAnAssignmentOp;
12774                 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
12775                                                 : First->getBeginLoc();
12776                 NoteRange = ErrorRange = FirstBinOp
12777                                              ? FirstBinOp->getSourceRange()
12778                                              : SourceRange(ErrorLoc, ErrorLoc);
12779               } else {
12780                 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
12781                 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
12782                   ErrorFound = NotAnAssignmentOp;
12783                   NoteLoc = ErrorLoc = SecondBinOp
12784                                            ? SecondBinOp->getOperatorLoc()
12785                                            : Second->getBeginLoc();
12786                   NoteRange = ErrorRange =
12787                       SecondBinOp ? SecondBinOp->getSourceRange()
12788                                   : SourceRange(ErrorLoc, ErrorLoc);
12789                 } else {
12790                   Expr *PossibleXRHSInFirst =
12791                       FirstBinOp->getRHS()->IgnoreParenImpCasts();
12792                   Expr *PossibleXLHSInSecond =
12793                       SecondBinOp->getLHS()->IgnoreParenImpCasts();
12794                   llvm::FoldingSetNodeID X1Id, X2Id;
12795                   PossibleXRHSInFirst->Profile(X1Id, Context,
12796                                                /*Canonical=*/true);
12797                   PossibleXLHSInSecond->Profile(X2Id, Context,
12798                                                 /*Canonical=*/true);
12799                   IsUpdateExprFound = X1Id == X2Id;
12800                   if (IsUpdateExprFound) {
12801                     V = FirstBinOp->getLHS();
12802                     X = SecondBinOp->getLHS();
12803                     E = SecondBinOp->getRHS();
12804                     UE = nullptr;
12805                     IsXLHSInRHSPart = false;
12806                     IsPostfixUpdate = true;
12807                   } else {
12808                     ErrorFound = NotASpecificExpression;
12809                     ErrorLoc = FirstBinOp->getExprLoc();
12810                     ErrorRange = FirstBinOp->getSourceRange();
12811                     NoteLoc = SecondBinOp->getLHS()->getExprLoc();
12812                     NoteRange = SecondBinOp->getRHS()->getSourceRange();
12813                   }
12814                 }
12815               }
12816             }
12817           }
12818         } else {
12819           NoteLoc = ErrorLoc = Body->getBeginLoc();
12820           NoteRange = ErrorRange =
12821               SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12822           ErrorFound = NotTwoSubstatements;
12823         }
12824       } else {
12825         NoteLoc = ErrorLoc = Body->getBeginLoc();
12826         NoteRange = ErrorRange =
12827             SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12828         ErrorFound = NotACompoundStatement;
12829       }
12830     }
12831     if (ErrorFound != NoError) {
12832       Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
12833           << ErrorRange;
12834       Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12835       return StmtError();
12836     }
12837     if (SemaRef.CurContext->isDependentContext())
12838       UE = V = E = X = nullptr;
12839   } else if (AtomicKind == OMPC_compare) {
12840     if (IsCompareCapture) {
12841       OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
12842       OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
12843       if (!Checker.checkStmt(Body, ErrorInfo)) {
12844         Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
12845             << ErrorInfo.ErrorRange;
12846         Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12847             << ErrorInfo.Error << ErrorInfo.NoteRange;
12848         return StmtError();
12849       }
12850       X = Checker.getX();
12851       E = Checker.getE();
12852       D = Checker.getD();
12853       CE = Checker.getCond();
12854       V = Checker.getV();
12855       R = Checker.getR();
12856       // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12857       IsXLHSInRHSPart = Checker.isXBinopExpr();
12858       IsFailOnly = Checker.isFailOnly();
12859       IsPostfixUpdate = Checker.isPostfixUpdate();
12860     } else {
12861       OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
12862       OpenMPAtomicCompareChecker Checker(SemaRef);
12863       if (!Checker.checkStmt(Body, ErrorInfo)) {
12864         Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
12865             << ErrorInfo.ErrorRange;
12866         Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12867             << ErrorInfo.Error << ErrorInfo.NoteRange;
12868         return StmtError();
12869       }
12870       X = Checker.getX();
12871       E = Checker.getE();
12872       D = Checker.getD();
12873       CE = Checker.getCond();
12874       // The weak clause may only appear if the resulting atomic operation is
12875       // an atomic conditional update for which the comparison tests for
12876       // equality. It was not possible to do this check in
12877       // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
12878       // could not be performed (Clauses are not available).
12879       auto *It = find_if(Clauses, [](OMPClause *C) {
12880         return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
12881       });
12882       if (It != Clauses.end()) {
12883         auto *Cond = dyn_cast<BinaryOperator>(CE);
12884         if (Cond->getOpcode() != BO_EQ) {
12885           ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
12886           ErrorInfo.ErrorLoc = Cond->getExprLoc();
12887           ErrorInfo.NoteLoc = Cond->getOperatorLoc();
12888           ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12889 
12890           Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
12891               << ErrorInfo.ErrorRange;
12892           return StmtError();
12893         }
12894       }
12895       // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12896       IsXLHSInRHSPart = Checker.isXBinopExpr();
12897     }
12898   }
12899 
12900   SemaRef.setFunctionHasBranchProtectedScope();
12901 
12902   return OMPAtomicDirective::Create(
12903       Context, StartLoc, EndLoc, Clauses, AStmt,
12904       {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
12905 }
12906 
ActOnOpenMPTargetDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)12907 StmtResult SemaOpenMP::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
12908                                                   Stmt *AStmt,
12909                                                   SourceLocation StartLoc,
12910                                                   SourceLocation EndLoc) {
12911   if (!AStmt)
12912     return StmtError();
12913 
12914   CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target, AStmt);
12915 
12916   // OpenMP [2.16, Nesting of Regions]
12917   // If specified, a teams construct must be contained within a target
12918   // construct. That target construct must contain no statements or directives
12919   // outside of the teams construct.
12920   if (DSAStack->hasInnerTeamsRegion()) {
12921     const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
12922     bool OMPTeamsFound = true;
12923     if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
12924       auto I = CS->body_begin();
12925       while (I != CS->body_end()) {
12926         const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
12927         bool IsTeams = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
12928         if (!IsTeams || I != CS->body_begin()) {
12929           OMPTeamsFound = false;
12930           if (IsTeams && I != CS->body_begin()) {
12931             // This is the two teams case. Since the InnerTeamsRegionLoc will
12932             // point to this second one reset the iterator to the other teams.
12933             --I;
12934           }
12935           break;
12936         }
12937         ++I;
12938       }
12939       assert(I != CS->body_end() && "Not found statement");
12940       S = *I;
12941     } else {
12942       const auto *OED = dyn_cast<OMPExecutableDirective>(S);
12943       OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
12944     }
12945     if (!OMPTeamsFound) {
12946       Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
12947       Diag(DSAStack->getInnerTeamsRegionLoc(),
12948            diag::note_omp_nested_teams_construct_here);
12949       Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
12950           << isa<OMPExecutableDirective>(S);
12951       return StmtError();
12952     }
12953   }
12954 
12955   return OMPTargetDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
12956                                     AStmt);
12957 }
12958 
ActOnOpenMPTargetParallelDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)12959 StmtResult SemaOpenMP::ActOnOpenMPTargetParallelDirective(
12960     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12961     SourceLocation EndLoc) {
12962   if (!AStmt)
12963     return StmtError();
12964 
12965   setBranchProtectedScope(SemaRef, OMPD_target_parallel, AStmt);
12966 
12967   return OMPTargetParallelDirective::Create(
12968       getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
12969       DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
12970 }
12971 
ActOnOpenMPTargetParallelForDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)12972 StmtResult SemaOpenMP::ActOnOpenMPTargetParallelForDirective(
12973     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12974     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
12975   if (!AStmt)
12976     return StmtError();
12977 
12978   CapturedStmt *CS =
12979       setBranchProtectedScope(SemaRef, OMPD_target_parallel_for, AStmt);
12980 
12981   OMPLoopBasedDirective::HelperExprs B;
12982   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
12983   // define the nested loops number.
12984   unsigned NestedLoopCount =
12985       checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
12986                       getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
12987                       VarsWithImplicitDSA, B);
12988   if (NestedLoopCount == 0)
12989     return StmtError();
12990 
12991   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
12992     return StmtError();
12993 
12994   return OMPTargetParallelForDirective::Create(
12995       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
12996       DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
12997 }
12998 
12999 /// Check for existence of a map clause in the list of clauses.
hasClauses(ArrayRef<OMPClause * > Clauses,const OpenMPClauseKind K)13000 static bool hasClauses(ArrayRef<OMPClause *> Clauses,
13001                        const OpenMPClauseKind K) {
13002   return llvm::any_of(
13003       Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13004 }
13005 
13006 template <typename... Params>
hasClauses(ArrayRef<OMPClause * > Clauses,const OpenMPClauseKind K,const Params...ClauseTypes)13007 static bool hasClauses(ArrayRef<OMPClause *> Clauses, const OpenMPClauseKind K,
13008                        const Params... ClauseTypes) {
13009   return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13010 }
13011 
13012 /// Check if the variables in the mapping clause are externally visible.
isClauseMappable(ArrayRef<OMPClause * > Clauses)13013 static bool isClauseMappable(ArrayRef<OMPClause *> Clauses) {
13014   for (const OMPClause *C : Clauses) {
13015     if (auto *TC = dyn_cast<OMPToClause>(C))
13016       return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13017         return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13018                (VD->isExternallyVisible() &&
13019                 VD->getVisibility() != HiddenVisibility);
13020       });
13021     else if (auto *FC = dyn_cast<OMPFromClause>(C))
13022       return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13023         return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13024                (VD->isExternallyVisible() &&
13025                 VD->getVisibility() != HiddenVisibility);
13026       });
13027   }
13028 
13029   return true;
13030 }
13031 
13032 StmtResult
ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)13033 SemaOpenMP::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
13034                                            Stmt *AStmt, SourceLocation StartLoc,
13035                                            SourceLocation EndLoc) {
13036   if (!AStmt)
13037     return StmtError();
13038 
13039   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13040 
13041   // OpenMP [2.12.2, target data Construct, Restrictions]
13042   // At least one map, use_device_addr or use_device_ptr clause must appear on
13043   // the directive.
13044   if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13045       (getLangOpts().OpenMP < 50 ||
13046        !hasClauses(Clauses, OMPC_use_device_addr))) {
13047     StringRef Expected;
13048     if (getLangOpts().OpenMP < 50)
13049       Expected = "'map' or 'use_device_ptr'";
13050     else
13051       Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13052     Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13053         << Expected << getOpenMPDirectiveName(OMPD_target_data);
13054     return StmtError();
13055   }
13056 
13057   SemaRef.setFunctionHasBranchProtectedScope();
13058 
13059   return OMPTargetDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13060                                         Clauses, AStmt);
13061 }
13062 
ActOnOpenMPTargetEnterDataDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc,Stmt * AStmt)13063 StmtResult SemaOpenMP::ActOnOpenMPTargetEnterDataDirective(
13064     ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13065     SourceLocation EndLoc, Stmt *AStmt) {
13066   if (!AStmt)
13067     return StmtError();
13068 
13069   setBranchProtectedScope(SemaRef, OMPD_target_enter_data, AStmt);
13070 
13071   // OpenMP [2.10.2, Restrictions, p. 99]
13072   // At least one map clause must appear on the directive.
13073   if (!hasClauses(Clauses, OMPC_map)) {
13074     Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13075         << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
13076     return StmtError();
13077   }
13078 
13079   return OMPTargetEnterDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13080                                              Clauses, AStmt);
13081 }
13082 
ActOnOpenMPTargetExitDataDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc,Stmt * AStmt)13083 StmtResult SemaOpenMP::ActOnOpenMPTargetExitDataDirective(
13084     ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13085     SourceLocation EndLoc, Stmt *AStmt) {
13086   if (!AStmt)
13087     return StmtError();
13088 
13089   setBranchProtectedScope(SemaRef, OMPD_target_exit_data, AStmt);
13090 
13091   // OpenMP [2.10.3, Restrictions, p. 102]
13092   // At least one map clause must appear on the directive.
13093   if (!hasClauses(Clauses, OMPC_map)) {
13094     Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13095         << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
13096     return StmtError();
13097   }
13098 
13099   return OMPTargetExitDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13100                                             Clauses, AStmt);
13101 }
13102 
ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc,Stmt * AStmt)13103 StmtResult SemaOpenMP::ActOnOpenMPTargetUpdateDirective(
13104     ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13105     SourceLocation EndLoc, Stmt *AStmt) {
13106   if (!AStmt)
13107     return StmtError();
13108 
13109   setBranchProtectedScope(SemaRef, OMPD_target_update, AStmt);
13110 
13111   if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13112     Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13113     return StmtError();
13114   }
13115 
13116   if (!isClauseMappable(Clauses)) {
13117     Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13118     return StmtError();
13119   }
13120 
13121   return OMPTargetUpdateDirective::Create(getASTContext(), StartLoc, EndLoc,
13122                                           Clauses, AStmt);
13123 }
13124 
ActOnOpenMPTeamsDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)13125 StmtResult SemaOpenMP::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
13126                                                  Stmt *AStmt,
13127                                                  SourceLocation StartLoc,
13128                                                  SourceLocation EndLoc) {
13129   if (!AStmt)
13130     return StmtError();
13131 
13132   // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13133   if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13134     Diag(StartLoc, diag::warn_hip_omp_target_directives);
13135 
13136   setBranchProtectedScope(SemaRef, OMPD_teams, AStmt);
13137 
13138   DSAStack->setParentTeamsRegionLoc(StartLoc);
13139 
13140   return OMPTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13141                                    AStmt);
13142 }
13143 
ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc,SourceLocation EndLoc,OpenMPDirectiveKind CancelRegion)13144 StmtResult SemaOpenMP::ActOnOpenMPCancellationPointDirective(
13145     SourceLocation StartLoc, SourceLocation EndLoc,
13146     OpenMPDirectiveKind CancelRegion) {
13147   if (DSAStack->isParentNowaitRegion()) {
13148     Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13149     return StmtError();
13150   }
13151   if (DSAStack->isParentOrderedRegion()) {
13152     Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13153     return StmtError();
13154   }
13155   return OMPCancellationPointDirective::Create(getASTContext(), StartLoc,
13156                                                EndLoc, CancelRegion);
13157 }
13158 
ActOnOpenMPCancelDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc,OpenMPDirectiveKind CancelRegion)13159 StmtResult SemaOpenMP::ActOnOpenMPCancelDirective(
13160     ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13161     SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13162   if (DSAStack->isParentNowaitRegion()) {
13163     Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13164     return StmtError();
13165   }
13166   if (DSAStack->isParentOrderedRegion()) {
13167     Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13168     return StmtError();
13169   }
13170   DSAStack->setParentCancelRegion(/*Cancel=*/true);
13171   return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13172                                     CancelRegion);
13173 }
13174 
checkReductionClauseWithNogroup(Sema & S,ArrayRef<OMPClause * > Clauses)13175 static bool checkReductionClauseWithNogroup(Sema &S,
13176                                             ArrayRef<OMPClause *> Clauses) {
13177   const OMPClause *ReductionClause = nullptr;
13178   const OMPClause *NogroupClause = nullptr;
13179   for (const OMPClause *C : Clauses) {
13180     if (C->getClauseKind() == OMPC_reduction) {
13181       ReductionClause = C;
13182       if (NogroupClause)
13183         break;
13184       continue;
13185     }
13186     if (C->getClauseKind() == OMPC_nogroup) {
13187       NogroupClause = C;
13188       if (ReductionClause)
13189         break;
13190       continue;
13191     }
13192   }
13193   if (ReductionClause && NogroupClause) {
13194     S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13195         << SourceRange(NogroupClause->getBeginLoc(),
13196                        NogroupClause->getEndLoc());
13197     return true;
13198   }
13199   return false;
13200 }
13201 
ActOnOpenMPTaskLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13202 StmtResult SemaOpenMP::ActOnOpenMPTaskLoopDirective(
13203     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13204     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13205   if (!AStmt)
13206     return StmtError();
13207 
13208   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13209   OMPLoopBasedDirective::HelperExprs B;
13210   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13211   // define the nested loops number.
13212   unsigned NestedLoopCount =
13213       checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13214                       /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13215                       *DSAStack, VarsWithImplicitDSA, B);
13216   if (NestedLoopCount == 0)
13217     return StmtError();
13218 
13219   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13220          "omp for loop exprs were not built");
13221 
13222   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13223   // The grainsize clause and num_tasks clause are mutually exclusive and may
13224   // not appear on the same taskloop directive.
13225   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13226                                     {OMPC_grainsize, OMPC_num_tasks}))
13227     return StmtError();
13228   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13229   // If a reduction clause is present on the taskloop directive, the nogroup
13230   // clause must not be specified.
13231   if (checkReductionClauseWithNogroup(SemaRef, Clauses))
13232     return StmtError();
13233 
13234   SemaRef.setFunctionHasBranchProtectedScope();
13235   return OMPTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13236                                       NestedLoopCount, Clauses, AStmt, B,
13237                                       DSAStack->isCancelRegion());
13238 }
13239 
ActOnOpenMPTaskLoopSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13240 StmtResult SemaOpenMP::ActOnOpenMPTaskLoopSimdDirective(
13241     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13242     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13243   if (!AStmt)
13244     return StmtError();
13245 
13246   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13247   OMPLoopBasedDirective::HelperExprs B;
13248   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13249   // define the nested loops number.
13250   unsigned NestedLoopCount =
13251       checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13252                       /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13253                       *DSAStack, VarsWithImplicitDSA, B);
13254   if (NestedLoopCount == 0)
13255     return StmtError();
13256 
13257   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13258     return StmtError();
13259 
13260   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13261   // The grainsize clause and num_tasks clause are mutually exclusive and may
13262   // not appear on the same taskloop directive.
13263   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13264                                     {OMPC_grainsize, OMPC_num_tasks}))
13265     return StmtError();
13266   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13267   // If a reduction clause is present on the taskloop directive, the nogroup
13268   // clause must not be specified.
13269   if (checkReductionClauseWithNogroup(SemaRef, Clauses))
13270     return StmtError();
13271   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13272     return StmtError();
13273 
13274   SemaRef.setFunctionHasBranchProtectedScope();
13275   return OMPTaskLoopSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13276                                           NestedLoopCount, Clauses, AStmt, B);
13277 }
13278 
ActOnOpenMPMasterTaskLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13279 StmtResult SemaOpenMP::ActOnOpenMPMasterTaskLoopDirective(
13280     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13281     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13282   if (!AStmt)
13283     return StmtError();
13284 
13285   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13286   OMPLoopBasedDirective::HelperExprs B;
13287   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13288   // define the nested loops number.
13289   unsigned NestedLoopCount =
13290       checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13291                       /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13292                       *DSAStack, VarsWithImplicitDSA, B);
13293   if (NestedLoopCount == 0)
13294     return StmtError();
13295 
13296   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13297          "omp for loop exprs were not built");
13298 
13299   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13300   // The grainsize clause and num_tasks clause are mutually exclusive and may
13301   // not appear on the same taskloop directive.
13302   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13303                                     {OMPC_grainsize, OMPC_num_tasks}))
13304     return StmtError();
13305   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13306   // If a reduction clause is present on the taskloop directive, the nogroup
13307   // clause must not be specified.
13308   if (checkReductionClauseWithNogroup(SemaRef, Clauses))
13309     return StmtError();
13310 
13311   SemaRef.setFunctionHasBranchProtectedScope();
13312   return OMPMasterTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13313                                             NestedLoopCount, Clauses, AStmt, B,
13314                                             DSAStack->isCancelRegion());
13315 }
13316 
ActOnOpenMPMaskedTaskLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13317 StmtResult SemaOpenMP::ActOnOpenMPMaskedTaskLoopDirective(
13318     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13319     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13320   if (!AStmt)
13321     return StmtError();
13322 
13323   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13324   OMPLoopBasedDirective::HelperExprs B;
13325   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13326   // define the nested loops number.
13327   unsigned NestedLoopCount =
13328       checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13329                       /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13330                       *DSAStack, VarsWithImplicitDSA, B);
13331   if (NestedLoopCount == 0)
13332     return StmtError();
13333 
13334   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13335          "omp for loop exprs were not built");
13336 
13337   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13338   // The grainsize clause and num_tasks clause are mutually exclusive and may
13339   // not appear on the same taskloop directive.
13340   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13341                                     {OMPC_grainsize, OMPC_num_tasks}))
13342     return StmtError();
13343   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13344   // If a reduction clause is present on the taskloop directive, the nogroup
13345   // clause must not be specified.
13346   if (checkReductionClauseWithNogroup(SemaRef, Clauses))
13347     return StmtError();
13348 
13349   SemaRef.setFunctionHasBranchProtectedScope();
13350   return OMPMaskedTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13351                                             NestedLoopCount, Clauses, AStmt, B,
13352                                             DSAStack->isCancelRegion());
13353 }
13354 
ActOnOpenMPMasterTaskLoopSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13355 StmtResult SemaOpenMP::ActOnOpenMPMasterTaskLoopSimdDirective(
13356     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13357     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13358   if (!AStmt)
13359     return StmtError();
13360 
13361   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13362   OMPLoopBasedDirective::HelperExprs B;
13363   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13364   // define the nested loops number.
13365   unsigned NestedLoopCount =
13366       checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13367                       /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13368                       *DSAStack, VarsWithImplicitDSA, B);
13369   if (NestedLoopCount == 0)
13370     return StmtError();
13371 
13372   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13373     return StmtError();
13374 
13375   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13376   // The grainsize clause and num_tasks clause are mutually exclusive and may
13377   // not appear on the same taskloop directive.
13378   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13379                                     {OMPC_grainsize, OMPC_num_tasks}))
13380     return StmtError();
13381   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13382   // If a reduction clause is present on the taskloop directive, the nogroup
13383   // clause must not be specified.
13384   if (checkReductionClauseWithNogroup(SemaRef, Clauses))
13385     return StmtError();
13386   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13387     return StmtError();
13388 
13389   SemaRef.setFunctionHasBranchProtectedScope();
13390   return OMPMasterTaskLoopSimdDirective::Create(
13391       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13392 }
13393 
ActOnOpenMPMaskedTaskLoopSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13394 StmtResult SemaOpenMP::ActOnOpenMPMaskedTaskLoopSimdDirective(
13395     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13396     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13397   if (!AStmt)
13398     return StmtError();
13399 
13400   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13401   OMPLoopBasedDirective::HelperExprs B;
13402   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13403   // define the nested loops number.
13404   unsigned NestedLoopCount =
13405       checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13406                       /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13407                       *DSAStack, VarsWithImplicitDSA, B);
13408   if (NestedLoopCount == 0)
13409     return StmtError();
13410 
13411   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13412     return StmtError();
13413 
13414   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13415   // The grainsize clause and num_tasks clause are mutually exclusive and may
13416   // not appear on the same taskloop directive.
13417   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13418                                     {OMPC_grainsize, OMPC_num_tasks}))
13419     return StmtError();
13420   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13421   // If a reduction clause is present on the taskloop directive, the nogroup
13422   // clause must not be specified.
13423   if (checkReductionClauseWithNogroup(SemaRef, Clauses))
13424     return StmtError();
13425   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13426     return StmtError();
13427 
13428   SemaRef.setFunctionHasBranchProtectedScope();
13429   return OMPMaskedTaskLoopSimdDirective::Create(
13430       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13431 }
13432 
ActOnOpenMPParallelMasterTaskLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13433 StmtResult SemaOpenMP::ActOnOpenMPParallelMasterTaskLoopDirective(
13434     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13435     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13436   if (!AStmt)
13437     return StmtError();
13438 
13439   CapturedStmt *CS =
13440       setBranchProtectedScope(SemaRef, OMPD_parallel_master_taskloop, AStmt);
13441 
13442   OMPLoopBasedDirective::HelperExprs B;
13443   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13444   // define the nested loops number.
13445   unsigned NestedLoopCount = checkOpenMPLoop(
13446       OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13447       /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13448       VarsWithImplicitDSA, B);
13449   if (NestedLoopCount == 0)
13450     return StmtError();
13451 
13452   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13453          "omp for loop exprs were not built");
13454 
13455   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13456   // The grainsize clause and num_tasks clause are mutually exclusive and may
13457   // not appear on the same taskloop directive.
13458   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13459                                     {OMPC_grainsize, OMPC_num_tasks}))
13460     return StmtError();
13461   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13462   // If a reduction clause is present on the taskloop directive, the nogroup
13463   // clause must not be specified.
13464   if (checkReductionClauseWithNogroup(SemaRef, Clauses))
13465     return StmtError();
13466 
13467   return OMPParallelMasterTaskLoopDirective::Create(
13468       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13469       DSAStack->isCancelRegion());
13470 }
13471 
ActOnOpenMPParallelMaskedTaskLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13472 StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedTaskLoopDirective(
13473     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13474     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13475   if (!AStmt)
13476     return StmtError();
13477 
13478   CapturedStmt *CS =
13479       setBranchProtectedScope(SemaRef, OMPD_parallel_masked_taskloop, AStmt);
13480 
13481   OMPLoopBasedDirective::HelperExprs B;
13482   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13483   // define the nested loops number.
13484   unsigned NestedLoopCount = checkOpenMPLoop(
13485       OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13486       /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13487       VarsWithImplicitDSA, B);
13488   if (NestedLoopCount == 0)
13489     return StmtError();
13490 
13491   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13492          "omp for loop exprs were not built");
13493 
13494   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13495   // The grainsize clause and num_tasks clause are mutually exclusive and may
13496   // not appear on the same taskloop directive.
13497   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13498                                     {OMPC_grainsize, OMPC_num_tasks}))
13499     return StmtError();
13500   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13501   // If a reduction clause is present on the taskloop directive, the nogroup
13502   // clause must not be specified.
13503   if (checkReductionClauseWithNogroup(SemaRef, Clauses))
13504     return StmtError();
13505 
13506   return OMPParallelMaskedTaskLoopDirective::Create(
13507       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13508       DSAStack->isCancelRegion());
13509 }
13510 
ActOnOpenMPParallelMasterTaskLoopSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13511 StmtResult SemaOpenMP::ActOnOpenMPParallelMasterTaskLoopSimdDirective(
13512     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13513     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13514   if (!AStmt)
13515     return StmtError();
13516 
13517   CapturedStmt *CS = setBranchProtectedScope(
13518       SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13519 
13520   OMPLoopBasedDirective::HelperExprs B;
13521   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13522   // define the nested loops number.
13523   unsigned NestedLoopCount = checkOpenMPLoop(
13524       OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13525       /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13526       VarsWithImplicitDSA, B);
13527   if (NestedLoopCount == 0)
13528     return StmtError();
13529 
13530   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13531     return StmtError();
13532 
13533   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13534   // The grainsize clause and num_tasks clause are mutually exclusive and may
13535   // not appear on the same taskloop directive.
13536   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13537                                     {OMPC_grainsize, OMPC_num_tasks}))
13538     return StmtError();
13539   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13540   // If a reduction clause is present on the taskloop directive, the nogroup
13541   // clause must not be specified.
13542   if (checkReductionClauseWithNogroup(SemaRef, Clauses))
13543     return StmtError();
13544   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13545     return StmtError();
13546 
13547   return OMPParallelMasterTaskLoopSimdDirective::Create(
13548       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13549 }
13550 
ActOnOpenMPParallelMaskedTaskLoopSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13551 StmtResult SemaOpenMP::ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
13552     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13553     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13554   if (!AStmt)
13555     return StmtError();
13556 
13557   CapturedStmt *CS = setBranchProtectedScope(
13558       SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13559 
13560   OMPLoopBasedDirective::HelperExprs B;
13561   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13562   // define the nested loops number.
13563   unsigned NestedLoopCount = checkOpenMPLoop(
13564       OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13565       /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13566       VarsWithImplicitDSA, B);
13567   if (NestedLoopCount == 0)
13568     return StmtError();
13569 
13570   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13571     return StmtError();
13572 
13573   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13574   // The grainsize clause and num_tasks clause are mutually exclusive and may
13575   // not appear on the same taskloop directive.
13576   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
13577                                     {OMPC_grainsize, OMPC_num_tasks}))
13578     return StmtError();
13579   // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13580   // If a reduction clause is present on the taskloop directive, the nogroup
13581   // clause must not be specified.
13582   if (checkReductionClauseWithNogroup(SemaRef, Clauses))
13583     return StmtError();
13584   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13585     return StmtError();
13586 
13587   return OMPParallelMaskedTaskLoopSimdDirective::Create(
13588       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13589 }
13590 
ActOnOpenMPDistributeDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13591 StmtResult SemaOpenMP::ActOnOpenMPDistributeDirective(
13592     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13593     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13594   if (!AStmt)
13595     return StmtError();
13596 
13597   if (!checkLastPrivateForMappedDirectives(Clauses))
13598     return StmtError();
13599 
13600   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13601   OMPLoopBasedDirective::HelperExprs B;
13602   // In presence of clause 'collapse' with number of loops, it will
13603   // define the nested loops number.
13604   unsigned NestedLoopCount =
13605       checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
13606                       nullptr /*ordered not a clause on distribute*/, AStmt,
13607                       SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13608   if (NestedLoopCount == 0)
13609     return StmtError();
13610 
13611   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13612          "omp for loop exprs were not built");
13613 
13614   SemaRef.setFunctionHasBranchProtectedScope();
13615   auto *DistributeDirective = OMPDistributeDirective::Create(
13616       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13617       DSAStack->getMappedDirective());
13618   return DistributeDirective;
13619 }
13620 
ActOnOpenMPDistributeParallelForDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13621 StmtResult SemaOpenMP::ActOnOpenMPDistributeParallelForDirective(
13622     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13623     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13624   if (!AStmt)
13625     return StmtError();
13626 
13627   CapturedStmt *CS =
13628       setBranchProtectedScope(SemaRef, OMPD_distribute_parallel_for, AStmt);
13629 
13630   OMPLoopBasedDirective::HelperExprs B;
13631   // In presence of clause 'collapse' with number of loops, it will
13632   // define the nested loops number.
13633   unsigned NestedLoopCount = checkOpenMPLoop(
13634       OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13635       nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13636       VarsWithImplicitDSA, B);
13637   if (NestedLoopCount == 0)
13638     return StmtError();
13639 
13640   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13641          "omp for loop exprs were not built");
13642 
13643   return OMPDistributeParallelForDirective::Create(
13644       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13645       DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13646 }
13647 
ActOnOpenMPDistributeParallelForSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13648 StmtResult SemaOpenMP::ActOnOpenMPDistributeParallelForSimdDirective(
13649     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13650     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13651   if (!AStmt)
13652     return StmtError();
13653 
13654   CapturedStmt *CS = setBranchProtectedScope(
13655       SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
13656 
13657   OMPLoopBasedDirective::HelperExprs B;
13658   // In presence of clause 'collapse' with number of loops, it will
13659   // define the nested loops number.
13660   unsigned NestedLoopCount = checkOpenMPLoop(
13661       OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13662       nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13663       VarsWithImplicitDSA, B);
13664   if (NestedLoopCount == 0)
13665     return StmtError();
13666 
13667   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13668     return StmtError();
13669 
13670   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13671     return StmtError();
13672 
13673   return OMPDistributeParallelForSimdDirective::Create(
13674       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13675 }
13676 
ActOnOpenMPDistributeSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13677 StmtResult SemaOpenMP::ActOnOpenMPDistributeSimdDirective(
13678     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13679     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13680   if (!AStmt)
13681     return StmtError();
13682 
13683   CapturedStmt *CS =
13684       setBranchProtectedScope(SemaRef, OMPD_distribute_simd, AStmt);
13685 
13686   OMPLoopBasedDirective::HelperExprs B;
13687   // In presence of clause 'collapse' with number of loops, it will
13688   // define the nested loops number.
13689   unsigned NestedLoopCount =
13690       checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
13691                       nullptr /*ordered not a clause on distribute*/, CS,
13692                       SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13693   if (NestedLoopCount == 0)
13694     return StmtError();
13695 
13696   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13697     return StmtError();
13698 
13699   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13700     return StmtError();
13701 
13702   return OMPDistributeSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13703                                             NestedLoopCount, Clauses, AStmt, B);
13704 }
13705 
ActOnOpenMPTargetParallelForSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13706 StmtResult SemaOpenMP::ActOnOpenMPTargetParallelForSimdDirective(
13707     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13708     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13709   if (!AStmt)
13710     return StmtError();
13711 
13712   CapturedStmt *CS =
13713       setBranchProtectedScope(SemaRef, OMPD_target_parallel_for_simd, AStmt);
13714 
13715   OMPLoopBasedDirective::HelperExprs B;
13716   // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13717   // define the nested loops number.
13718   unsigned NestedLoopCount = checkOpenMPLoop(
13719       OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
13720       getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13721       VarsWithImplicitDSA, B);
13722   if (NestedLoopCount == 0)
13723     return StmtError();
13724 
13725   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13726     return StmtError();
13727 
13728   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13729     return StmtError();
13730 
13731   return OMPTargetParallelForSimdDirective::Create(
13732       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13733 }
13734 
ActOnOpenMPTargetSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13735 StmtResult SemaOpenMP::ActOnOpenMPTargetSimdDirective(
13736     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13737     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13738   if (!AStmt)
13739     return StmtError();
13740 
13741   CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target_simd, AStmt);
13742 
13743   OMPLoopBasedDirective::HelperExprs B;
13744   // In presence of clause 'collapse' with number of loops, it will define the
13745   // nested loops number.
13746   unsigned NestedLoopCount =
13747       checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
13748                       getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13749                       VarsWithImplicitDSA, B);
13750   if (NestedLoopCount == 0)
13751     return StmtError();
13752 
13753   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13754     return StmtError();
13755 
13756   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13757     return StmtError();
13758 
13759   return OMPTargetSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13760                                         NestedLoopCount, Clauses, AStmt, B);
13761 }
13762 
ActOnOpenMPTeamsDistributeDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13763 StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeDirective(
13764     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13765     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13766   if (!AStmt)
13767     return StmtError();
13768 
13769   CapturedStmt *CS =
13770       setBranchProtectedScope(SemaRef, OMPD_teams_distribute, AStmt);
13771 
13772   OMPLoopBasedDirective::HelperExprs B;
13773   // In presence of clause 'collapse' with number of loops, it will
13774   // define the nested loops number.
13775   unsigned NestedLoopCount =
13776       checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
13777                       nullptr /*ordered not a clause on distribute*/, CS,
13778                       SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13779   if (NestedLoopCount == 0)
13780     return StmtError();
13781 
13782   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13783          "omp teams distribute loop exprs were not built");
13784 
13785   DSAStack->setParentTeamsRegionLoc(StartLoc);
13786 
13787   return OMPTeamsDistributeDirective::Create(
13788       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13789 }
13790 
ActOnOpenMPTeamsDistributeSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13791 StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeSimdDirective(
13792     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13793     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13794   if (!AStmt)
13795     return StmtError();
13796 
13797   CapturedStmt *CS =
13798       setBranchProtectedScope(SemaRef, OMPD_teams_distribute_simd, AStmt);
13799 
13800   OMPLoopBasedDirective::HelperExprs B;
13801   // In presence of clause 'collapse' with number of loops, it will
13802   // define the nested loops number.
13803   unsigned NestedLoopCount = checkOpenMPLoop(
13804       OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
13805       nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13806       VarsWithImplicitDSA, B);
13807   if (NestedLoopCount == 0)
13808     return StmtError();
13809 
13810   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13811     return StmtError();
13812 
13813   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13814     return StmtError();
13815 
13816   DSAStack->setParentTeamsRegionLoc(StartLoc);
13817 
13818   return OMPTeamsDistributeSimdDirective::Create(
13819       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13820 }
13821 
ActOnOpenMPTeamsDistributeParallelForSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13822 StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
13823     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13824     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13825   if (!AStmt)
13826     return StmtError();
13827 
13828   CapturedStmt *CS = setBranchProtectedScope(
13829       SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
13830 
13831   OMPLoopBasedDirective::HelperExprs B;
13832   // In presence of clause 'collapse' with number of loops, it will
13833   // define the nested loops number.
13834   unsigned NestedLoopCount = checkOpenMPLoop(
13835       OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13836       nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13837       VarsWithImplicitDSA, B);
13838   if (NestedLoopCount == 0)
13839     return StmtError();
13840 
13841   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13842     return StmtError();
13843 
13844   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13845     return StmtError();
13846 
13847   DSAStack->setParentTeamsRegionLoc(StartLoc);
13848 
13849   return OMPTeamsDistributeParallelForSimdDirective::Create(
13850       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13851 }
13852 
ActOnOpenMPTeamsDistributeParallelForDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13853 StmtResult SemaOpenMP::ActOnOpenMPTeamsDistributeParallelForDirective(
13854     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13855     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13856   if (!AStmt)
13857     return StmtError();
13858 
13859   CapturedStmt *CS = setBranchProtectedScope(
13860       SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
13861 
13862   OMPLoopBasedDirective::HelperExprs B;
13863   // In presence of clause 'collapse' with number of loops, it will
13864   // define the nested loops number.
13865   unsigned NestedLoopCount = checkOpenMPLoop(
13866       OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13867       nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13868       VarsWithImplicitDSA, B);
13869 
13870   if (NestedLoopCount == 0)
13871     return StmtError();
13872 
13873   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13874          "omp for loop exprs were not built");
13875 
13876   DSAStack->setParentTeamsRegionLoc(StartLoc);
13877 
13878   return OMPTeamsDistributeParallelForDirective::Create(
13879       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13880       DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13881 }
13882 
ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)13883 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDirective(
13884     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13885     SourceLocation EndLoc) {
13886   if (!AStmt)
13887     return StmtError();
13888 
13889   setBranchProtectedScope(SemaRef, OMPD_target_teams, AStmt);
13890 
13891   const OMPClause *BareClause = nullptr;
13892   bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) &&
13893                                          hasClauses(Clauses, OMPC_thread_limit);
13894   bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) {
13895     BareClause = C;
13896     return C->getClauseKind() == OMPC_ompx_bare;
13897   });
13898 
13899   if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
13900     Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
13901     return StmtError();
13902   }
13903 
13904   return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc,
13905                                          Clauses, AStmt);
13906 }
13907 
ActOnOpenMPTargetTeamsDistributeDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13908 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeDirective(
13909     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13910     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13911   if (!AStmt)
13912     return StmtError();
13913 
13914   CapturedStmt *CS =
13915       setBranchProtectedScope(SemaRef, OMPD_target_teams_distribute, AStmt);
13916 
13917   OMPLoopBasedDirective::HelperExprs B;
13918   // In presence of clause 'collapse' with number of loops, it will
13919   // define the nested loops number.
13920   unsigned NestedLoopCount = checkOpenMPLoop(
13921       OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
13922       nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13923       VarsWithImplicitDSA, B);
13924   if (NestedLoopCount == 0)
13925     return StmtError();
13926 
13927   assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13928          "omp target teams distribute loop exprs were not built");
13929 
13930   return OMPTargetTeamsDistributeDirective::Create(
13931       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13932 }
13933 
ActOnOpenMPTargetTeamsDistributeParallelForDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13934 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
13935     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13936     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13937   if (!AStmt)
13938     return StmtError();
13939 
13940   CapturedStmt *CS = setBranchProtectedScope(
13941       SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
13942 
13943   OMPLoopBasedDirective::HelperExprs B;
13944   // In presence of clause 'collapse' with number of loops, it will
13945   // define the nested loops number.
13946   unsigned NestedLoopCount = checkOpenMPLoop(
13947       OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13948       nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13949       VarsWithImplicitDSA, B);
13950   if (NestedLoopCount == 0)
13951     return StmtError();
13952 
13953   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13954     return StmtError();
13955 
13956   return OMPTargetTeamsDistributeParallelForDirective::Create(
13957       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13958       DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13959 }
13960 
ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13961 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
13962     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13963     SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13964   if (!AStmt)
13965     return StmtError();
13966 
13967   CapturedStmt *CS = setBranchProtectedScope(
13968       SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
13969 
13970   OMPLoopBasedDirective::HelperExprs B;
13971   // In presence of clause 'collapse' with number of loops, it will
13972   // define the nested loops number.
13973   unsigned NestedLoopCount =
13974       checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
13975                       getCollapseNumberExpr(Clauses),
13976                       nullptr /*ordered not a clause on distribute*/, CS,
13977                       SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13978   if (NestedLoopCount == 0)
13979     return StmtError();
13980 
13981   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13982     return StmtError();
13983 
13984   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
13985     return StmtError();
13986 
13987   return OMPTargetTeamsDistributeParallelForSimdDirective::Create(
13988       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13989 }
13990 
ActOnOpenMPTargetTeamsDistributeSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13991 StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeSimdDirective(
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_target_teams_distribute_simd, 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_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14005       nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14006       VarsWithImplicitDSA, B);
14007   if (NestedLoopCount == 0)
14008     return StmtError();
14009 
14010   if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14011     return StmtError();
14012 
14013   if (checkSimdlenSafelenSpecified(SemaRef, Clauses))
14014     return StmtError();
14015 
14016   return OMPTargetTeamsDistributeSimdDirective::Create(
14017       getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14018 }
14019 
checkTransformableLoopNest(OpenMPDirectiveKind Kind,Stmt * AStmt,int NumLoops,SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> & LoopHelpers,Stmt * & Body,SmallVectorImpl<SmallVector<Stmt *,0>> & OriginalInits)14020 bool SemaOpenMP::checkTransformableLoopNest(
14021     OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14022     SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers,
14023     Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *, 0>> &OriginalInits) {
14024   OriginalInits.emplace_back();
14025   bool Result = OMPLoopBasedDirective::doForAllLoops(
14026       AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14027       [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14028                                                         Stmt *CurStmt) {
14029         VarsWithInheritedDSAType TmpDSA;
14030         unsigned SingleNumLoops =
14031             checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14032                             TmpDSA, LoopHelpers[Cnt]);
14033         if (SingleNumLoops == 0)
14034           return true;
14035         assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14036         if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14037           OriginalInits.back().push_back(For->getInit());
14038           Body = For->getBody();
14039         } else {
14040           assert(isa<CXXForRangeStmt>(CurStmt) &&
14041                  "Expected canonical for or range-based for loops.");
14042           auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14043           OriginalInits.back().push_back(CXXFor->getBeginStmt());
14044           Body = CXXFor->getBody();
14045         }
14046         OriginalInits.emplace_back();
14047         return false;
14048       },
14049       [&OriginalInits](OMPLoopBasedDirective *Transform) {
14050         Stmt *DependentPreInits;
14051         if (auto *Dir = dyn_cast<OMPTileDirective>(Transform))
14052           DependentPreInits = Dir->getPreInits();
14053         else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
14054           DependentPreInits = Dir->getPreInits();
14055         else if (auto *Dir = dyn_cast<OMPReverseDirective>(Transform))
14056           DependentPreInits = Dir->getPreInits();
14057         else if (auto *Dir = dyn_cast<OMPInterchangeDirective>(Transform))
14058           DependentPreInits = Dir->getPreInits();
14059         else
14060           llvm_unreachable("Unhandled loop transformation");
14061 
14062         appendFlattenedStmtList(OriginalInits.back(), DependentPreInits);
14063       });
14064   assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14065   OriginalInits.pop_back();
14066   return Result;
14067 }
14068 
14069 /// 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)14070 static void addLoopPreInits(ASTContext &Context,
14071                             OMPLoopBasedDirective::HelperExprs &LoopHelper,
14072                             Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
14073                             SmallVectorImpl<Stmt *> &PreInits) {
14074 
14075   // For range-based for-statements, ensure that their syntactic sugar is
14076   // executed by adding them as pre-init statements.
14077   if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14078     Stmt *RangeInit = CXXRangeFor->getInit();
14079     if (RangeInit)
14080       PreInits.push_back(RangeInit);
14081 
14082     DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14083     PreInits.push_back(new (Context) DeclStmt(RangeStmt->getDeclGroup(),
14084                                               RangeStmt->getBeginLoc(),
14085                                               RangeStmt->getEndLoc()));
14086 
14087     DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14088     PreInits.push_back(new (Context) DeclStmt(RangeEnd->getDeclGroup(),
14089                                               RangeEnd->getBeginLoc(),
14090                                               RangeEnd->getEndLoc()));
14091   }
14092 
14093   llvm::append_range(PreInits, OriginalInit);
14094 
14095   // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
14096   if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
14097     PreInits.push_back(new (Context) DeclStmt(
14098         PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14099   }
14100 
14101   // Gather declarations for the data members used as counters.
14102   for (Expr *CounterRef : LoopHelper.Counters) {
14103     auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14104     if (isa<OMPCapturedExprDecl>(CounterDecl))
14105       PreInits.push_back(new (Context) DeclStmt(
14106           DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
14107   }
14108 }
14109 
14110 /// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
14111 /// loop of a construct.
collectLoopStmts(Stmt * AStmt,MutableArrayRef<Stmt * > LoopStmts)14112 static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) {
14113   size_t NumLoops = LoopStmts.size();
14114   OMPLoopBasedDirective::doForAllLoops(
14115       AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
14116       [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
14117         assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
14118         LoopStmts[Cnt] = CurStmt;
14119         return false;
14120       });
14121   assert(!is_contained(LoopStmts, nullptr) &&
14122          "Expecting a loop statement for each affected loop");
14123 }
14124 
ActOnOpenMPTileDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)14125 StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
14126                                                 Stmt *AStmt,
14127                                                 SourceLocation StartLoc,
14128                                                 SourceLocation EndLoc) {
14129   ASTContext &Context = getASTContext();
14130   Scope *CurScope = SemaRef.getCurScope();
14131 
14132   const auto *SizesClause =
14133       OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14134   if (!SizesClause ||
14135       llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; }))
14136     return StmtError();
14137   unsigned NumLoops = SizesClause->getNumSizes();
14138 
14139   // Empty statement should only be possible if there already was an error.
14140   if (!AStmt)
14141     return StmtError();
14142 
14143   // Verify and diagnose loop nest.
14144   SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
14145   Stmt *Body = nullptr;
14146   SmallVector<SmallVector<Stmt *, 0>, 4> OriginalInits;
14147   if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14148                                   OriginalInits))
14149     return StmtError();
14150 
14151   // Delay tiling to when template is completely instantiated.
14152   if (SemaRef.CurContext->isDependentContext())
14153     return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14154                                     NumLoops, AStmt, nullptr, nullptr);
14155 
14156   assert(LoopHelpers.size() == NumLoops &&
14157          "Expecting loop iteration space dimensionality to match number of "
14158          "affected loops");
14159   assert(OriginalInits.size() == NumLoops &&
14160          "Expecting loop iteration space dimensionality to match number of "
14161          "affected loops");
14162 
14163   // Collect all affected loop statements.
14164   SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14165   collectLoopStmts(AStmt, LoopStmts);
14166 
14167   SmallVector<Stmt *, 4> PreInits;
14168   CaptureVars CopyTransformer(SemaRef);
14169 
14170   // Create iteration variables for the generated loops.
14171   SmallVector<VarDecl *, 4> FloorIndVars;
14172   SmallVector<VarDecl *, 4> TileIndVars;
14173   FloorIndVars.resize(NumLoops);
14174   TileIndVars.resize(NumLoops);
14175   for (unsigned I = 0; I < NumLoops; ++I) {
14176     OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14177 
14178     assert(LoopHelper.Counters.size() == 1 &&
14179            "Expect single-dimensional loop iteration space");
14180     auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14181     std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14182     DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14183     QualType CntTy = IterVarRef->getType();
14184 
14185     // Iteration variable for the floor (i.e. outer) loop.
14186     {
14187       std::string FloorCntName =
14188           (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14189       VarDecl *FloorCntDecl =
14190           buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14191       FloorIndVars[I] = FloorCntDecl;
14192     }
14193 
14194     // Iteration variable for the tile (i.e. inner) loop.
14195     {
14196       std::string TileCntName =
14197           (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14198 
14199       // Reuse the iteration variable created by checkOpenMPLoop. It is also
14200       // used by the expressions to derive the original iteration variable's
14201       // value from the logical iteration number.
14202       auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14203       TileCntDecl->setDeclName(
14204           &SemaRef.PP.getIdentifierTable().get(TileCntName));
14205       TileIndVars[I] = TileCntDecl;
14206     }
14207 
14208     addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
14209                     PreInits);
14210   }
14211 
14212   // Once the original iteration values are set, append the innermost body.
14213   Stmt *Inner = Body;
14214 
14215   auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
14216                           SizesClause, CurScope](int I) -> Expr * {
14217     Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14218     if (isa<ConstantExpr>(DimTileSizeExpr))
14219       return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14220 
14221     // When the tile size is not a constant but a variable, it is possible to
14222     // pass non-positive numbers. For instance:
14223     // \code{c}
14224     //   int a = 0;
14225     //   #pragma omp tile sizes(a)
14226     //   for (int i = 0; i < 42; ++i)
14227     //     body(i);
14228     // \endcode
14229     // Although there is no meaningful interpretation of the tile size, the body
14230     // should still be executed 42 times to avoid surprises. To preserve the
14231     // invariant that every loop iteration is executed exactly once and not
14232     // cause an infinite loop, apply a minimum tile size of one.
14233     // Build expr:
14234     // \code{c}
14235     //   (TS <= 0) ? 1 : TS
14236     // \endcode
14237     QualType DimTy = DimTileSizeExpr->getType();
14238     uint64_t DimWidth = Context.getTypeSize(DimTy);
14239     IntegerLiteral *Zero = IntegerLiteral::Create(
14240         Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14241     IntegerLiteral *One =
14242         IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
14243     Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
14244         CurScope, {}, BO_LE,
14245         AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
14246     Expr *MinOne = new (Context) ConditionalOperator(
14247         Cond, {}, One, {},
14248         AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14249         VK_PRValue, OK_Ordinary);
14250     return MinOne;
14251   };
14252 
14253   // Create tile loops from the inside to the outside.
14254   for (int I = NumLoops - 1; I >= 0; --I) {
14255     OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14256     Expr *NumIterations = LoopHelper.NumIterations;
14257     auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14258     QualType IVTy = NumIterations->getType();
14259     Stmt *LoopStmt = LoopStmts[I];
14260 
14261     // Commonly used variables. One of the constraints of an AST is that every
14262     // node object must appear at most once, hence we define lamdas that create
14263     // a new AST node at every use.
14264     auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
14265                           OrigCntVar]() {
14266       return buildDeclRefExpr(SemaRef, TileIndVars[I], IVTy,
14267                               OrigCntVar->getExprLoc());
14268     };
14269     auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, IVTy,
14270                            OrigCntVar]() {
14271       return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14272                               OrigCntVar->getExprLoc());
14273     };
14274 
14275     // For init-statement: auto .tile.iv = .floor.iv
14276     SemaRef.AddInitializerToDecl(
14277         TileIndVars[I], SemaRef.DefaultLvalueConversion(MakeFloorIVRef()).get(),
14278         /*DirectInit=*/false);
14279     Decl *CounterDecl = TileIndVars[I];
14280     StmtResult InitStmt = new (Context)
14281         DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14282                  OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14283     if (!InitStmt.isUsable())
14284       return StmtError();
14285 
14286     // For cond-expression:
14287     //   .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
14288     ExprResult EndOfTile =
14289         SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14290                            MakeFloorIVRef(), MakeDimTileSize(I));
14291     if (!EndOfTile.isUsable())
14292       return StmtError();
14293     ExprResult IsPartialTile =
14294         SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14295                            NumIterations, EndOfTile.get());
14296     if (!IsPartialTile.isUsable())
14297       return StmtError();
14298     ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
14299         LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14300         IsPartialTile.get(), NumIterations, EndOfTile.get());
14301     if (!MinTileAndIterSpace.isUsable())
14302       return StmtError();
14303     ExprResult CondExpr =
14304         SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14305                            MakeTileIVRef(), MinTileAndIterSpace.get());
14306     if (!CondExpr.isUsable())
14307       return StmtError();
14308 
14309     // For incr-statement: ++.tile.iv
14310     ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14311         CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
14312     if (!IncrStmt.isUsable())
14313       return StmtError();
14314 
14315     // Statements to set the original iteration variable's value from the
14316     // logical iteration number.
14317     // Generated for loop is:
14318     // \code
14319     // Original_for_init;
14320     // for (auto .tile.iv = .floor.iv;
14321     //      .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
14322     //      ++.tile.iv) {
14323     //   Original_Body;
14324     //   Original_counter_update;
14325     // }
14326     // \endcode
14327     // FIXME: If the innermost body is an loop itself, inserting these
14328     // statements stops it being recognized  as a perfectly nested loop (e.g.
14329     // for applying tiling again). If this is the case, sink the expressions
14330     // further into the inner loop.
14331     SmallVector<Stmt *, 4> BodyParts;
14332     BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14333     if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14334       BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14335     BodyParts.push_back(Inner);
14336     Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
14337                                  Inner->getBeginLoc(), Inner->getEndLoc());
14338     Inner = new (Context)
14339         ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14340                 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14341                 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14342   }
14343 
14344   // Create floor loops from the inside to the outside.
14345   for (int I = NumLoops - 1; I >= 0; --I) {
14346     auto &LoopHelper = LoopHelpers[I];
14347     Expr *NumIterations = LoopHelper.NumIterations;
14348     DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14349     QualType IVTy = NumIterations->getType();
14350 
14351     // Commonly used variables. One of the constraints of an AST is that every
14352     // node object must appear at most once, hence we define lamdas that create
14353     // a new AST node at every use.
14354     auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, IVTy,
14355                            OrigCntVar]() {
14356       return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14357                               OrigCntVar->getExprLoc());
14358     };
14359 
14360     // For init-statement: auto .floor.iv = 0
14361     SemaRef.AddInitializerToDecl(
14362         FloorIndVars[I],
14363         SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14364         /*DirectInit=*/false);
14365     Decl *CounterDecl = FloorIndVars[I];
14366     StmtResult InitStmt = new (Context)
14367         DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14368                  OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14369     if (!InitStmt.isUsable())
14370       return StmtError();
14371 
14372     // For cond-expression: .floor.iv < NumIterations
14373     ExprResult CondExpr =
14374         SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14375                            MakeFloorIVRef(), NumIterations);
14376     if (!CondExpr.isUsable())
14377       return StmtError();
14378 
14379     // For incr-statement: .floor.iv += DimTileSize
14380     ExprResult IncrStmt =
14381         SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
14382                            MakeFloorIVRef(), MakeDimTileSize(I));
14383     if (!IncrStmt.isUsable())
14384       return StmtError();
14385 
14386     Inner = new (Context)
14387         ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14388                 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14389                 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14390   }
14391 
14392   return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
14393                                   AStmt, Inner,
14394                                   buildPreInits(Context, PreInits));
14395 }
14396 
ActOnOpenMPUnrollDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)14397 StmtResult SemaOpenMP::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses,
14398                                                   Stmt *AStmt,
14399                                                   SourceLocation StartLoc,
14400                                                   SourceLocation EndLoc) {
14401   ASTContext &Context = getASTContext();
14402   Scope *CurScope = SemaRef.getCurScope();
14403   // Empty statement should only be possible if there already was an error.
14404   if (!AStmt)
14405     return StmtError();
14406 
14407   if (checkMutuallyExclusiveClauses(SemaRef, Clauses,
14408                                     {OMPC_partial, OMPC_full}))
14409     return StmtError();
14410 
14411   const OMPFullClause *FullClause =
14412       OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
14413   const OMPPartialClause *PartialClause =
14414       OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
14415   assert(!(FullClause && PartialClause) &&
14416          "mutual exclusivity must have been checked before");
14417 
14418   constexpr unsigned NumLoops = 1;
14419   Stmt *Body = nullptr;
14420   SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
14421       NumLoops);
14422   SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
14423   if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
14424                                   Body, OriginalInits))
14425     return StmtError();
14426 
14427   unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
14428 
14429   // Delay unrolling to when template is completely instantiated.
14430   if (SemaRef.CurContext->isDependentContext())
14431     return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14432                                       NumGeneratedLoops, nullptr, nullptr);
14433 
14434   assert(LoopHelpers.size() == NumLoops &&
14435          "Expecting a single-dimensional loop iteration space");
14436   assert(OriginalInits.size() == NumLoops &&
14437          "Expecting a single-dimensional loop iteration space");
14438   OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
14439 
14440   if (FullClause) {
14441     if (!VerifyPositiveIntegerConstantInClause(
14442              LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
14443              /*SuppressExprDiags=*/true)
14444              .isUsable()) {
14445       Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
14446       Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
14447           << "#pragma omp unroll full";
14448       return StmtError();
14449     }
14450   }
14451 
14452   // The generated loop may only be passed to other loop-associated directive
14453   // when a partial clause is specified. Without the requirement it is
14454   // sufficient to generate loop unroll metadata at code-generation.
14455   if (NumGeneratedLoops == 0)
14456     return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14457                                       NumGeneratedLoops, nullptr, nullptr);
14458 
14459   // Otherwise, we need to provide a de-sugared/transformed AST that can be
14460   // associated with another loop directive.
14461   //
14462   // The canonical loop analysis return by checkTransformableLoopNest assumes
14463   // the following structure to be the same loop without transformations or
14464   // directives applied: \code OriginalInits; LoopHelper.PreInits;
14465   // LoopHelper.Counters;
14466   // for (; IV < LoopHelper.NumIterations; ++IV) {
14467   //   LoopHelper.Updates;
14468   //   Body;
14469   // }
14470   // \endcode
14471   // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
14472   // and referenced by LoopHelper.IterationVarRef.
14473   //
14474   // The unrolling directive transforms this into the following loop:
14475   // \code
14476   // OriginalInits;         \
14477   // LoopHelper.PreInits;    > NewPreInits
14478   // LoopHelper.Counters;   /
14479   // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
14480   //   #pragma clang loop unroll_count(Factor)
14481   //   for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
14482   //   {
14483   //     LoopHelper.Updates;
14484   //     Body;
14485   //   }
14486   // }
14487   // \endcode
14488   // where UIV is a new logical iteration counter. IV must be the same VarDecl
14489   // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
14490   // references it. If the partially unrolled loop is associated with another
14491   // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
14492   // analyze this loop, i.e. the outer loop must fulfill the constraints of an
14493   // OpenMP canonical loop. The inner loop is not an associable canonical loop
14494   // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
14495   // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
14496   // property of the OMPLoopBasedDirective instead of statements in
14497   // CompoundStatement. This is to allow the loop to become a non-outermost loop
14498   // of a canonical loop nest where these PreInits are emitted before the
14499   // outermost directive.
14500 
14501   // Find the loop statement.
14502   Stmt *LoopStmt = nullptr;
14503   collectLoopStmts(AStmt, {LoopStmt});
14504 
14505   // Determine the PreInit declarations.
14506   SmallVector<Stmt *, 4> PreInits;
14507   addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14508 
14509   auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14510   QualType IVTy = IterationVarRef->getType();
14511   assert(LoopHelper.Counters.size() == 1 &&
14512          "Expecting a single-dimensional loop iteration space");
14513   auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14514 
14515   // Determine the unroll factor.
14516   uint64_t Factor;
14517   SourceLocation FactorLoc;
14518   if (Expr *FactorVal = PartialClause->getFactor()) {
14519     Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
14520     FactorLoc = FactorVal->getExprLoc();
14521   } else {
14522     // TODO: Use a better profitability model.
14523     Factor = 2;
14524   }
14525   assert(Factor > 0 && "Expected positive unroll factor");
14526   auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
14527     return IntegerLiteral::Create(
14528         getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor),
14529         IVTy, FactorLoc);
14530   };
14531 
14532   // Iteration variable SourceLocations.
14533   SourceLocation OrigVarLoc = OrigVar->getExprLoc();
14534   SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
14535   SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
14536 
14537   // Internal variable names.
14538   std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14539   std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
14540   std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
14541   std::string InnerTripCountName =
14542       (Twine(".unroll_inner.tripcount.") + OrigVarName).str();
14543 
14544   // Create the iteration variable for the unrolled loop.
14545   VarDecl *OuterIVDecl =
14546       buildVarDecl(SemaRef, {}, IVTy, OuterIVName, nullptr, OrigVar);
14547   auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
14548     return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc);
14549   };
14550 
14551   // Iteration variable for the inner loop: Reuse the iteration variable created
14552   // by checkOpenMPLoop.
14553   auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14554   InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(InnerIVName));
14555   auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
14556     return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc);
14557   };
14558 
14559   // Make a copy of the NumIterations expression for each use: By the AST
14560   // constraints, every expression object in a DeclContext must be unique.
14561   CaptureVars CopyTransformer(SemaRef);
14562   auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
14563     return AssertSuccess(
14564         CopyTransformer.TransformExpr(LoopHelper.NumIterations));
14565   };
14566 
14567   // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
14568   ExprResult LValueConv = SemaRef.DefaultLvalueConversion(MakeOuterRef());
14569   SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(),
14570                                /*DirectInit=*/false);
14571   StmtResult InnerInit = new (Context)
14572       DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14573   if (!InnerInit.isUsable())
14574     return StmtError();
14575 
14576   // Inner For cond-expression:
14577   // \code
14578   //   .unroll_inner.iv < .unrolled.iv + Factor &&
14579   //   .unroll_inner.iv < NumIterations
14580   // \endcode
14581   // This conjunction of two conditions allows ScalarEvolution to derive the
14582   // maximum trip count of the inner loop.
14583   ExprResult EndOfTile =
14584       SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14585                          MakeOuterRef(), MakeFactorExpr());
14586   if (!EndOfTile.isUsable())
14587     return StmtError();
14588   ExprResult InnerCond1 =
14589       SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14590                          MakeInnerRef(), EndOfTile.get());
14591   if (!InnerCond1.isUsable())
14592     return StmtError();
14593   ExprResult InnerCond2 =
14594       SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14595                          MakeInnerRef(), MakeNumIterations());
14596   if (!InnerCond2.isUsable())
14597     return StmtError();
14598   ExprResult InnerCond =
14599       SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
14600                          InnerCond1.get(), InnerCond2.get());
14601   if (!InnerCond.isUsable())
14602     return StmtError();
14603 
14604   // Inner For incr-statement: ++.unroll_inner.iv
14605   ExprResult InnerIncr = SemaRef.BuildUnaryOp(
14606       CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
14607   if (!InnerIncr.isUsable())
14608     return StmtError();
14609 
14610   // Inner For statement.
14611   SmallVector<Stmt *> InnerBodyStmts;
14612   InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14613   if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14614     InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
14615   InnerBodyStmts.push_back(Body);
14616   CompoundStmt *InnerBody =
14617       CompoundStmt::Create(getASTContext(), InnerBodyStmts, FPOptionsOverride(),
14618                            Body->getBeginLoc(), Body->getEndLoc());
14619   ForStmt *InnerFor = new (Context)
14620       ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
14621               InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
14622               LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14623 
14624   // Unroll metadata for the inner loop.
14625   // This needs to take into account the remainder portion of the unrolled loop,
14626   // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
14627   // supports multiple loop exits. Instead, unroll using a factor equivalent to
14628   // the maximum trip count, which will also generate a remainder loop. Just
14629   // `unroll(enable)` (which could have been useful if the user has not
14630   // specified a concrete factor; even though the outer loop cannot be
14631   // influenced anymore, would avoid more code bloat than necessary) will refuse
14632   // the loop because "Won't unroll; remainder loop could not be generated when
14633   // assuming runtime trip count". Even if it did work, it must not choose a
14634   // larger unroll factor than the maximum loop length, or it would always just
14635   // execute the remainder loop.
14636   LoopHintAttr *UnrollHintAttr =
14637       LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
14638                                    LoopHintAttr::Numeric, MakeFactorExpr());
14639   AttributedStmt *InnerUnrolled = AttributedStmt::Create(
14640       getASTContext(), StartLoc, {UnrollHintAttr}, InnerFor);
14641 
14642   // Outer For init-statement: auto .unrolled.iv = 0
14643   SemaRef.AddInitializerToDecl(
14644       OuterIVDecl,
14645       SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14646       /*DirectInit=*/false);
14647   StmtResult OuterInit = new (Context)
14648       DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14649   if (!OuterInit.isUsable())
14650     return StmtError();
14651 
14652   // Outer For cond-expression: .unrolled.iv < NumIterations
14653   ExprResult OuterConde =
14654       SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14655                          MakeOuterRef(), MakeNumIterations());
14656   if (!OuterConde.isUsable())
14657     return StmtError();
14658 
14659   // Outer For incr-statement: .unrolled.iv += Factor
14660   ExprResult OuterIncr =
14661       SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
14662                          MakeOuterRef(), MakeFactorExpr());
14663   if (!OuterIncr.isUsable())
14664     return StmtError();
14665 
14666   // Outer For statement.
14667   ForStmt *OuterFor = new (Context)
14668       ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
14669               OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
14670               LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14671 
14672   return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14673                                     NumGeneratedLoops, OuterFor,
14674                                     buildPreInits(Context, PreInits));
14675 }
14676 
ActOnOpenMPReverseDirective(Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)14677 StmtResult SemaOpenMP::ActOnOpenMPReverseDirective(Stmt *AStmt,
14678                                                    SourceLocation StartLoc,
14679                                                    SourceLocation EndLoc) {
14680   ASTContext &Context = getASTContext();
14681   Scope *CurScope = SemaRef.getCurScope();
14682 
14683   // Empty statement should only be possible if there already was an error.
14684   if (!AStmt)
14685     return StmtError();
14686 
14687   constexpr unsigned NumLoops = 1;
14688   Stmt *Body = nullptr;
14689   SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
14690       NumLoops);
14691   SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
14692   if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
14693                                   Body, OriginalInits))
14694     return StmtError();
14695 
14696   // Delay applying the transformation to when template is completely
14697   // instantiated.
14698   if (SemaRef.CurContext->isDependentContext())
14699     return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
14700                                        nullptr, nullptr);
14701 
14702   assert(LoopHelpers.size() == NumLoops &&
14703          "Expecting a single-dimensional loop iteration space");
14704   assert(OriginalInits.size() == NumLoops &&
14705          "Expecting a single-dimensional loop iteration space");
14706   OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
14707 
14708   // Find the loop statement.
14709   Stmt *LoopStmt = nullptr;
14710   collectLoopStmts(AStmt, {LoopStmt});
14711 
14712   // Determine the PreInit declarations.
14713   SmallVector<Stmt *> PreInits;
14714   addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14715 
14716   auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14717   QualType IVTy = IterationVarRef->getType();
14718   uint64_t IVWidth = Context.getTypeSize(IVTy);
14719   auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14720 
14721   // Iteration variable SourceLocations.
14722   SourceLocation OrigVarLoc = OrigVar->getExprLoc();
14723   SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
14724   SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
14725 
14726   // Locations pointing to the transformation.
14727   SourceLocation TransformLoc = StartLoc;
14728   SourceLocation TransformLocBegin = StartLoc;
14729   SourceLocation TransformLocEnd = EndLoc;
14730 
14731   // Internal variable names.
14732   std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14733   SmallString<64> ForwardIVName(".forward.iv.");
14734   ForwardIVName += OrigVarName;
14735   SmallString<64> ReversedIVName(".reversed.iv.");
14736   ReversedIVName += OrigVarName;
14737 
14738   // LoopHelper.Updates will read the logical iteration number from
14739   // LoopHelper.IterationVarRef, compute the value of the user loop counter of
14740   // that logical iteration from it, then assign it to the user loop counter
14741   // variable. We cannot directly use LoopHelper.IterationVarRef as the
14742   // induction variable of the generated loop because it may cause an underflow:
14743   // \code{.c}
14744   //   for (unsigned i = 0; i < n; ++i)
14745   //     body(i);
14746   // \endcode
14747   //
14748   // Naive reversal:
14749   // \code{.c}
14750   //   for (unsigned i = n-1; i >= 0; --i)
14751   //     body(i);
14752   // \endcode
14753   //
14754   // Instead, we introduce a new iteration variable representing the logical
14755   // iteration counter of the original loop, convert it to the logical iteration
14756   // number of the reversed loop, then let LoopHelper.Updates compute the user's
14757   // loop iteration variable from it.
14758   // \code{.cpp}
14759   //   for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
14760   //     auto .reversed.iv = n - .forward.iv - 1;
14761   //     i = (.reversed.iv + 0) * 1;                // LoopHelper.Updates
14762   //     body(i);                                   // Body
14763   //   }
14764   // \endcode
14765 
14766   // Subexpressions with more than one use. One of the constraints of an AST is
14767   // that every node object must appear at most once, hence we define a lambda
14768   // that creates a new AST node at every use.
14769   CaptureVars CopyTransformer(SemaRef);
14770   auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
14771     return AssertSuccess(
14772         CopyTransformer.TransformExpr(LoopHelper.NumIterations));
14773   };
14774 
14775   // Create the iteration variable for the forward loop (from 0 to n-1).
14776   VarDecl *ForwardIVDecl =
14777       buildVarDecl(SemaRef, {}, IVTy, ForwardIVName, nullptr, OrigVar);
14778   auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
14779                          OrigVarLoc]() {
14780     return buildDeclRefExpr(SemaRef, ForwardIVDecl, IVTy, OrigVarLoc);
14781   };
14782 
14783   // Iteration variable for the reversed induction variable (from n-1 downto 0):
14784   // Reuse the iteration variable created by checkOpenMPLoop.
14785   auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14786   ReversedIVDecl->setDeclName(
14787       &SemaRef.PP.getIdentifierTable().get(ReversedIVName));
14788 
14789   // For init-statement:
14790   // \code{.cpp}
14791   //   auto .forward.iv = 0;
14792   // \endcode
14793   auto *Zero = IntegerLiteral::Create(Context, llvm::APInt::getZero(IVWidth),
14794                                       ForwardIVDecl->getType(), OrigVarLoc);
14795   SemaRef.AddInitializerToDecl(ForwardIVDecl, Zero, /*DirectInit=*/false);
14796   StmtResult Init = new (Context)
14797       DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14798   if (!Init.isUsable())
14799     return StmtError();
14800 
14801   // Forward iv cond-expression:
14802   // \code{.cpp}
14803   //   .forward.iv < MakeNumIterations()
14804   // \endcode
14805   ExprResult Cond =
14806       SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14807                          MakeForwardRef(), MakeNumIterations());
14808   if (!Cond.isUsable())
14809     return StmtError();
14810 
14811   // Forward incr-statement:
14812   // \code{.c}
14813   //   ++.forward.iv
14814   // \endcode
14815   ExprResult Incr = SemaRef.BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
14816                                          UO_PreInc, MakeForwardRef());
14817   if (!Incr.isUsable())
14818     return StmtError();
14819 
14820   // Reverse the forward-iv:
14821   // \code{.cpp}
14822   //   auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
14823   // \endcode
14824   auto *One = IntegerLiteral::Create(Context, llvm::APInt(IVWidth, 1), IVTy,
14825                                      TransformLoc);
14826   ExprResult Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub,
14827                                         MakeNumIterations(), One);
14828   if (!Minus.isUsable())
14829     return StmtError();
14830   Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.get(),
14831                              MakeForwardRef());
14832   if (!Minus.isUsable())
14833     return StmtError();
14834   StmtResult InitReversed = new (Context) DeclStmt(
14835       DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
14836   if (!InitReversed.isUsable())
14837     return StmtError();
14838   SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.get(),
14839                                /*DirectInit=*/false);
14840 
14841   // The new loop body.
14842   SmallVector<Stmt *, 4> BodyStmts;
14843   BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
14844                     (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
14845   BodyStmts.push_back(InitReversed.get());
14846   llvm::append_range(BodyStmts, LoopHelper.Updates);
14847   if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14848     BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
14849   BodyStmts.push_back(Body);
14850   auto *ReversedBody =
14851       CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
14852                            Body->getBeginLoc(), Body->getEndLoc());
14853 
14854   // Finally create the reversed For-statement.
14855   auto *ReversedFor = new (Context)
14856       ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
14857               ReversedBody, LoopHelper.Init->getBeginLoc(),
14858               LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14859   return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
14860                                      ReversedFor,
14861                                      buildPreInits(Context, PreInits));
14862 }
14863 
ActOnOpenMPInterchangeDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)14864 StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective(
14865     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14866     SourceLocation EndLoc) {
14867   ASTContext &Context = getASTContext();
14868   DeclContext *CurContext = SemaRef.CurContext;
14869   Scope *CurScope = SemaRef.getCurScope();
14870 
14871   // Empty statement should only be possible if there already was an error.
14872   if (!AStmt)
14873     return StmtError();
14874 
14875   // interchange without permutation clause swaps two loops.
14876   constexpr size_t NumLoops = 2;
14877 
14878   // Verify and diagnose loop nest.
14879   SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
14880   Stmt *Body = nullptr;
14881   SmallVector<SmallVector<Stmt *, 0>, 2> OriginalInits;
14882   if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
14883                                   LoopHelpers, Body, OriginalInits))
14884     return StmtError();
14885 
14886   // Delay interchange to when template is completely instantiated.
14887   if (CurContext->isDependentContext())
14888     return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
14889                                            NumLoops, AStmt, nullptr, nullptr);
14890 
14891   assert(LoopHelpers.size() == NumLoops &&
14892          "Expecting loop iteration space dimensionaly to match number of "
14893          "affected loops");
14894   assert(OriginalInits.size() == NumLoops &&
14895          "Expecting loop iteration space dimensionaly to match number of "
14896          "affected loops");
14897 
14898   // Decode the permutation clause.
14899   constexpr uint64_t Permutation[] = {1, 0};
14900 
14901   // Find the affected loops.
14902   SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14903   collectLoopStmts(AStmt, LoopStmts);
14904 
14905   // Collect pre-init statements on the order before the permuation.
14906   SmallVector<Stmt *> PreInits;
14907   for (auto I : llvm::seq<int>(NumLoops)) {
14908     OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14909 
14910     assert(LoopHelper.Counters.size() == 1 &&
14911            "Single-dimensional loop iteration space expected");
14912     auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14913 
14914     std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14915     addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
14916                     PreInits);
14917   }
14918 
14919   SmallVector<VarDecl *> PermutedIndVars(NumLoops);
14920   CaptureVars CopyTransformer(SemaRef);
14921 
14922   // Create the permuted loops from the inside to the outside of the
14923   // interchanged loop nest. Body of the innermost new loop is the original
14924   // innermost body.
14925   Stmt *Inner = Body;
14926   for (auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
14927     // Get the original loop that belongs to this new position.
14928     uint64_t SourceIdx = Permutation[TargetIdx];
14929     OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
14930     Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
14931     assert(SourceHelper.Counters.size() == 1 &&
14932            "Single-dimensional loop iteration space expected");
14933     auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.Counters.front());
14934 
14935     // Normalized loop counter variable: From 0 to n-1, always an integer type.
14936     DeclRefExpr *IterVarRef = cast<DeclRefExpr>(SourceHelper.IterationVarRef);
14937     QualType IVTy = IterVarRef->getType();
14938     assert(IVTy->isIntegerType() &&
14939            "Expected the logical iteration counter to be an integer");
14940 
14941     std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14942     SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
14943 
14944     // Make a copy of the NumIterations expression for each use: By the AST
14945     // constraints, every expression object in a DeclContext must be unique.
14946     auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
14947       return AssertSuccess(
14948           CopyTransformer.TransformExpr(SourceHelper.NumIterations));
14949     };
14950 
14951     // Iteration variable for the permuted loop. Reuse the one from
14952     // checkOpenMPLoop which will also be used to update the original loop
14953     // variable.
14954     SmallString<64> PermutedCntName(".permuted_");
14955     PermutedCntName.append({llvm::utostr(TargetIdx), ".iv.", OrigVarName});
14956     auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14957     PermutedCntDecl->setDeclName(
14958         &SemaRef.PP.getIdentifierTable().get(PermutedCntName));
14959     PermutedIndVars[TargetIdx] = PermutedCntDecl;
14960     auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
14961       return buildDeclRefExpr(SemaRef, PermutedCntDecl, IVTy, OrigVarLoc);
14962     };
14963 
14964     // For init-statement:
14965     // \code
14966     //   auto .permuted_{target}.iv = 0
14967     // \endcode
14968     ExprResult Zero = SemaRef.ActOnIntegerConstant(OrigVarLoc, 0);
14969     if (!Zero.isUsable())
14970       return StmtError();
14971     SemaRef.AddInitializerToDecl(PermutedCntDecl, Zero.get(),
14972                                  /*DirectInit=*/false);
14973     StmtResult InitStmt = new (Context)
14974         DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
14975                  OrigCntVar->getEndLoc());
14976     if (!InitStmt.isUsable())
14977       return StmtError();
14978 
14979     // For cond-expression:
14980     // \code
14981     //   .permuted_{target}.iv < MakeNumIterations()
14982     // \endcode
14983     ExprResult CondExpr =
14984         SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
14985                            MakePermutedRef(), MakeNumIterations());
14986     if (!CondExpr.isUsable())
14987       return StmtError();
14988 
14989     // For incr-statement:
14990     // \code
14991     //   ++.tile.iv
14992     // \endcode
14993     ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14994         CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
14995     if (!IncrStmt.isUsable())
14996       return StmtError();
14997 
14998     SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
14999                                      SourceHelper.Updates.end());
15000     if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
15001       BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15002     BodyParts.push_back(Inner);
15003     Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15004                                  Inner->getBeginLoc(), Inner->getEndLoc());
15005     Inner = new (Context) ForStmt(
15006         Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
15007         SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
15008         SourceHelper.Inc->getEndLoc());
15009   }
15010 
15011   return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15012                                          NumLoops, AStmt, Inner,
15013                                          buildPreInits(Context, PreInits));
15014 }
15015 
ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,Expr * Expr,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)15016 OMPClause *SemaOpenMP::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
15017                                                    Expr *Expr,
15018                                                    SourceLocation StartLoc,
15019                                                    SourceLocation LParenLoc,
15020                                                    SourceLocation EndLoc) {
15021   OMPClause *Res = nullptr;
15022   switch (Kind) {
15023   case OMPC_final:
15024     Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
15025     break;
15026   case OMPC_num_threads:
15027     Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
15028     break;
15029   case OMPC_safelen:
15030     Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
15031     break;
15032   case OMPC_simdlen:
15033     Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
15034     break;
15035   case OMPC_allocator:
15036     Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
15037     break;
15038   case OMPC_collapse:
15039     Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
15040     break;
15041   case OMPC_ordered:
15042     Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
15043     break;
15044   case OMPC_num_teams:
15045     Res = ActOnOpenMPNumTeamsClause(Expr, StartLoc, LParenLoc, EndLoc);
15046     break;
15047   case OMPC_thread_limit:
15048     Res = ActOnOpenMPThreadLimitClause(Expr, StartLoc, LParenLoc, EndLoc);
15049     break;
15050   case OMPC_priority:
15051     Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
15052     break;
15053   case OMPC_hint:
15054     Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
15055     break;
15056   case OMPC_depobj:
15057     Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
15058     break;
15059   case OMPC_detach:
15060     Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
15061     break;
15062   case OMPC_novariants:
15063     Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
15064     break;
15065   case OMPC_nocontext:
15066     Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
15067     break;
15068   case OMPC_filter:
15069     Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
15070     break;
15071   case OMPC_partial:
15072     Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
15073     break;
15074   case OMPC_message:
15075     Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
15076     break;
15077   case OMPC_align:
15078     Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
15079     break;
15080   case OMPC_ompx_dyn_cgroup_mem:
15081     Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
15082     break;
15083   case OMPC_grainsize:
15084   case OMPC_num_tasks:
15085   case OMPC_device:
15086   case OMPC_if:
15087   case OMPC_default:
15088   case OMPC_proc_bind:
15089   case OMPC_schedule:
15090   case OMPC_private:
15091   case OMPC_firstprivate:
15092   case OMPC_lastprivate:
15093   case OMPC_shared:
15094   case OMPC_reduction:
15095   case OMPC_task_reduction:
15096   case OMPC_in_reduction:
15097   case OMPC_linear:
15098   case OMPC_aligned:
15099   case OMPC_copyin:
15100   case OMPC_copyprivate:
15101   case OMPC_nowait:
15102   case OMPC_untied:
15103   case OMPC_mergeable:
15104   case OMPC_threadprivate:
15105   case OMPC_sizes:
15106   case OMPC_allocate:
15107   case OMPC_flush:
15108   case OMPC_read:
15109   case OMPC_write:
15110   case OMPC_update:
15111   case OMPC_capture:
15112   case OMPC_compare:
15113   case OMPC_seq_cst:
15114   case OMPC_acq_rel:
15115   case OMPC_acquire:
15116   case OMPC_release:
15117   case OMPC_relaxed:
15118   case OMPC_depend:
15119   case OMPC_threads:
15120   case OMPC_simd:
15121   case OMPC_map:
15122   case OMPC_nogroup:
15123   case OMPC_dist_schedule:
15124   case OMPC_defaultmap:
15125   case OMPC_unknown:
15126   case OMPC_uniform:
15127   case OMPC_to:
15128   case OMPC_from:
15129   case OMPC_use_device_ptr:
15130   case OMPC_use_device_addr:
15131   case OMPC_is_device_ptr:
15132   case OMPC_unified_address:
15133   case OMPC_unified_shared_memory:
15134   case OMPC_reverse_offload:
15135   case OMPC_dynamic_allocators:
15136   case OMPC_atomic_default_mem_order:
15137   case OMPC_device_type:
15138   case OMPC_match:
15139   case OMPC_nontemporal:
15140   case OMPC_order:
15141   case OMPC_at:
15142   case OMPC_severity:
15143   case OMPC_destroy:
15144   case OMPC_inclusive:
15145   case OMPC_exclusive:
15146   case OMPC_uses_allocators:
15147   case OMPC_affinity:
15148   case OMPC_when:
15149   case OMPC_bind:
15150   default:
15151     llvm_unreachable("Clause is not allowed.");
15152   }
15153   return Res;
15154 }
15155 
15156 // An OpenMP directive such as 'target parallel' has two captured regions:
15157 // for the 'target' and 'parallel' respectively.  This function returns
15158 // the region in which to capture expressions associated with a clause.
15159 // A return value of OMPD_unknown signifies that the expression should not
15160 // be captured.
getOpenMPCaptureRegionForClause(OpenMPDirectiveKind DKind,OpenMPClauseKind CKind,unsigned OpenMPVersion,OpenMPDirectiveKind NameModifier=OMPD_unknown)15161 static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
15162     OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15163     OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15164   assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
15165          "Invalid directive with CKind-clause");
15166 
15167   // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
15168   if (NameModifier != OMPD_unknown &&
15169       !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
15170     return OMPD_unknown;
15171 
15172   ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(DKind);
15173 
15174   // [5.2:341:24-30]
15175   // If the clauses have expressions on them, such as for various clauses where
15176   // the argument of the clause is an expression, or lower-bound, length, or
15177   // stride expressions inside array sections (or subscript and stride
15178   // expressions in subscript-triplet for Fortran), or linear-step or alignment
15179   // expressions, the expressions are evaluated immediately before the construct
15180   // to which the clause has been split or duplicated per the above rules
15181   // (therefore inside of the outer leaf constructs). However, the expressions
15182   // inside the num_teams and thread_limit clauses are always evaluated before
15183   // the outermost leaf construct.
15184 
15185   // Process special cases first.
15186   switch (CKind) {
15187   case OMPC_if:
15188     switch (DKind) {
15189     case OMPD_teams_loop:
15190     case OMPD_target_teams_loop:
15191       // For [target] teams loop, assume capture region is 'teams' so it's
15192       // available for codegen later to use if/when necessary.
15193       return OMPD_teams;
15194     case OMPD_target_update:
15195     case OMPD_target_enter_data:
15196     case OMPD_target_exit_data:
15197       return OMPD_task;
15198     default:
15199       break;
15200     }
15201     break;
15202   case OMPC_num_teams:
15203   case OMPC_thread_limit:
15204   case OMPC_ompx_dyn_cgroup_mem:
15205     if (Leafs[0] == OMPD_target)
15206       return OMPD_target;
15207     break;
15208   case OMPC_device:
15209     if (Leafs[0] == OMPD_target ||
15210         llvm::is_contained({OMPD_dispatch, OMPD_target_update,
15211                             OMPD_target_enter_data, OMPD_target_exit_data},
15212                            DKind))
15213       return OMPD_task;
15214     break;
15215   case OMPC_novariants:
15216   case OMPC_nocontext:
15217     if (DKind == OMPD_dispatch)
15218       return OMPD_task;
15219     break;
15220   case OMPC_when:
15221     if (DKind == OMPD_metadirective)
15222       return OMPD_metadirective;
15223     break;
15224   case OMPC_filter:
15225     return OMPD_unknown;
15226   default:
15227     break;
15228   }
15229 
15230   // If none of the special cases above applied, and DKind is a capturing
15231   // directive, find the innermost enclosing leaf construct that allows the
15232   // clause, and returns the corresponding capture region.
15233 
15234   auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
15235     // Find the index in "Leafs" of the last leaf that allows the given
15236     // clause. The search will only include indexes [0, EndIdx).
15237     // EndIdx may be set to the index of the NameModifier, if present.
15238     int InnermostIdx = [&]() {
15239       for (int I = EndIdx - 1; I >= 0; --I) {
15240         if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
15241           return I;
15242       }
15243       return -1;
15244     }();
15245 
15246     // Find the nearest enclosing capture region.
15247     SmallVector<OpenMPDirectiveKind, 2> Regions;
15248     for (int I = InnermostIdx - 1; I >= 0; --I) {
15249       if (!isOpenMPCapturingDirective(Leafs[I]))
15250         continue;
15251       Regions.clear();
15252       getOpenMPCaptureRegions(Regions, Leafs[I]);
15253       if (Regions[0] != OMPD_unknown)
15254         return Regions.back();
15255     }
15256     return OMPD_unknown;
15257   };
15258 
15259   if (isOpenMPCapturingDirective(DKind)) {
15260     auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
15261       for (int I = 0, E = Leafs.size(); I != E; ++I) {
15262         if (Leafs[I] == Dir)
15263           return I + 1;
15264       }
15265       return 0;
15266     };
15267 
15268     int End = NameModifier == OMPD_unknown ? Leafs.size()
15269                                            : GetLeafIndex(NameModifier);
15270     return GetEnclosingRegion(End, CKind);
15271   }
15272 
15273   return OMPD_unknown;
15274 }
15275 
ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,Expr * Condition,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation NameModifierLoc,SourceLocation ColonLoc,SourceLocation EndLoc)15276 OMPClause *SemaOpenMP::ActOnOpenMPIfClause(
15277     OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
15278     SourceLocation LParenLoc, SourceLocation NameModifierLoc,
15279     SourceLocation ColonLoc, SourceLocation EndLoc) {
15280   Expr *ValExpr = Condition;
15281   Stmt *HelperValStmt = nullptr;
15282   OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15283   if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
15284       !Condition->isInstantiationDependent() &&
15285       !Condition->containsUnexpandedParameterPack()) {
15286     ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
15287     if (Val.isInvalid())
15288       return nullptr;
15289 
15290     ValExpr = Val.get();
15291 
15292     OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15293     CaptureRegion = getOpenMPCaptureRegionForClause(
15294         DKind, OMPC_if, getLangOpts().OpenMP, NameModifier);
15295     if (CaptureRegion != OMPD_unknown &&
15296         !SemaRef.CurContext->isDependentContext()) {
15297       ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15298       llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15299       ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15300       HelperValStmt = buildPreInits(getASTContext(), Captures);
15301     }
15302   }
15303 
15304   return new (getASTContext())
15305       OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
15306                   LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
15307 }
15308 
ActOnOpenMPFinalClause(Expr * Condition,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)15309 OMPClause *SemaOpenMP::ActOnOpenMPFinalClause(Expr *Condition,
15310                                               SourceLocation StartLoc,
15311                                               SourceLocation LParenLoc,
15312                                               SourceLocation EndLoc) {
15313   Expr *ValExpr = Condition;
15314   Stmt *HelperValStmt = nullptr;
15315   OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15316   if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
15317       !Condition->isInstantiationDependent() &&
15318       !Condition->containsUnexpandedParameterPack()) {
15319     ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
15320     if (Val.isInvalid())
15321       return nullptr;
15322 
15323     ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
15324 
15325     OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15326     CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final,
15327                                                     getLangOpts().OpenMP);
15328     if (CaptureRegion != OMPD_unknown &&
15329         !SemaRef.CurContext->isDependentContext()) {
15330       ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15331       llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15332       ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15333       HelperValStmt = buildPreInits(getASTContext(), Captures);
15334     }
15335   }
15336 
15337   return new (getASTContext()) OMPFinalClause(
15338       ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15339 }
15340 
15341 ExprResult
PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,Expr * Op)15342 SemaOpenMP::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
15343                                                    Expr *Op) {
15344   if (!Op)
15345     return ExprError();
15346 
15347   class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
15348   public:
15349     IntConvertDiagnoser()
15350         : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {}
15351     SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
15352                                          QualType T) override {
15353       return S.Diag(Loc, diag::err_omp_not_integral) << T;
15354     }
15355     SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
15356                                              QualType T) override {
15357       return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
15358     }
15359     SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
15360                                                QualType T,
15361                                                QualType ConvTy) override {
15362       return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
15363     }
15364     SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
15365                                            QualType ConvTy) override {
15366       return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
15367              << ConvTy->isEnumeralType() << ConvTy;
15368     }
15369     SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
15370                                             QualType T) override {
15371       return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
15372     }
15373     SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
15374                                         QualType ConvTy) override {
15375       return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
15376              << ConvTy->isEnumeralType() << ConvTy;
15377     }
15378     SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
15379                                              QualType) override {
15380       llvm_unreachable("conversion functions are permitted");
15381     }
15382   } ConvertDiagnoser;
15383   return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
15384 }
15385 
15386 static bool
isNonNegativeIntegerValue(Expr * & ValExpr,Sema & SemaRef,OpenMPClauseKind CKind,bool StrictlyPositive,bool BuildCapture=false,OpenMPDirectiveKind DKind=OMPD_unknown,OpenMPDirectiveKind * CaptureRegion=nullptr,Stmt ** HelperValStmt=nullptr)15387 isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind,
15388                           bool StrictlyPositive, bool BuildCapture = false,
15389                           OpenMPDirectiveKind DKind = OMPD_unknown,
15390                           OpenMPDirectiveKind *CaptureRegion = nullptr,
15391                           Stmt **HelperValStmt = nullptr) {
15392   if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
15393       !ValExpr->isInstantiationDependent()) {
15394     SourceLocation Loc = ValExpr->getExprLoc();
15395     ExprResult Value =
15396         SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
15397     if (Value.isInvalid())
15398       return false;
15399 
15400     ValExpr = Value.get();
15401     // The expression must evaluate to a non-negative integer value.
15402     if (std::optional<llvm::APSInt> Result =
15403             ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
15404       if (Result->isSigned() &&
15405           !((!StrictlyPositive && Result->isNonNegative()) ||
15406             (StrictlyPositive && Result->isStrictlyPositive()))) {
15407         SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
15408             << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
15409             << ValExpr->getSourceRange();
15410         return false;
15411       }
15412     }
15413     if (!BuildCapture)
15414       return true;
15415     *CaptureRegion =
15416         getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
15417     if (*CaptureRegion != OMPD_unknown &&
15418         !SemaRef.CurContext->isDependentContext()) {
15419       ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15420       llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15421       ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15422       *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
15423     }
15424   }
15425   return true;
15426 }
15427 
ActOnOpenMPNumThreadsClause(Expr * NumThreads,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)15428 OMPClause *SemaOpenMP::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
15429                                                    SourceLocation StartLoc,
15430                                                    SourceLocation LParenLoc,
15431                                                    SourceLocation EndLoc) {
15432   Expr *ValExpr = NumThreads;
15433   Stmt *HelperValStmt = nullptr;
15434 
15435   // OpenMP [2.5, Restrictions]
15436   //  The num_threads expression must evaluate to a positive integer value.
15437   if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads,
15438                                  /*StrictlyPositive=*/true))
15439     return nullptr;
15440 
15441   OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15442   OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
15443       DKind, OMPC_num_threads, getLangOpts().OpenMP);
15444   if (CaptureRegion != OMPD_unknown &&
15445       !SemaRef.CurContext->isDependentContext()) {
15446     ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15447     llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15448     ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15449     HelperValStmt = buildPreInits(getASTContext(), Captures);
15450   }
15451 
15452   return new (getASTContext()) OMPNumThreadsClause(
15453       ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15454 }
15455 
VerifyPositiveIntegerConstantInClause(Expr * E,OpenMPClauseKind CKind,bool StrictlyPositive,bool SuppressExprDiags)15456 ExprResult SemaOpenMP::VerifyPositiveIntegerConstantInClause(
15457     Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
15458     bool SuppressExprDiags) {
15459   if (!E)
15460     return ExprError();
15461   if (E->isValueDependent() || E->isTypeDependent() ||
15462       E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
15463     return E;
15464 
15465   llvm::APSInt Result;
15466   ExprResult ICE;
15467   if (SuppressExprDiags) {
15468     // Use a custom diagnoser that suppresses 'note' diagnostics about the
15469     // expression.
15470     struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
15471       SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
15472       SemaBase::SemaDiagnosticBuilder
15473       diagnoseNotICE(Sema &S, SourceLocation Loc) override {
15474         llvm_unreachable("Diagnostic suppressed");
15475       }
15476     } Diagnoser;
15477     ICE = SemaRef.VerifyIntegerConstantExpression(E, &Result, Diagnoser,
15478                                                   Sema::AllowFold);
15479   } else {
15480     ICE = SemaRef.VerifyIntegerConstantExpression(E, &Result,
15481                                                   /*FIXME*/ Sema::AllowFold);
15482   }
15483   if (ICE.isInvalid())
15484     return ExprError();
15485 
15486   if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
15487       (!StrictlyPositive && !Result.isNonNegative())) {
15488     Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
15489         << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
15490         << E->getSourceRange();
15491     return ExprError();
15492   }
15493   if ((CKind == OMPC_aligned || CKind == OMPC_align) && !Result.isPowerOf2()) {
15494     Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
15495         << E->getSourceRange();
15496     return ExprError();
15497   }
15498   if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
15499     DSAStack->setAssociatedLoops(Result.getExtValue());
15500   else if (CKind == OMPC_ordered)
15501     DSAStack->setAssociatedLoops(Result.getExtValue());
15502   return ICE;
15503 }
15504 
ActOnOpenMPSafelenClause(Expr * Len,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)15505 OMPClause *SemaOpenMP::ActOnOpenMPSafelenClause(Expr *Len,
15506                                                 SourceLocation StartLoc,
15507                                                 SourceLocation LParenLoc,
15508                                                 SourceLocation EndLoc) {
15509   // OpenMP [2.8.1, simd construct, Description]
15510   // The parameter of the safelen clause must be a constant
15511   // positive integer expression.
15512   ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
15513   if (Safelen.isInvalid())
15514     return nullptr;
15515   return new (getASTContext())
15516       OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
15517 }
15518 
ActOnOpenMPSimdlenClause(Expr * Len,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)15519 OMPClause *SemaOpenMP::ActOnOpenMPSimdlenClause(Expr *Len,
15520                                                 SourceLocation StartLoc,
15521                                                 SourceLocation LParenLoc,
15522                                                 SourceLocation EndLoc) {
15523   // OpenMP [2.8.1, simd construct, Description]
15524   // The parameter of the simdlen clause must be a constant
15525   // positive integer expression.
15526   ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
15527   if (Simdlen.isInvalid())
15528     return nullptr;
15529   return new (getASTContext())
15530       OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
15531 }
15532 
15533 /// Tries to find omp_allocator_handle_t type.
findOMPAllocatorHandleT(Sema & S,SourceLocation Loc,DSAStackTy * Stack)15534 static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc,
15535                                     DSAStackTy *Stack) {
15536   if (!Stack->getOMPAllocatorHandleT().isNull())
15537     return true;
15538 
15539   // Set the allocator handle type.
15540   IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
15541   ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
15542   if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
15543     S.Diag(Loc, diag::err_omp_implied_type_not_found)
15544         << "omp_allocator_handle_t";
15545     return false;
15546   }
15547   QualType AllocatorHandleEnumTy = PT.get();
15548   AllocatorHandleEnumTy.addConst();
15549   Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
15550 
15551   // Fill the predefined allocator map.
15552   bool ErrorFound = false;
15553   for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
15554     auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
15555     StringRef Allocator =
15556         OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
15557     DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
15558     auto *VD = dyn_cast_or_null<ValueDecl>(
15559         S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
15560     if (!VD) {
15561       ErrorFound = true;
15562       break;
15563     }
15564     QualType AllocatorType =
15565         VD->getType().getNonLValueExprType(S.getASTContext());
15566     ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
15567     if (!Res.isUsable()) {
15568       ErrorFound = true;
15569       break;
15570     }
15571     Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
15572                                       Sema::AA_Initializing,
15573                                       /* AllowExplicit */ true);
15574     if (!Res.isUsable()) {
15575       ErrorFound = true;
15576       break;
15577     }
15578     Stack->setAllocator(AllocatorKind, Res.get());
15579   }
15580   if (ErrorFound) {
15581     S.Diag(Loc, diag::err_omp_implied_type_not_found)
15582         << "omp_allocator_handle_t";
15583     return false;
15584   }
15585 
15586   return true;
15587 }
15588 
ActOnOpenMPAllocatorClause(Expr * A,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)15589 OMPClause *SemaOpenMP::ActOnOpenMPAllocatorClause(Expr *A,
15590                                                   SourceLocation StartLoc,
15591                                                   SourceLocation LParenLoc,
15592                                                   SourceLocation EndLoc) {
15593   // OpenMP [2.11.3, allocate Directive, Description]
15594   // allocator is an expression of omp_allocator_handle_t type.
15595   if (!findOMPAllocatorHandleT(SemaRef, A->getExprLoc(), DSAStack))
15596     return nullptr;
15597 
15598   ExprResult Allocator = SemaRef.DefaultLvalueConversion(A);
15599   if (Allocator.isInvalid())
15600     return nullptr;
15601   Allocator = SemaRef.PerformImplicitConversion(
15602       Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
15603       Sema::AA_Initializing,
15604       /*AllowExplicit=*/true);
15605   if (Allocator.isInvalid())
15606     return nullptr;
15607   return new (getASTContext())
15608       OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
15609 }
15610 
ActOnOpenMPCollapseClause(Expr * NumForLoops,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)15611 OMPClause *SemaOpenMP::ActOnOpenMPCollapseClause(Expr *NumForLoops,
15612                                                  SourceLocation StartLoc,
15613                                                  SourceLocation LParenLoc,
15614                                                  SourceLocation EndLoc) {
15615   // OpenMP [2.7.1, loop construct, Description]
15616   // OpenMP [2.8.1, simd construct, Description]
15617   // OpenMP [2.9.6, distribute construct, Description]
15618   // The parameter of the collapse clause must be a constant
15619   // positive integer expression.
15620   ExprResult NumForLoopsResult =
15621       VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
15622   if (NumForLoopsResult.isInvalid())
15623     return nullptr;
15624   return new (getASTContext())
15625       OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
15626 }
15627 
ActOnOpenMPOrderedClause(SourceLocation StartLoc,SourceLocation EndLoc,SourceLocation LParenLoc,Expr * NumForLoops)15628 OMPClause *SemaOpenMP::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
15629                                                 SourceLocation EndLoc,
15630                                                 SourceLocation LParenLoc,
15631                                                 Expr *NumForLoops) {
15632   // OpenMP [2.7.1, loop construct, Description]
15633   // OpenMP [2.8.1, simd construct, Description]
15634   // OpenMP [2.9.6, distribute construct, Description]
15635   // The parameter of the ordered clause must be a constant
15636   // positive integer expression if any.
15637   if (NumForLoops && LParenLoc.isValid()) {
15638     ExprResult NumForLoopsResult =
15639         VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
15640     if (NumForLoopsResult.isInvalid())
15641       return nullptr;
15642     NumForLoops = NumForLoopsResult.get();
15643   } else {
15644     NumForLoops = nullptr;
15645   }
15646   auto *Clause =
15647       OMPOrderedClause::Create(getASTContext(), NumForLoops,
15648                                NumForLoops ? DSAStack->getAssociatedLoops() : 0,
15649                                StartLoc, LParenLoc, EndLoc);
15650   DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
15651   return Clause;
15652 }
15653 
ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,unsigned Argument,SourceLocation ArgumentLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)15654 OMPClause *SemaOpenMP::ActOnOpenMPSimpleClause(
15655     OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
15656     SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
15657   OMPClause *Res = nullptr;
15658   switch (Kind) {
15659   case OMPC_default:
15660     Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument),
15661                                    ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15662     break;
15663   case OMPC_proc_bind:
15664     Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
15665                                     ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15666     break;
15667   case OMPC_atomic_default_mem_order:
15668     Res = ActOnOpenMPAtomicDefaultMemOrderClause(
15669         static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
15670         ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15671     break;
15672   case OMPC_fail:
15673     Res = ActOnOpenMPFailClause(static_cast<OpenMPClauseKind>(Argument),
15674                                 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15675     break;
15676   case OMPC_update:
15677     Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
15678                                   ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15679     break;
15680   case OMPC_bind:
15681     Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
15682                                 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15683     break;
15684   case OMPC_at:
15685     Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
15686                               ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15687     break;
15688   case OMPC_severity:
15689     Res = ActOnOpenMPSeverityClause(
15690         static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
15691         LParenLoc, EndLoc);
15692     break;
15693   case OMPC_if:
15694   case OMPC_final:
15695   case OMPC_num_threads:
15696   case OMPC_safelen:
15697   case OMPC_simdlen:
15698   case OMPC_sizes:
15699   case OMPC_allocator:
15700   case OMPC_collapse:
15701   case OMPC_schedule:
15702   case OMPC_private:
15703   case OMPC_firstprivate:
15704   case OMPC_lastprivate:
15705   case OMPC_shared:
15706   case OMPC_reduction:
15707   case OMPC_task_reduction:
15708   case OMPC_in_reduction:
15709   case OMPC_linear:
15710   case OMPC_aligned:
15711   case OMPC_copyin:
15712   case OMPC_copyprivate:
15713   case OMPC_ordered:
15714   case OMPC_nowait:
15715   case OMPC_untied:
15716   case OMPC_mergeable:
15717   case OMPC_threadprivate:
15718   case OMPC_allocate:
15719   case OMPC_flush:
15720   case OMPC_depobj:
15721   case OMPC_read:
15722   case OMPC_write:
15723   case OMPC_capture:
15724   case OMPC_compare:
15725   case OMPC_seq_cst:
15726   case OMPC_acq_rel:
15727   case OMPC_acquire:
15728   case OMPC_release:
15729   case OMPC_relaxed:
15730   case OMPC_depend:
15731   case OMPC_device:
15732   case OMPC_threads:
15733   case OMPC_simd:
15734   case OMPC_map:
15735   case OMPC_num_teams:
15736   case OMPC_thread_limit:
15737   case OMPC_priority:
15738   case OMPC_grainsize:
15739   case OMPC_nogroup:
15740   case OMPC_num_tasks:
15741   case OMPC_hint:
15742   case OMPC_dist_schedule:
15743   case OMPC_defaultmap:
15744   case OMPC_unknown:
15745   case OMPC_uniform:
15746   case OMPC_to:
15747   case OMPC_from:
15748   case OMPC_use_device_ptr:
15749   case OMPC_use_device_addr:
15750   case OMPC_is_device_ptr:
15751   case OMPC_has_device_addr:
15752   case OMPC_unified_address:
15753   case OMPC_unified_shared_memory:
15754   case OMPC_reverse_offload:
15755   case OMPC_dynamic_allocators:
15756   case OMPC_device_type:
15757   case OMPC_match:
15758   case OMPC_nontemporal:
15759   case OMPC_destroy:
15760   case OMPC_novariants:
15761   case OMPC_nocontext:
15762   case OMPC_detach:
15763   case OMPC_inclusive:
15764   case OMPC_exclusive:
15765   case OMPC_uses_allocators:
15766   case OMPC_affinity:
15767   case OMPC_when:
15768   case OMPC_message:
15769   default:
15770     llvm_unreachable("Clause is not allowed.");
15771   }
15772   return Res;
15773 }
15774 
15775 static std::string
getListOfPossibleValues(OpenMPClauseKind K,unsigned First,unsigned Last,ArrayRef<unsigned> Exclude=std::nullopt)15776 getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last,
15777                         ArrayRef<unsigned> Exclude = std::nullopt) {
15778   SmallString<256> Buffer;
15779   llvm::raw_svector_ostream Out(Buffer);
15780   unsigned Skipped = Exclude.size();
15781   for (unsigned I = First; I < Last; ++I) {
15782     if (llvm::is_contained(Exclude, I)) {
15783       --Skipped;
15784       continue;
15785     }
15786     Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
15787     if (I + Skipped + 2 == Last)
15788       Out << " or ";
15789     else if (I + Skipped + 1 != Last)
15790       Out << ", ";
15791   }
15792   return std::string(Out.str());
15793 }
15794 
ActOnOpenMPDefaultClause(DefaultKind Kind,SourceLocation KindKwLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)15795 OMPClause *SemaOpenMP::ActOnOpenMPDefaultClause(DefaultKind Kind,
15796                                                 SourceLocation KindKwLoc,
15797                                                 SourceLocation StartLoc,
15798                                                 SourceLocation LParenLoc,
15799                                                 SourceLocation EndLoc) {
15800   if (Kind == OMP_DEFAULT_unknown) {
15801     Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15802         << getListOfPossibleValues(OMPC_default, /*First=*/0,
15803                                    /*Last=*/unsigned(OMP_DEFAULT_unknown))
15804         << getOpenMPClauseName(OMPC_default);
15805     return nullptr;
15806   }
15807 
15808   switch (Kind) {
15809   case OMP_DEFAULT_none:
15810     DSAStack->setDefaultDSANone(KindKwLoc);
15811     break;
15812   case OMP_DEFAULT_shared:
15813     DSAStack->setDefaultDSAShared(KindKwLoc);
15814     break;
15815   case OMP_DEFAULT_firstprivate:
15816     DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
15817     break;
15818   case OMP_DEFAULT_private:
15819     DSAStack->setDefaultDSAPrivate(KindKwLoc);
15820     break;
15821   default:
15822     llvm_unreachable("DSA unexpected in OpenMP default clause");
15823   }
15824 
15825   return new (getASTContext())
15826       OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15827 }
15828 
ActOnOpenMPProcBindClause(ProcBindKind Kind,SourceLocation KindKwLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)15829 OMPClause *SemaOpenMP::ActOnOpenMPProcBindClause(ProcBindKind Kind,
15830                                                  SourceLocation KindKwLoc,
15831                                                  SourceLocation StartLoc,
15832                                                  SourceLocation LParenLoc,
15833                                                  SourceLocation EndLoc) {
15834   if (Kind == OMP_PROC_BIND_unknown) {
15835     Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15836         << getListOfPossibleValues(OMPC_proc_bind,
15837                                    /*First=*/unsigned(OMP_PROC_BIND_master),
15838                                    /*Last=*/
15839                                    unsigned(getLangOpts().OpenMP > 50
15840                                                 ? OMP_PROC_BIND_primary
15841                                                 : OMP_PROC_BIND_spread) +
15842                                        1)
15843         << getOpenMPClauseName(OMPC_proc_bind);
15844     return nullptr;
15845   }
15846   if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
15847     Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15848         << getListOfPossibleValues(OMPC_proc_bind,
15849                                    /*First=*/unsigned(OMP_PROC_BIND_master),
15850                                    /*Last=*/
15851                                    unsigned(OMP_PROC_BIND_spread) + 1)
15852         << getOpenMPClauseName(OMPC_proc_bind);
15853   return new (getASTContext())
15854       OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15855 }
15856 
ActOnOpenMPAtomicDefaultMemOrderClause(OpenMPAtomicDefaultMemOrderClauseKind Kind,SourceLocation KindKwLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)15857 OMPClause *SemaOpenMP::ActOnOpenMPAtomicDefaultMemOrderClause(
15858     OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindKwLoc,
15859     SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
15860   if (Kind == OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) {
15861     Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15862         << getListOfPossibleValues(
15863                OMPC_atomic_default_mem_order, /*First=*/0,
15864                /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown)
15865         << getOpenMPClauseName(OMPC_atomic_default_mem_order);
15866     return nullptr;
15867   }
15868   return new (getASTContext()) OMPAtomicDefaultMemOrderClause(
15869       Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15870 }
15871 
ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,SourceLocation KindKwLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)15872 OMPClause *SemaOpenMP::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
15873                                            SourceLocation KindKwLoc,
15874                                            SourceLocation StartLoc,
15875                                            SourceLocation LParenLoc,
15876                                            SourceLocation EndLoc) {
15877   if (Kind == OMPC_AT_unknown) {
15878     Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15879         << getListOfPossibleValues(OMPC_at, /*First=*/0,
15880                                    /*Last=*/OMPC_AT_unknown)
15881         << getOpenMPClauseName(OMPC_at);
15882     return nullptr;
15883   }
15884   return new (getASTContext())
15885       OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15886 }
15887 
ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,SourceLocation KindKwLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)15888 OMPClause *SemaOpenMP::ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,
15889                                                  SourceLocation KindKwLoc,
15890                                                  SourceLocation StartLoc,
15891                                                  SourceLocation LParenLoc,
15892                                                  SourceLocation EndLoc) {
15893   if (Kind == OMPC_SEVERITY_unknown) {
15894     Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15895         << getListOfPossibleValues(OMPC_severity, /*First=*/0,
15896                                    /*Last=*/OMPC_SEVERITY_unknown)
15897         << getOpenMPClauseName(OMPC_severity);
15898     return nullptr;
15899   }
15900   return new (getASTContext())
15901       OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15902 }
15903 
ActOnOpenMPMessageClause(Expr * ME,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)15904 OMPClause *SemaOpenMP::ActOnOpenMPMessageClause(Expr *ME,
15905                                                 SourceLocation StartLoc,
15906                                                 SourceLocation LParenLoc,
15907                                                 SourceLocation EndLoc) {
15908   assert(ME && "NULL expr in Message clause");
15909   if (!isa<StringLiteral>(ME)) {
15910     Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
15911         << getOpenMPClauseName(OMPC_message);
15912     return nullptr;
15913   }
15914   return new (getASTContext())
15915       OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc);
15916 }
15917 
ActOnOpenMPOrderClause(OpenMPOrderClauseModifier Modifier,OpenMPOrderClauseKind Kind,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation MLoc,SourceLocation KindLoc,SourceLocation EndLoc)15918 OMPClause *SemaOpenMP::ActOnOpenMPOrderClause(
15919     OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind,
15920     SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
15921     SourceLocation KindLoc, SourceLocation EndLoc) {
15922   if (Kind != OMPC_ORDER_concurrent ||
15923       (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
15924     // Kind should be concurrent,
15925     // Modifiers introduced in OpenMP 5.1
15926     static_assert(OMPC_ORDER_unknown > 0,
15927                   "OMPC_ORDER_unknown not greater than 0");
15928 
15929     Diag(KindLoc, diag::err_omp_unexpected_clause_value)
15930         << getListOfPossibleValues(OMPC_order,
15931                                    /*First=*/0,
15932                                    /*Last=*/OMPC_ORDER_unknown)
15933         << getOpenMPClauseName(OMPC_order);
15934     return nullptr;
15935   }
15936   if (getLangOpts().OpenMP >= 51) {
15937     if (Modifier == OMPC_ORDER_MODIFIER_unknown && MLoc.isValid()) {
15938       Diag(MLoc, diag::err_omp_unexpected_clause_value)
15939           << getListOfPossibleValues(OMPC_order,
15940                                      /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
15941                                      /*Last=*/OMPC_ORDER_MODIFIER_last)
15942           << getOpenMPClauseName(OMPC_order);
15943     } else {
15944       DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
15945       if (DSAStack->getCurScope()) {
15946         // mark the current scope with 'order' flag
15947         unsigned existingFlags = DSAStack->getCurScope()->getFlags();
15948         DSAStack->getCurScope()->setFlags(existingFlags |
15949                                           Scope::OpenMPOrderClauseScope);
15950       }
15951     }
15952   }
15953   return new (getASTContext()) OMPOrderClause(
15954       Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
15955 }
15956 
ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind,SourceLocation KindKwLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)15957 OMPClause *SemaOpenMP::ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind,
15958                                                SourceLocation KindKwLoc,
15959                                                SourceLocation StartLoc,
15960                                                SourceLocation LParenLoc,
15961                                                SourceLocation EndLoc) {
15962   if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
15963       Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
15964     SmallVector<unsigned> Except = {
15965         OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
15966         OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
15967     if (getLangOpts().OpenMP < 51)
15968       Except.push_back(OMPC_DEPEND_inoutset);
15969     Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15970         << getListOfPossibleValues(OMPC_depend, /*First=*/0,
15971                                    /*Last=*/OMPC_DEPEND_unknown, Except)
15972         << getOpenMPClauseName(OMPC_update);
15973     return nullptr;
15974   }
15975   return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc,
15976                                  KindKwLoc, Kind, EndLoc);
15977 }
15978 
ActOnOpenMPSizesClause(ArrayRef<Expr * > SizeExprs,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)15979 OMPClause *SemaOpenMP::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs,
15980                                               SourceLocation StartLoc,
15981                                               SourceLocation LParenLoc,
15982                                               SourceLocation EndLoc) {
15983   SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
15984 
15985   for (Expr *&SizeExpr : SanitizedSizeExprs) {
15986     // Skip if already sanitized, e.g. during a partial template instantiation.
15987     if (!SizeExpr)
15988       continue;
15989 
15990     bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes,
15991                                              /*StrictlyPositive=*/true);
15992 
15993     // isNonNegativeIntegerValue returns true for non-integral types (but still
15994     // emits error diagnostic), so check for the expected type explicitly.
15995     QualType SizeTy = SizeExpr->getType();
15996     if (!SizeTy->isIntegerType())
15997       IsValid = false;
15998 
15999     // Handling in templates is tricky. There are four possibilities to
16000     // consider:
16001     //
16002     // 1a. The expression is valid and we are in a instantiated template or not
16003     //     in a template:
16004     //       Pass valid expression to be further analysed later in Sema.
16005     // 1b. The expression is valid and we are in a template (including partial
16006     //     instantiation):
16007     //       isNonNegativeIntegerValue skipped any checks so there is no
16008     //       guarantee it will be correct after instantiation.
16009     //       ActOnOpenMPSizesClause will be called again at instantiation when
16010     //       it is not in a dependent context anymore. This may cause warnings
16011     //       to be emitted multiple times.
16012     // 2a. The expression is invalid and we are in an instantiated template or
16013     //     not in a template:
16014     //       Invalidate the expression with a clearly wrong value (nullptr) so
16015     //       later in Sema we do not have to do the same validity analysis again
16016     //       or crash from unexpected data. Error diagnostics have already been
16017     //       emitted.
16018     // 2b. The expression is invalid and we are in a template (including partial
16019     //     instantiation):
16020     //       Pass the invalid expression as-is, template instantiation may
16021     //       replace unexpected types/values with valid ones. The directives
16022     //       with this clause must not try to use these expressions in dependent
16023     //       contexts, but delay analysis until full instantiation.
16024     if (!SizeExpr->isInstantiationDependent() && !IsValid)
16025       SizeExpr = nullptr;
16026   }
16027 
16028   return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
16029                                 SanitizedSizeExprs);
16030 }
16031 
ActOnOpenMPFullClause(SourceLocation StartLoc,SourceLocation EndLoc)16032 OMPClause *SemaOpenMP::ActOnOpenMPFullClause(SourceLocation StartLoc,
16033                                              SourceLocation EndLoc) {
16034   return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc);
16035 }
16036 
ActOnOpenMPPartialClause(Expr * FactorExpr,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16037 OMPClause *SemaOpenMP::ActOnOpenMPPartialClause(Expr *FactorExpr,
16038                                                 SourceLocation StartLoc,
16039                                                 SourceLocation LParenLoc,
16040                                                 SourceLocation EndLoc) {
16041   if (FactorExpr) {
16042     // If an argument is specified, it must be a constant (or an unevaluated
16043     // template expression).
16044     ExprResult FactorResult = VerifyPositiveIntegerConstantInClause(
16045         FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
16046     if (FactorResult.isInvalid())
16047       return nullptr;
16048     FactorExpr = FactorResult.get();
16049   }
16050 
16051   return OMPPartialClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
16052                                   FactorExpr);
16053 }
16054 
ActOnOpenMPAlignClause(Expr * A,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16055 OMPClause *SemaOpenMP::ActOnOpenMPAlignClause(Expr *A, SourceLocation StartLoc,
16056                                               SourceLocation LParenLoc,
16057                                               SourceLocation EndLoc) {
16058   ExprResult AlignVal;
16059   AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
16060   if (AlignVal.isInvalid())
16061     return nullptr;
16062   return OMPAlignClause::Create(getASTContext(), AlignVal.get(), StartLoc,
16063                                 LParenLoc, EndLoc);
16064 }
16065 
ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,ArrayRef<unsigned> Argument,Expr * Expr,SourceLocation StartLoc,SourceLocation LParenLoc,ArrayRef<SourceLocation> ArgumentLoc,SourceLocation DelimLoc,SourceLocation EndLoc)16066 OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause(
16067     OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,
16068     SourceLocation StartLoc, SourceLocation LParenLoc,
16069     ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
16070     SourceLocation EndLoc) {
16071   OMPClause *Res = nullptr;
16072   switch (Kind) {
16073   case OMPC_schedule:
16074     enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
16075     assert(Argument.size() == NumberOfElements &&
16076            ArgumentLoc.size() == NumberOfElements);
16077     Res = ActOnOpenMPScheduleClause(
16078         static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
16079         static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
16080         static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
16081         StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
16082         ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
16083     break;
16084   case OMPC_if:
16085     assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16086     Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
16087                               Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
16088                               DelimLoc, EndLoc);
16089     break;
16090   case OMPC_dist_schedule:
16091     Res = ActOnOpenMPDistScheduleClause(
16092         static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
16093         StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
16094     break;
16095   case OMPC_defaultmap:
16096     enum { Modifier, DefaultmapKind };
16097     Res = ActOnOpenMPDefaultmapClause(
16098         static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
16099         static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
16100         StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
16101         EndLoc);
16102     break;
16103   case OMPC_order:
16104     enum { OrderModifier, OrderKind };
16105     Res = ActOnOpenMPOrderClause(
16106         static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
16107         static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
16108         LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
16109     break;
16110   case OMPC_device:
16111     assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16112     Res = ActOnOpenMPDeviceClause(
16113         static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
16114         StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16115     break;
16116   case OMPC_grainsize:
16117     assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16118            "Modifier for grainsize clause and its location are expected.");
16119     Res = ActOnOpenMPGrainsizeClause(
16120         static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
16121         StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16122     break;
16123   case OMPC_num_tasks:
16124     assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16125            "Modifier for num_tasks clause and its location are expected.");
16126     Res = ActOnOpenMPNumTasksClause(
16127         static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
16128         StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16129     break;
16130   case OMPC_final:
16131   case OMPC_num_threads:
16132   case OMPC_safelen:
16133   case OMPC_simdlen:
16134   case OMPC_sizes:
16135   case OMPC_allocator:
16136   case OMPC_collapse:
16137   case OMPC_default:
16138   case OMPC_proc_bind:
16139   case OMPC_private:
16140   case OMPC_firstprivate:
16141   case OMPC_lastprivate:
16142   case OMPC_shared:
16143   case OMPC_reduction:
16144   case OMPC_task_reduction:
16145   case OMPC_in_reduction:
16146   case OMPC_linear:
16147   case OMPC_aligned:
16148   case OMPC_copyin:
16149   case OMPC_copyprivate:
16150   case OMPC_ordered:
16151   case OMPC_nowait:
16152   case OMPC_untied:
16153   case OMPC_mergeable:
16154   case OMPC_threadprivate:
16155   case OMPC_allocate:
16156   case OMPC_flush:
16157   case OMPC_depobj:
16158   case OMPC_read:
16159   case OMPC_write:
16160   case OMPC_update:
16161   case OMPC_capture:
16162   case OMPC_compare:
16163   case OMPC_seq_cst:
16164   case OMPC_acq_rel:
16165   case OMPC_acquire:
16166   case OMPC_release:
16167   case OMPC_relaxed:
16168   case OMPC_depend:
16169   case OMPC_threads:
16170   case OMPC_simd:
16171   case OMPC_map:
16172   case OMPC_num_teams:
16173   case OMPC_thread_limit:
16174   case OMPC_priority:
16175   case OMPC_nogroup:
16176   case OMPC_hint:
16177   case OMPC_unknown:
16178   case OMPC_uniform:
16179   case OMPC_to:
16180   case OMPC_from:
16181   case OMPC_use_device_ptr:
16182   case OMPC_use_device_addr:
16183   case OMPC_is_device_ptr:
16184   case OMPC_has_device_addr:
16185   case OMPC_unified_address:
16186   case OMPC_unified_shared_memory:
16187   case OMPC_reverse_offload:
16188   case OMPC_dynamic_allocators:
16189   case OMPC_atomic_default_mem_order:
16190   case OMPC_device_type:
16191   case OMPC_match:
16192   case OMPC_nontemporal:
16193   case OMPC_at:
16194   case OMPC_severity:
16195   case OMPC_message:
16196   case OMPC_destroy:
16197   case OMPC_novariants:
16198   case OMPC_nocontext:
16199   case OMPC_detach:
16200   case OMPC_inclusive:
16201   case OMPC_exclusive:
16202   case OMPC_uses_allocators:
16203   case OMPC_affinity:
16204   case OMPC_when:
16205   case OMPC_bind:
16206   default:
16207     llvm_unreachable("Clause is not allowed.");
16208   }
16209   return Res;
16210 }
16211 
checkScheduleModifiers(Sema & S,OpenMPScheduleClauseModifier M1,OpenMPScheduleClauseModifier M2,SourceLocation M1Loc,SourceLocation M2Loc)16212 static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1,
16213                                    OpenMPScheduleClauseModifier M2,
16214                                    SourceLocation M1Loc, SourceLocation M2Loc) {
16215   if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
16216     SmallVector<unsigned, 2> Excluded;
16217     if (M2 != OMPC_SCHEDULE_MODIFIER_unknown)
16218       Excluded.push_back(M2);
16219     if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
16220       Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
16221     if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
16222       Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
16223     S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
16224         << getListOfPossibleValues(OMPC_schedule,
16225                                    /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
16226                                    /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
16227                                    Excluded)
16228         << getOpenMPClauseName(OMPC_schedule);
16229     return true;
16230   }
16231   return false;
16232 }
16233 
ActOnOpenMPScheduleClause(OpenMPScheduleClauseModifier M1,OpenMPScheduleClauseModifier M2,OpenMPScheduleClauseKind Kind,Expr * ChunkSize,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation M1Loc,SourceLocation M2Loc,SourceLocation KindLoc,SourceLocation CommaLoc,SourceLocation EndLoc)16234 OMPClause *SemaOpenMP::ActOnOpenMPScheduleClause(
16235     OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
16236     OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
16237     SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
16238     SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
16239   if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) ||
16240       checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc))
16241     return nullptr;
16242   // OpenMP, 2.7.1, Loop Construct, Restrictions
16243   // Either the monotonic modifier or the nonmonotonic modifier can be specified
16244   // but not both.
16245   if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
16246       (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
16247        M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
16248       (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
16249        M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
16250     Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
16251         << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
16252         << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
16253     return nullptr;
16254   }
16255   if (Kind == OMPC_SCHEDULE_unknown) {
16256     std::string Values;
16257     if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
16258       unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
16259       Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16260                                        /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
16261                                        Exclude);
16262     } else {
16263       Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16264                                        /*Last=*/OMPC_SCHEDULE_unknown);
16265     }
16266     Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16267         << Values << getOpenMPClauseName(OMPC_schedule);
16268     return nullptr;
16269   }
16270   // OpenMP, 2.7.1, Loop Construct, Restrictions
16271   // The nonmonotonic modifier can only be specified with schedule(dynamic) or
16272   // schedule(guided).
16273   // OpenMP 5.0 does not have this restriction.
16274   if (getLangOpts().OpenMP < 50 &&
16275       (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
16276        M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
16277       Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
16278     Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
16279          diag::err_omp_schedule_nonmonotonic_static);
16280     return nullptr;
16281   }
16282   Expr *ValExpr = ChunkSize;
16283   Stmt *HelperValStmt = nullptr;
16284   if (ChunkSize) {
16285     if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
16286         !ChunkSize->isInstantiationDependent() &&
16287         !ChunkSize->containsUnexpandedParameterPack()) {
16288       SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
16289       ExprResult Val =
16290           PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
16291       if (Val.isInvalid())
16292         return nullptr;
16293 
16294       ValExpr = Val.get();
16295 
16296       // OpenMP [2.7.1, Restrictions]
16297       //  chunk_size must be a loop invariant integer expression with a positive
16298       //  value.
16299       if (std::optional<llvm::APSInt> Result =
16300               ValExpr->getIntegerConstantExpr(getASTContext())) {
16301         if (Result->isSigned() && !Result->isStrictlyPositive()) {
16302           Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
16303               << "schedule" << 1 << ChunkSize->getSourceRange();
16304           return nullptr;
16305         }
16306       } else if (getOpenMPCaptureRegionForClause(
16307                      DSAStack->getCurrentDirective(), OMPC_schedule,
16308                      getLangOpts().OpenMP) != OMPD_unknown &&
16309                  !SemaRef.CurContext->isDependentContext()) {
16310         ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16311         llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16312         ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16313         HelperValStmt = buildPreInits(getASTContext(), Captures);
16314       }
16315     }
16316   }
16317 
16318   return new (getASTContext())
16319       OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
16320                         ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
16321 }
16322 
ActOnOpenMPClause(OpenMPClauseKind Kind,SourceLocation StartLoc,SourceLocation EndLoc)16323 OMPClause *SemaOpenMP::ActOnOpenMPClause(OpenMPClauseKind Kind,
16324                                          SourceLocation StartLoc,
16325                                          SourceLocation EndLoc) {
16326   OMPClause *Res = nullptr;
16327   switch (Kind) {
16328   case OMPC_ordered:
16329     Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
16330     break;
16331   case OMPC_nowait:
16332     Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
16333     break;
16334   case OMPC_untied:
16335     Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
16336     break;
16337   case OMPC_mergeable:
16338     Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
16339     break;
16340   case OMPC_read:
16341     Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
16342     break;
16343   case OMPC_write:
16344     Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
16345     break;
16346   case OMPC_update:
16347     Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
16348     break;
16349   case OMPC_capture:
16350     Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
16351     break;
16352   case OMPC_compare:
16353     Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
16354     break;
16355   case OMPC_fail:
16356     Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
16357     break;
16358   case OMPC_seq_cst:
16359     Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
16360     break;
16361   case OMPC_acq_rel:
16362     Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
16363     break;
16364   case OMPC_acquire:
16365     Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
16366     break;
16367   case OMPC_release:
16368     Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
16369     break;
16370   case OMPC_relaxed:
16371     Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
16372     break;
16373   case OMPC_weak:
16374     Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
16375     break;
16376   case OMPC_threads:
16377     Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
16378     break;
16379   case OMPC_simd:
16380     Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
16381     break;
16382   case OMPC_nogroup:
16383     Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
16384     break;
16385   case OMPC_unified_address:
16386     Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
16387     break;
16388   case OMPC_unified_shared_memory:
16389     Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
16390     break;
16391   case OMPC_reverse_offload:
16392     Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
16393     break;
16394   case OMPC_dynamic_allocators:
16395     Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
16396     break;
16397   case OMPC_destroy:
16398     Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
16399                                    /*LParenLoc=*/SourceLocation(),
16400                                    /*VarLoc=*/SourceLocation(), EndLoc);
16401     break;
16402   case OMPC_full:
16403     Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
16404     break;
16405   case OMPC_partial:
16406     Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
16407     break;
16408   case OMPC_ompx_bare:
16409     Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
16410     break;
16411   case OMPC_if:
16412   case OMPC_final:
16413   case OMPC_num_threads:
16414   case OMPC_safelen:
16415   case OMPC_simdlen:
16416   case OMPC_sizes:
16417   case OMPC_allocator:
16418   case OMPC_collapse:
16419   case OMPC_schedule:
16420   case OMPC_private:
16421   case OMPC_firstprivate:
16422   case OMPC_lastprivate:
16423   case OMPC_shared:
16424   case OMPC_reduction:
16425   case OMPC_task_reduction:
16426   case OMPC_in_reduction:
16427   case OMPC_linear:
16428   case OMPC_aligned:
16429   case OMPC_copyin:
16430   case OMPC_copyprivate:
16431   case OMPC_default:
16432   case OMPC_proc_bind:
16433   case OMPC_threadprivate:
16434   case OMPC_allocate:
16435   case OMPC_flush:
16436   case OMPC_depobj:
16437   case OMPC_depend:
16438   case OMPC_device:
16439   case OMPC_map:
16440   case OMPC_num_teams:
16441   case OMPC_thread_limit:
16442   case OMPC_priority:
16443   case OMPC_grainsize:
16444   case OMPC_num_tasks:
16445   case OMPC_hint:
16446   case OMPC_dist_schedule:
16447   case OMPC_defaultmap:
16448   case OMPC_unknown:
16449   case OMPC_uniform:
16450   case OMPC_to:
16451   case OMPC_from:
16452   case OMPC_use_device_ptr:
16453   case OMPC_use_device_addr:
16454   case OMPC_is_device_ptr:
16455   case OMPC_has_device_addr:
16456   case OMPC_atomic_default_mem_order:
16457   case OMPC_device_type:
16458   case OMPC_match:
16459   case OMPC_nontemporal:
16460   case OMPC_order:
16461   case OMPC_at:
16462   case OMPC_severity:
16463   case OMPC_message:
16464   case OMPC_novariants:
16465   case OMPC_nocontext:
16466   case OMPC_detach:
16467   case OMPC_inclusive:
16468   case OMPC_exclusive:
16469   case OMPC_uses_allocators:
16470   case OMPC_affinity:
16471   case OMPC_when:
16472   case OMPC_ompx_dyn_cgroup_mem:
16473   default:
16474     llvm_unreachable("Clause is not allowed.");
16475   }
16476   return Res;
16477 }
16478 
ActOnOpenMPNowaitClause(SourceLocation StartLoc,SourceLocation EndLoc)16479 OMPClause *SemaOpenMP::ActOnOpenMPNowaitClause(SourceLocation StartLoc,
16480                                                SourceLocation EndLoc) {
16481   DSAStack->setNowaitRegion();
16482   return new (getASTContext()) OMPNowaitClause(StartLoc, EndLoc);
16483 }
16484 
ActOnOpenMPUntiedClause(SourceLocation StartLoc,SourceLocation EndLoc)16485 OMPClause *SemaOpenMP::ActOnOpenMPUntiedClause(SourceLocation StartLoc,
16486                                                SourceLocation EndLoc) {
16487   DSAStack->setUntiedRegion();
16488   return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
16489 }
16490 
ActOnOpenMPMergeableClause(SourceLocation StartLoc,SourceLocation EndLoc)16491 OMPClause *SemaOpenMP::ActOnOpenMPMergeableClause(SourceLocation StartLoc,
16492                                                   SourceLocation EndLoc) {
16493   return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
16494 }
16495 
ActOnOpenMPReadClause(SourceLocation StartLoc,SourceLocation EndLoc)16496 OMPClause *SemaOpenMP::ActOnOpenMPReadClause(SourceLocation StartLoc,
16497                                              SourceLocation EndLoc) {
16498   return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
16499 }
16500 
ActOnOpenMPWriteClause(SourceLocation StartLoc,SourceLocation EndLoc)16501 OMPClause *SemaOpenMP::ActOnOpenMPWriteClause(SourceLocation StartLoc,
16502                                               SourceLocation EndLoc) {
16503   return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
16504 }
16505 
ActOnOpenMPUpdateClause(SourceLocation StartLoc,SourceLocation EndLoc)16506 OMPClause *SemaOpenMP::ActOnOpenMPUpdateClause(SourceLocation StartLoc,
16507                                                SourceLocation EndLoc) {
16508   return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc);
16509 }
16510 
ActOnOpenMPCaptureClause(SourceLocation StartLoc,SourceLocation EndLoc)16511 OMPClause *SemaOpenMP::ActOnOpenMPCaptureClause(SourceLocation StartLoc,
16512                                                 SourceLocation EndLoc) {
16513   return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
16514 }
16515 
ActOnOpenMPCompareClause(SourceLocation StartLoc,SourceLocation EndLoc)16516 OMPClause *SemaOpenMP::ActOnOpenMPCompareClause(SourceLocation StartLoc,
16517                                                 SourceLocation EndLoc) {
16518   return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
16519 }
16520 
ActOnOpenMPFailClause(SourceLocation StartLoc,SourceLocation EndLoc)16521 OMPClause *SemaOpenMP::ActOnOpenMPFailClause(SourceLocation StartLoc,
16522                                              SourceLocation EndLoc) {
16523   return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
16524 }
16525 
ActOnOpenMPFailClause(OpenMPClauseKind Parameter,SourceLocation KindLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16526 OMPClause *SemaOpenMP::ActOnOpenMPFailClause(OpenMPClauseKind Parameter,
16527                                              SourceLocation KindLoc,
16528                                              SourceLocation StartLoc,
16529                                              SourceLocation LParenLoc,
16530                                              SourceLocation EndLoc) {
16531 
16532   if (!checkFailClauseParameter(Parameter)) {
16533     Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
16534     return nullptr;
16535   }
16536   return new (getASTContext())
16537       OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
16538 }
16539 
ActOnOpenMPSeqCstClause(SourceLocation StartLoc,SourceLocation EndLoc)16540 OMPClause *SemaOpenMP::ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
16541                                                SourceLocation EndLoc) {
16542   return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
16543 }
16544 
ActOnOpenMPAcqRelClause(SourceLocation StartLoc,SourceLocation EndLoc)16545 OMPClause *SemaOpenMP::ActOnOpenMPAcqRelClause(SourceLocation StartLoc,
16546                                                SourceLocation EndLoc) {
16547   return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
16548 }
16549 
ActOnOpenMPAcquireClause(SourceLocation StartLoc,SourceLocation EndLoc)16550 OMPClause *SemaOpenMP::ActOnOpenMPAcquireClause(SourceLocation StartLoc,
16551                                                 SourceLocation EndLoc) {
16552   return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
16553 }
16554 
ActOnOpenMPReleaseClause(SourceLocation StartLoc,SourceLocation EndLoc)16555 OMPClause *SemaOpenMP::ActOnOpenMPReleaseClause(SourceLocation StartLoc,
16556                                                 SourceLocation EndLoc) {
16557   return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
16558 }
16559 
ActOnOpenMPRelaxedClause(SourceLocation StartLoc,SourceLocation EndLoc)16560 OMPClause *SemaOpenMP::ActOnOpenMPRelaxedClause(SourceLocation StartLoc,
16561                                                 SourceLocation EndLoc) {
16562   return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
16563 }
16564 
ActOnOpenMPWeakClause(SourceLocation StartLoc,SourceLocation EndLoc)16565 OMPClause *SemaOpenMP::ActOnOpenMPWeakClause(SourceLocation StartLoc,
16566                                              SourceLocation EndLoc) {
16567   return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
16568 }
16569 
ActOnOpenMPThreadsClause(SourceLocation StartLoc,SourceLocation EndLoc)16570 OMPClause *SemaOpenMP::ActOnOpenMPThreadsClause(SourceLocation StartLoc,
16571                                                 SourceLocation EndLoc) {
16572   return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
16573 }
16574 
ActOnOpenMPSIMDClause(SourceLocation StartLoc,SourceLocation EndLoc)16575 OMPClause *SemaOpenMP::ActOnOpenMPSIMDClause(SourceLocation StartLoc,
16576                                              SourceLocation EndLoc) {
16577   return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
16578 }
16579 
ActOnOpenMPNogroupClause(SourceLocation StartLoc,SourceLocation EndLoc)16580 OMPClause *SemaOpenMP::ActOnOpenMPNogroupClause(SourceLocation StartLoc,
16581                                                 SourceLocation EndLoc) {
16582   return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
16583 }
16584 
ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,SourceLocation EndLoc)16585 OMPClause *SemaOpenMP::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,
16586                                                        SourceLocation EndLoc) {
16587   return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
16588 }
16589 
16590 OMPClause *
ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,SourceLocation EndLoc)16591 SemaOpenMP::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
16592                                                  SourceLocation EndLoc) {
16593   return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
16594 }
16595 
ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,SourceLocation EndLoc)16596 OMPClause *SemaOpenMP::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
16597                                                        SourceLocation EndLoc) {
16598   return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
16599 }
16600 
16601 OMPClause *
ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,SourceLocation EndLoc)16602 SemaOpenMP::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,
16603                                                SourceLocation EndLoc) {
16604   return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
16605 }
16606 
16607 StmtResult
ActOnOpenMPInteropDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc)16608 SemaOpenMP::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
16609                                         SourceLocation StartLoc,
16610                                         SourceLocation EndLoc) {
16611 
16612   // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16613   // At least one action-clause must appear on a directive.
16614   if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
16615     StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
16616     Diag(StartLoc, diag::err_omp_no_clause_for_directive)
16617         << Expected << getOpenMPDirectiveName(OMPD_interop);
16618     return StmtError();
16619   }
16620 
16621   // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16622   // A depend clause can only appear on the directive if a targetsync
16623   // interop-type is present or the interop-var was initialized with
16624   // the targetsync interop-type.
16625 
16626   // If there is any 'init' clause diagnose if there is no 'init' clause with
16627   // interop-type of 'targetsync'. Cases involving other directives cannot be
16628   // diagnosed.
16629   const OMPDependClause *DependClause = nullptr;
16630   bool HasInitClause = false;
16631   bool IsTargetSync = false;
16632   for (const OMPClause *C : Clauses) {
16633     if (IsTargetSync)
16634       break;
16635     if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
16636       HasInitClause = true;
16637       if (InitClause->getIsTargetSync())
16638         IsTargetSync = true;
16639     } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
16640       DependClause = DC;
16641     }
16642   }
16643   if (DependClause && HasInitClause && !IsTargetSync) {
16644     Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
16645     return StmtError();
16646   }
16647 
16648   // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16649   // Each interop-var may be specified for at most one action-clause of each
16650   // interop construct.
16651   llvm::SmallPtrSet<const ValueDecl *, 4> InteropVars;
16652   for (OMPClause *C : Clauses) {
16653     OpenMPClauseKind ClauseKind = C->getClauseKind();
16654     std::pair<ValueDecl *, bool> DeclResult;
16655     SourceLocation ELoc;
16656     SourceRange ERange;
16657 
16658     if (ClauseKind == OMPC_init) {
16659       auto *E = cast<OMPInitClause>(C)->getInteropVar();
16660       DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
16661     } else if (ClauseKind == OMPC_use) {
16662       auto *E = cast<OMPUseClause>(C)->getInteropVar();
16663       DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
16664     } else if (ClauseKind == OMPC_destroy) {
16665       auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
16666       DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
16667     }
16668 
16669     if (DeclResult.first) {
16670       if (!InteropVars.insert(DeclResult.first).second) {
16671         Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
16672             << DeclResult.first;
16673         return StmtError();
16674       }
16675     }
16676   }
16677 
16678   return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc,
16679                                      Clauses);
16680 }
16681 
isValidInteropVariable(Sema & SemaRef,Expr * InteropVarExpr,SourceLocation VarLoc,OpenMPClauseKind Kind)16682 static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
16683                                    SourceLocation VarLoc,
16684                                    OpenMPClauseKind Kind) {
16685   SourceLocation ELoc;
16686   SourceRange ERange;
16687   Expr *RefExpr = InteropVarExpr;
16688   auto Res =
16689       getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
16690                      /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
16691 
16692   if (Res.second) {
16693     // It will be analyzed later.
16694     return true;
16695   }
16696 
16697   if (!Res.first)
16698     return false;
16699 
16700   // Interop variable should be of type omp_interop_t.
16701   bool HasError = false;
16702   QualType InteropType;
16703   LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
16704                       VarLoc, Sema::LookupOrdinaryName);
16705   if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
16706     NamedDecl *ND = Result.getFoundDecl();
16707     if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
16708       InteropType = QualType(TD->getTypeForDecl(), 0);
16709     } else {
16710       HasError = true;
16711     }
16712   } else {
16713     HasError = true;
16714   }
16715 
16716   if (HasError) {
16717     SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
16718         << "omp_interop_t";
16719     return false;
16720   }
16721 
16722   QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
16723   if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
16724     SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
16725     return false;
16726   }
16727 
16728   // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16729   // The interop-var passed to init or destroy must be non-const.
16730   if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
16731       isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
16732     SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
16733         << /*non-const*/ 1;
16734     return false;
16735   }
16736   return true;
16737 }
16738 
ActOnOpenMPInitClause(Expr * InteropVar,OMPInteropInfo & InteropInfo,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation VarLoc,SourceLocation EndLoc)16739 OMPClause *SemaOpenMP::ActOnOpenMPInitClause(
16740     Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
16741     SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
16742 
16743   if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init))
16744     return nullptr;
16745 
16746   // Check prefer_type values.  These foreign-runtime-id values are either
16747   // string literals or constant integral expressions.
16748   for (const Expr *E : InteropInfo.PreferTypes) {
16749     if (E->isValueDependent() || E->isTypeDependent() ||
16750         E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
16751       continue;
16752     if (E->isIntegerConstantExpr(getASTContext()))
16753       continue;
16754     if (isa<StringLiteral>(E))
16755       continue;
16756     Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
16757     return nullptr;
16758   }
16759 
16760   return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo,
16761                                StartLoc, LParenLoc, VarLoc, EndLoc);
16762 }
16763 
ActOnOpenMPUseClause(Expr * InteropVar,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation VarLoc,SourceLocation EndLoc)16764 OMPClause *SemaOpenMP::ActOnOpenMPUseClause(Expr *InteropVar,
16765                                             SourceLocation StartLoc,
16766                                             SourceLocation LParenLoc,
16767                                             SourceLocation VarLoc,
16768                                             SourceLocation EndLoc) {
16769 
16770   if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use))
16771     return nullptr;
16772 
16773   return new (getASTContext())
16774       OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
16775 }
16776 
ActOnOpenMPDestroyClause(Expr * InteropVar,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation VarLoc,SourceLocation EndLoc)16777 OMPClause *SemaOpenMP::ActOnOpenMPDestroyClause(Expr *InteropVar,
16778                                                 SourceLocation StartLoc,
16779                                                 SourceLocation LParenLoc,
16780                                                 SourceLocation VarLoc,
16781                                                 SourceLocation EndLoc) {
16782   if (!InteropVar && getLangOpts().OpenMP >= 52 &&
16783       DSAStack->getCurrentDirective() == OMPD_depobj) {
16784     Diag(StartLoc, diag::err_omp_expected_clause_argument)
16785         << getOpenMPClauseName(OMPC_destroy)
16786         << getOpenMPDirectiveName(OMPD_depobj);
16787     return nullptr;
16788   }
16789   if (InteropVar &&
16790       !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy))
16791     return nullptr;
16792 
16793   return new (getASTContext())
16794       OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
16795 }
16796 
ActOnOpenMPNovariantsClause(Expr * Condition,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16797 OMPClause *SemaOpenMP::ActOnOpenMPNovariantsClause(Expr *Condition,
16798                                                    SourceLocation StartLoc,
16799                                                    SourceLocation LParenLoc,
16800                                                    SourceLocation EndLoc) {
16801   Expr *ValExpr = Condition;
16802   Stmt *HelperValStmt = nullptr;
16803   OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16804   if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16805       !Condition->isInstantiationDependent() &&
16806       !Condition->containsUnexpandedParameterPack()) {
16807     ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
16808     if (Val.isInvalid())
16809       return nullptr;
16810 
16811     ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
16812 
16813     OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16814     CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
16815                                                     getLangOpts().OpenMP);
16816     if (CaptureRegion != OMPD_unknown &&
16817         !SemaRef.CurContext->isDependentContext()) {
16818       ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16819       llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16820       ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16821       HelperValStmt = buildPreInits(getASTContext(), Captures);
16822     }
16823   }
16824 
16825   return new (getASTContext()) OMPNovariantsClause(
16826       ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16827 }
16828 
ActOnOpenMPNocontextClause(Expr * Condition,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16829 OMPClause *SemaOpenMP::ActOnOpenMPNocontextClause(Expr *Condition,
16830                                                   SourceLocation StartLoc,
16831                                                   SourceLocation LParenLoc,
16832                                                   SourceLocation EndLoc) {
16833   Expr *ValExpr = Condition;
16834   Stmt *HelperValStmt = nullptr;
16835   OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16836   if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16837       !Condition->isInstantiationDependent() &&
16838       !Condition->containsUnexpandedParameterPack()) {
16839     ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
16840     if (Val.isInvalid())
16841       return nullptr;
16842 
16843     ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
16844 
16845     OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16846     CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext,
16847                                                     getLangOpts().OpenMP);
16848     if (CaptureRegion != OMPD_unknown &&
16849         !SemaRef.CurContext->isDependentContext()) {
16850       ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16851       llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16852       ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16853       HelperValStmt = buildPreInits(getASTContext(), Captures);
16854     }
16855   }
16856 
16857   return new (getASTContext()) OMPNocontextClause(
16858       ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16859 }
16860 
ActOnOpenMPFilterClause(Expr * ThreadID,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16861 OMPClause *SemaOpenMP::ActOnOpenMPFilterClause(Expr *ThreadID,
16862                                                SourceLocation StartLoc,
16863                                                SourceLocation LParenLoc,
16864                                                SourceLocation EndLoc) {
16865   Expr *ValExpr = ThreadID;
16866   Stmt *HelperValStmt = nullptr;
16867 
16868   OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16869   OpenMPDirectiveKind CaptureRegion =
16870       getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP);
16871   if (CaptureRegion != OMPD_unknown &&
16872       !SemaRef.CurContext->isDependentContext()) {
16873     ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16874     llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16875     ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16876     HelperValStmt = buildPreInits(getASTContext(), Captures);
16877   }
16878 
16879   return new (getASTContext()) OMPFilterClause(
16880       ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16881 }
16882 
ActOnOpenMPVarListClause(OpenMPClauseKind Kind,ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs,OpenMPVarListDataTy & Data)16883 OMPClause *SemaOpenMP::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
16884                                                 ArrayRef<Expr *> VarList,
16885                                                 const OMPVarListLocTy &Locs,
16886                                                 OpenMPVarListDataTy &Data) {
16887   SourceLocation StartLoc = Locs.StartLoc;
16888   SourceLocation LParenLoc = Locs.LParenLoc;
16889   SourceLocation EndLoc = Locs.EndLoc;
16890   OMPClause *Res = nullptr;
16891   int ExtraModifier = Data.ExtraModifier;
16892   SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
16893   SourceLocation ColonLoc = Data.ColonLoc;
16894   switch (Kind) {
16895   case OMPC_private:
16896     Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
16897     break;
16898   case OMPC_firstprivate:
16899     Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
16900     break;
16901   case OMPC_lastprivate:
16902     assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
16903            "Unexpected lastprivate modifier.");
16904     Res = ActOnOpenMPLastprivateClause(
16905         VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
16906         ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
16907     break;
16908   case OMPC_shared:
16909     Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
16910     break;
16911   case OMPC_reduction:
16912     assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
16913            "Unexpected lastprivate modifier.");
16914     Res = ActOnOpenMPReductionClause(
16915         VarList, static_cast<OpenMPReductionClauseModifier>(ExtraModifier),
16916         StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
16917         Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
16918     break;
16919   case OMPC_task_reduction:
16920     Res = ActOnOpenMPTaskReductionClause(
16921         VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
16922         Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
16923     break;
16924   case OMPC_in_reduction:
16925     Res = ActOnOpenMPInReductionClause(
16926         VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
16927         Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
16928     break;
16929   case OMPC_linear:
16930     assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
16931            "Unexpected linear modifier.");
16932     Res = ActOnOpenMPLinearClause(
16933         VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
16934         static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
16935         ColonLoc, Data.StepModifierLoc, EndLoc);
16936     break;
16937   case OMPC_aligned:
16938     Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
16939                                    LParenLoc, ColonLoc, EndLoc);
16940     break;
16941   case OMPC_copyin:
16942     Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
16943     break;
16944   case OMPC_copyprivate:
16945     Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
16946     break;
16947   case OMPC_flush:
16948     Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
16949     break;
16950   case OMPC_depend:
16951     assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
16952            "Unexpected depend modifier.");
16953     Res = ActOnOpenMPDependClause(
16954         {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
16955          ColonLoc, Data.OmpAllMemoryLoc},
16956         Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
16957     break;
16958   case OMPC_map:
16959     assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
16960            "Unexpected map modifier.");
16961     Res = ActOnOpenMPMapClause(
16962         Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
16963         Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
16964         static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
16965         ExtraModifierLoc, ColonLoc, VarList, Locs);
16966     break;
16967   case OMPC_to:
16968     Res =
16969         ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc,
16970                             Data.ReductionOrMapperIdScopeSpec,
16971                             Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
16972     break;
16973   case OMPC_from:
16974     Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc,
16975                                 Data.ReductionOrMapperIdScopeSpec,
16976                                 Data.ReductionOrMapperId, ColonLoc, VarList,
16977                                 Locs);
16978     break;
16979   case OMPC_use_device_ptr:
16980     Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
16981     break;
16982   case OMPC_use_device_addr:
16983     Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
16984     break;
16985   case OMPC_is_device_ptr:
16986     Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
16987     break;
16988   case OMPC_has_device_addr:
16989     Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
16990     break;
16991   case OMPC_allocate:
16992     Res = ActOnOpenMPAllocateClause(Data.DepModOrTailExpr, VarList, StartLoc,
16993                                     LParenLoc, ColonLoc, EndLoc);
16994     break;
16995   case OMPC_nontemporal:
16996     Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
16997     break;
16998   case OMPC_inclusive:
16999     Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17000     break;
17001   case OMPC_exclusive:
17002     Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17003     break;
17004   case OMPC_affinity:
17005     Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
17006                                     Data.DepModOrTailExpr, VarList);
17007     break;
17008   case OMPC_doacross:
17009     Res = ActOnOpenMPDoacrossClause(
17010         static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
17011         ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
17012     break;
17013   case OMPC_if:
17014   case OMPC_depobj:
17015   case OMPC_final:
17016   case OMPC_num_threads:
17017   case OMPC_safelen:
17018   case OMPC_simdlen:
17019   case OMPC_sizes:
17020   case OMPC_allocator:
17021   case OMPC_collapse:
17022   case OMPC_default:
17023   case OMPC_proc_bind:
17024   case OMPC_schedule:
17025   case OMPC_ordered:
17026   case OMPC_nowait:
17027   case OMPC_untied:
17028   case OMPC_mergeable:
17029   case OMPC_threadprivate:
17030   case OMPC_read:
17031   case OMPC_write:
17032   case OMPC_update:
17033   case OMPC_capture:
17034   case OMPC_compare:
17035   case OMPC_seq_cst:
17036   case OMPC_acq_rel:
17037   case OMPC_acquire:
17038   case OMPC_release:
17039   case OMPC_relaxed:
17040   case OMPC_device:
17041   case OMPC_threads:
17042   case OMPC_simd:
17043   case OMPC_num_teams:
17044   case OMPC_thread_limit:
17045   case OMPC_priority:
17046   case OMPC_grainsize:
17047   case OMPC_nogroup:
17048   case OMPC_num_tasks:
17049   case OMPC_hint:
17050   case OMPC_dist_schedule:
17051   case OMPC_defaultmap:
17052   case OMPC_unknown:
17053   case OMPC_uniform:
17054   case OMPC_unified_address:
17055   case OMPC_unified_shared_memory:
17056   case OMPC_reverse_offload:
17057   case OMPC_dynamic_allocators:
17058   case OMPC_atomic_default_mem_order:
17059   case OMPC_device_type:
17060   case OMPC_match:
17061   case OMPC_order:
17062   case OMPC_at:
17063   case OMPC_severity:
17064   case OMPC_message:
17065   case OMPC_destroy:
17066   case OMPC_novariants:
17067   case OMPC_nocontext:
17068   case OMPC_detach:
17069   case OMPC_uses_allocators:
17070   case OMPC_when:
17071   case OMPC_bind:
17072   default:
17073     llvm_unreachable("Clause is not allowed.");
17074   }
17075   return Res;
17076 }
17077 
getOpenMPCapturedExpr(VarDecl * Capture,ExprValueKind VK,ExprObjectKind OK,SourceLocation Loc)17078 ExprResult SemaOpenMP::getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
17079                                              ExprObjectKind OK,
17080                                              SourceLocation Loc) {
17081   ExprResult Res = SemaRef.BuildDeclRefExpr(
17082       Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
17083   if (!Res.isUsable())
17084     return ExprError();
17085   if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
17086     Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
17087     if (!Res.isUsable())
17088       return ExprError();
17089   }
17090   if (VK != VK_LValue && Res.get()->isGLValue()) {
17091     Res = SemaRef.DefaultLvalueConversion(Res.get());
17092     if (!Res.isUsable())
17093       return ExprError();
17094   }
17095   return Res;
17096 }
17097 
ActOnOpenMPPrivateClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)17098 OMPClause *SemaOpenMP::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
17099                                                 SourceLocation StartLoc,
17100                                                 SourceLocation LParenLoc,
17101                                                 SourceLocation EndLoc) {
17102   SmallVector<Expr *, 8> Vars;
17103   SmallVector<Expr *, 8> PrivateCopies;
17104   bool IsImplicitClause =
17105       StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17106   for (Expr *RefExpr : VarList) {
17107     assert(RefExpr && "NULL expr in OpenMP private clause.");
17108     SourceLocation ELoc;
17109     SourceRange ERange;
17110     Expr *SimpleRefExpr = RefExpr;
17111     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17112     if (Res.second) {
17113       // It will be analyzed later.
17114       Vars.push_back(RefExpr);
17115       PrivateCopies.push_back(nullptr);
17116     }
17117     ValueDecl *D = Res.first;
17118     if (!D)
17119       continue;
17120 
17121     QualType Type = D->getType();
17122     auto *VD = dyn_cast<VarDecl>(D);
17123 
17124     // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17125     //  A variable that appears in a private clause must not have an incomplete
17126     //  type or a reference type.
17127     if (SemaRef.RequireCompleteType(ELoc, Type,
17128                                     diag::err_omp_private_incomplete_type))
17129       continue;
17130     Type = Type.getNonReferenceType();
17131 
17132     // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
17133     // A variable that is privatized must not have a const-qualified type
17134     // unless it is of class type with a mutable member. This restriction does
17135     // not apply to the firstprivate clause.
17136     //
17137     // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
17138     // A variable that appears in a private clause must not have a
17139     // const-qualified type unless it is of class type with a mutable member.
17140     if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc))
17141       continue;
17142 
17143     // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17144     // in a Construct]
17145     //  Variables with the predetermined data-sharing attributes may not be
17146     //  listed in data-sharing attributes clauses, except for the cases
17147     //  listed below. For these exceptions only, listing a predetermined
17148     //  variable in a data-sharing attribute clause is allowed and overrides
17149     //  the variable's predetermined data-sharing attributes.
17150     DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17151     if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
17152       Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17153                                           << getOpenMPClauseName(OMPC_private);
17154       reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17155       continue;
17156     }
17157 
17158     OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17159     // Variably modified types are not supported for tasks.
17160     if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
17161         isOpenMPTaskingDirective(CurrDir)) {
17162       Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17163           << getOpenMPClauseName(OMPC_private) << Type
17164           << getOpenMPDirectiveName(CurrDir);
17165       bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17166                                VarDecl::DeclarationOnly;
17167       Diag(D->getLocation(),
17168            IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17169           << D;
17170       continue;
17171     }
17172 
17173     // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17174     // A list item cannot appear in both a map clause and a data-sharing
17175     // attribute clause on the same construct
17176     //
17177     // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17178     // A list item cannot appear in both a map clause and a data-sharing
17179     // attribute clause on the same construct unless the construct is a
17180     // combined construct.
17181     if ((getLangOpts().OpenMP <= 45 &&
17182          isOpenMPTargetExecutionDirective(CurrDir)) ||
17183         CurrDir == OMPD_target) {
17184       OpenMPClauseKind ConflictKind;
17185       if (DSAStack->checkMappableExprComponentListsForDecl(
17186               VD, /*CurrentRegionOnly=*/true,
17187               [&](OMPClauseMappableExprCommon::MappableExprComponentListRef,
17188                   OpenMPClauseKind WhereFoundClauseKind) -> bool {
17189                 ConflictKind = WhereFoundClauseKind;
17190                 return true;
17191               })) {
17192         Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17193             << getOpenMPClauseName(OMPC_private)
17194             << getOpenMPClauseName(ConflictKind)
17195             << getOpenMPDirectiveName(CurrDir);
17196         reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17197         continue;
17198       }
17199     }
17200 
17201     // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
17202     //  A variable of class type (or array thereof) that appears in a private
17203     //  clause requires an accessible, unambiguous default constructor for the
17204     //  class type.
17205     // Generate helper private variable and initialize it with the default
17206     // value. The address of the original variable is replaced by the address of
17207     // the new private variable in CodeGen. This new variable is not added to
17208     // IdResolver, so the code in the OpenMP region uses original variable for
17209     // proper diagnostics.
17210     Type = Type.getUnqualifiedType();
17211     VarDecl *VDPrivate =
17212         buildVarDecl(SemaRef, ELoc, Type, D->getName(),
17213                      D->hasAttrs() ? &D->getAttrs() : nullptr,
17214                      VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
17215     SemaRef.ActOnUninitializedDecl(VDPrivate);
17216     if (VDPrivate->isInvalidDecl())
17217       continue;
17218     DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
17219         SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
17220 
17221     DeclRefExpr *Ref = nullptr;
17222     if (!VD && !SemaRef.CurContext->isDependentContext()) {
17223       auto *FD = dyn_cast<FieldDecl>(D);
17224       VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
17225       if (VD)
17226         Ref = buildDeclRefExpr(SemaRef, VD, VD->getType().getNonReferenceType(),
17227                                RefExpr->getExprLoc());
17228       else
17229         Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
17230     }
17231     if (!IsImplicitClause)
17232       DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
17233     Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17234                        ? RefExpr->IgnoreParens()
17235                        : Ref);
17236     PrivateCopies.push_back(VDPrivateRefExpr);
17237   }
17238 
17239   if (Vars.empty())
17240     return nullptr;
17241 
17242   return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17243                                   Vars, PrivateCopies);
17244 }
17245 
ActOnOpenMPFirstprivateClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)17246 OMPClause *SemaOpenMP::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
17247                                                      SourceLocation StartLoc,
17248                                                      SourceLocation LParenLoc,
17249                                                      SourceLocation EndLoc) {
17250   SmallVector<Expr *, 8> Vars;
17251   SmallVector<Expr *, 8> PrivateCopies;
17252   SmallVector<Expr *, 8> Inits;
17253   SmallVector<Decl *, 4> ExprCaptures;
17254   bool IsImplicitClause =
17255       StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17256   SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
17257 
17258   for (Expr *RefExpr : VarList) {
17259     assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
17260     SourceLocation ELoc;
17261     SourceRange ERange;
17262     Expr *SimpleRefExpr = RefExpr;
17263     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17264     if (Res.second) {
17265       // It will be analyzed later.
17266       Vars.push_back(RefExpr);
17267       PrivateCopies.push_back(nullptr);
17268       Inits.push_back(nullptr);
17269     }
17270     ValueDecl *D = Res.first;
17271     if (!D)
17272       continue;
17273 
17274     ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
17275     QualType Type = D->getType();
17276     auto *VD = dyn_cast<VarDecl>(D);
17277 
17278     // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17279     //  A variable that appears in a private clause must not have an incomplete
17280     //  type or a reference type.
17281     if (SemaRef.RequireCompleteType(ELoc, Type,
17282                                     diag::err_omp_firstprivate_incomplete_type))
17283       continue;
17284     Type = Type.getNonReferenceType();
17285 
17286     // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
17287     //  A variable of class type (or array thereof) that appears in a private
17288     //  clause requires an accessible, unambiguous copy constructor for the
17289     //  class type.
17290     QualType ElemType =
17291         getASTContext().getBaseElementType(Type).getNonReferenceType();
17292 
17293     // If an implicit firstprivate variable found it was checked already.
17294     DSAStackTy::DSAVarData TopDVar;
17295     if (!IsImplicitClause) {
17296       DSAStackTy::DSAVarData DVar =
17297           DSAStack->getTopDSA(D, /*FromParent=*/false);
17298       TopDVar = DVar;
17299       OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17300       bool IsConstant = ElemType.isConstant(getASTContext());
17301       // OpenMP [2.4.13, Data-sharing Attribute Clauses]
17302       //  A list item that specifies a given variable may not appear in more
17303       // than one clause on the same directive, except that a variable may be
17304       //  specified in both firstprivate and lastprivate clauses.
17305       // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
17306       // A list item may appear in a firstprivate or lastprivate clause but not
17307       // both.
17308       if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
17309           (isOpenMPDistributeDirective(CurrDir) ||
17310            DVar.CKind != OMPC_lastprivate) &&
17311           DVar.RefExpr) {
17312         Diag(ELoc, diag::err_omp_wrong_dsa)
17313             << getOpenMPClauseName(DVar.CKind)
17314             << getOpenMPClauseName(OMPC_firstprivate);
17315         reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17316         continue;
17317       }
17318 
17319       // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17320       // in a Construct]
17321       //  Variables with the predetermined data-sharing attributes may not be
17322       //  listed in data-sharing attributes clauses, except for the cases
17323       //  listed below. For these exceptions only, listing a predetermined
17324       //  variable in a data-sharing attribute clause is allowed and overrides
17325       //  the variable's predetermined data-sharing attributes.
17326       // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17327       // in a Construct, C/C++, p.2]
17328       //  Variables with const-qualified type having no mutable member may be
17329       //  listed in a firstprivate clause, even if they are static data members.
17330       if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
17331           DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
17332         Diag(ELoc, diag::err_omp_wrong_dsa)
17333             << getOpenMPClauseName(DVar.CKind)
17334             << getOpenMPClauseName(OMPC_firstprivate);
17335         reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17336         continue;
17337       }
17338 
17339       // OpenMP [2.9.3.4, Restrictions, p.2]
17340       //  A list item that is private within a parallel region must not appear
17341       //  in a firstprivate clause on a worksharing construct if any of the
17342       //  worksharing regions arising from the worksharing construct ever bind
17343       //  to any of the parallel regions arising from the parallel construct.
17344       // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17345       // A list item that is private within a teams region must not appear in a
17346       // firstprivate clause on a distribute construct if any of the distribute
17347       // regions arising from the distribute construct ever bind to any of the
17348       // teams regions arising from the teams construct.
17349       // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17350       // A list item that appears in a reduction clause of a teams construct
17351       // must not appear in a firstprivate clause on a distribute construct if
17352       // any of the distribute regions arising from the distribute construct
17353       // ever bind to any of the teams regions arising from the teams construct.
17354       if ((isOpenMPWorksharingDirective(CurrDir) ||
17355            isOpenMPDistributeDirective(CurrDir)) &&
17356           !isOpenMPParallelDirective(CurrDir) &&
17357           !isOpenMPTeamsDirective(CurrDir)) {
17358         DVar = DSAStack->getImplicitDSA(D, true);
17359         if (DVar.CKind != OMPC_shared &&
17360             (isOpenMPParallelDirective(DVar.DKind) ||
17361              isOpenMPTeamsDirective(DVar.DKind) ||
17362              DVar.DKind == OMPD_unknown)) {
17363           Diag(ELoc, diag::err_omp_required_access)
17364               << getOpenMPClauseName(OMPC_firstprivate)
17365               << getOpenMPClauseName(OMPC_shared);
17366           reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17367           continue;
17368         }
17369       }
17370       // OpenMP [2.9.3.4, Restrictions, p.3]
17371       //  A list item that appears in a reduction clause of a parallel construct
17372       //  must not appear in a firstprivate clause on a worksharing or task
17373       //  construct if any of the worksharing or task regions arising from the
17374       //  worksharing or task construct ever bind to any of the parallel regions
17375       //  arising from the parallel construct.
17376       // OpenMP [2.9.3.4, Restrictions, p.4]
17377       //  A list item that appears in a reduction clause in worksharing
17378       //  construct must not appear in a firstprivate clause in a task construct
17379       //  encountered during execution of any of the worksharing regions arising
17380       //  from the worksharing construct.
17381       if (isOpenMPTaskingDirective(CurrDir)) {
17382         DVar = DSAStack->hasInnermostDSA(
17383             D,
17384             [](OpenMPClauseKind C, bool AppliedToPointee) {
17385               return C == OMPC_reduction && !AppliedToPointee;
17386             },
17387             [](OpenMPDirectiveKind K) {
17388               return isOpenMPParallelDirective(K) ||
17389                      isOpenMPWorksharingDirective(K) ||
17390                      isOpenMPTeamsDirective(K);
17391             },
17392             /*FromParent=*/true);
17393         if (DVar.CKind == OMPC_reduction &&
17394             (isOpenMPParallelDirective(DVar.DKind) ||
17395              isOpenMPWorksharingDirective(DVar.DKind) ||
17396              isOpenMPTeamsDirective(DVar.DKind))) {
17397           Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
17398               << getOpenMPDirectiveName(DVar.DKind);
17399           reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17400           continue;
17401         }
17402       }
17403 
17404       // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17405       // A list item cannot appear in both a map clause and a data-sharing
17406       // attribute clause on the same construct
17407       //
17408       // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17409       // A list item cannot appear in both a map clause and a data-sharing
17410       // attribute clause on the same construct unless the construct is a
17411       // combined construct.
17412       if ((getLangOpts().OpenMP <= 45 &&
17413            isOpenMPTargetExecutionDirective(CurrDir)) ||
17414           CurrDir == OMPD_target) {
17415         OpenMPClauseKind ConflictKind;
17416         if (DSAStack->checkMappableExprComponentListsForDecl(
17417                 VD, /*CurrentRegionOnly=*/true,
17418                 [&ConflictKind](
17419                     OMPClauseMappableExprCommon::MappableExprComponentListRef,
17420                     OpenMPClauseKind WhereFoundClauseKind) {
17421                   ConflictKind = WhereFoundClauseKind;
17422                   return true;
17423                 })) {
17424           Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17425               << getOpenMPClauseName(OMPC_firstprivate)
17426               << getOpenMPClauseName(ConflictKind)
17427               << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
17428           reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17429           continue;
17430         }
17431       }
17432     }
17433 
17434     // Variably modified types are not supported for tasks.
17435     if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
17436         isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
17437       Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17438           << getOpenMPClauseName(OMPC_firstprivate) << Type
17439           << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
17440       bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17441                                VarDecl::DeclarationOnly;
17442       Diag(D->getLocation(),
17443            IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17444           << D;
17445       continue;
17446     }
17447 
17448     Type = Type.getUnqualifiedType();
17449     VarDecl *VDPrivate =
17450         buildVarDecl(SemaRef, ELoc, Type, D->getName(),
17451                      D->hasAttrs() ? &D->getAttrs() : nullptr,
17452                      VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
17453     // Generate helper private variable and initialize it with the value of the
17454     // original variable. The address of the original variable is replaced by
17455     // the address of the new private variable in the CodeGen. This new variable
17456     // is not added to IdResolver, so the code in the OpenMP region uses
17457     // original variable for proper diagnostics and variable capturing.
17458     Expr *VDInitRefExpr = nullptr;
17459     // For arrays generate initializer for single element and replace it by the
17460     // original array element in CodeGen.
17461     if (Type->isArrayType()) {
17462       VarDecl *VDInit =
17463           buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName());
17464       VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc);
17465       Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get();
17466       ElemType = ElemType.getUnqualifiedType();
17467       VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(),
17468                                          ElemType, ".firstprivate.temp");
17469       InitializedEntity Entity =
17470           InitializedEntity::InitializeVariable(VDInitTemp);
17471       InitializationKind Kind = InitializationKind::CreateCopy(ELoc, ELoc);
17472 
17473       InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
17474       ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init);
17475       if (Result.isInvalid())
17476         VDPrivate->setInvalidDecl();
17477       else
17478         VDPrivate->setInit(Result.getAs<Expr>());
17479       // Remove temp variable declaration.
17480       getASTContext().Deallocate(VDInitTemp);
17481     } else {
17482       VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type,
17483                                      ".firstprivate.temp");
17484       VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(),
17485                                        RefExpr->getExprLoc());
17486       SemaRef.AddInitializerToDecl(
17487           VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
17488           /*DirectInit=*/false);
17489     }
17490     if (VDPrivate->isInvalidDecl()) {
17491       if (IsImplicitClause) {
17492         Diag(RefExpr->getExprLoc(),
17493              diag::note_omp_task_predetermined_firstprivate_here);
17494       }
17495       continue;
17496     }
17497     SemaRef.CurContext->addDecl(VDPrivate);
17498     DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
17499         SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(),
17500         RefExpr->getExprLoc());
17501     DeclRefExpr *Ref = nullptr;
17502     if (!VD && !SemaRef.CurContext->isDependentContext()) {
17503       if (TopDVar.CKind == OMPC_lastprivate) {
17504         Ref = TopDVar.PrivateCopy;
17505       } else {
17506         auto *FD = dyn_cast<FieldDecl>(D);
17507         VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
17508         if (VD)
17509           Ref =
17510               buildDeclRefExpr(SemaRef, VD, VD->getType().getNonReferenceType(),
17511                                RefExpr->getExprLoc());
17512         else
17513           Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
17514         if (VD || !isOpenMPCapturedDecl(D))
17515           ExprCaptures.push_back(Ref->getDecl());
17516       }
17517     }
17518     if (!IsImplicitClause)
17519       DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
17520     Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17521                        ? RefExpr->IgnoreParens()
17522                        : Ref);
17523     PrivateCopies.push_back(VDPrivateRefExpr);
17524     Inits.push_back(VDInitRefExpr);
17525   }
17526 
17527   if (Vars.empty())
17528     return nullptr;
17529 
17530   return OMPFirstprivateClause::Create(
17531       getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
17532       buildPreInits(getASTContext(), ExprCaptures));
17533 }
17534 
ActOnOpenMPLastprivateClause(ArrayRef<Expr * > VarList,OpenMPLastprivateModifier LPKind,SourceLocation LPKindLoc,SourceLocation ColonLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)17535 OMPClause *SemaOpenMP::ActOnOpenMPLastprivateClause(
17536     ArrayRef<Expr *> VarList, OpenMPLastprivateModifier LPKind,
17537     SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
17538     SourceLocation LParenLoc, SourceLocation EndLoc) {
17539   if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
17540     assert(ColonLoc.isValid() && "Colon location must be valid.");
17541     Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
17542         << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
17543                                    /*Last=*/OMPC_LASTPRIVATE_unknown)
17544         << getOpenMPClauseName(OMPC_lastprivate);
17545     return nullptr;
17546   }
17547 
17548   SmallVector<Expr *, 8> Vars;
17549   SmallVector<Expr *, 8> SrcExprs;
17550   SmallVector<Expr *, 8> DstExprs;
17551   SmallVector<Expr *, 8> AssignmentOps;
17552   SmallVector<Decl *, 4> ExprCaptures;
17553   SmallVector<Expr *, 4> ExprPostUpdates;
17554   for (Expr *RefExpr : VarList) {
17555     assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
17556     SourceLocation ELoc;
17557     SourceRange ERange;
17558     Expr *SimpleRefExpr = RefExpr;
17559     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17560     if (Res.second) {
17561       // It will be analyzed later.
17562       Vars.push_back(RefExpr);
17563       SrcExprs.push_back(nullptr);
17564       DstExprs.push_back(nullptr);
17565       AssignmentOps.push_back(nullptr);
17566     }
17567     ValueDecl *D = Res.first;
17568     if (!D)
17569       continue;
17570 
17571     QualType Type = D->getType();
17572     auto *VD = dyn_cast<VarDecl>(D);
17573 
17574     // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
17575     //  A variable that appears in a lastprivate clause must not have an
17576     //  incomplete type or a reference type.
17577     if (SemaRef.RequireCompleteType(ELoc, Type,
17578                                     diag::err_omp_lastprivate_incomplete_type))
17579       continue;
17580     Type = Type.getNonReferenceType();
17581 
17582     // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
17583     // A variable that is privatized must not have a const-qualified type
17584     // unless it is of class type with a mutable member. This restriction does
17585     // not apply to the firstprivate clause.
17586     //
17587     // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
17588     // A variable that appears in a lastprivate clause must not have a
17589     // const-qualified type unless it is of class type with a mutable member.
17590     if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc))
17591       continue;
17592 
17593     // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
17594     // A list item that appears in a lastprivate clause with the conditional
17595     // modifier must be a scalar variable.
17596     if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
17597       Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
17598       bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17599                                VarDecl::DeclarationOnly;
17600       Diag(D->getLocation(),
17601            IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17602           << D;
17603       continue;
17604     }
17605 
17606     OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17607     // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
17608     // in a Construct]
17609     //  Variables with the predetermined data-sharing attributes may not be
17610     //  listed in data-sharing attributes clauses, except for the cases
17611     //  listed below.
17612     // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
17613     // A list item may appear in a firstprivate or lastprivate clause but not
17614     // both.
17615     DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17616     if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
17617         (isOpenMPDistributeDirective(CurrDir) ||
17618          DVar.CKind != OMPC_firstprivate) &&
17619         (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
17620       Diag(ELoc, diag::err_omp_wrong_dsa)
17621           << getOpenMPClauseName(DVar.CKind)
17622           << getOpenMPClauseName(OMPC_lastprivate);
17623       reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17624       continue;
17625     }
17626 
17627     // OpenMP [2.14.3.5, Restrictions, p.2]
17628     // A list item that is private within a parallel region, or that appears in
17629     // the reduction clause of a parallel construct, must not appear in a
17630     // lastprivate clause on a worksharing construct if any of the corresponding
17631     // worksharing regions ever binds to any of the corresponding parallel
17632     // regions.
17633     DSAStackTy::DSAVarData TopDVar = DVar;
17634     if (isOpenMPWorksharingDirective(CurrDir) &&
17635         !isOpenMPParallelDirective(CurrDir) &&
17636         !isOpenMPTeamsDirective(CurrDir)) {
17637       DVar = DSAStack->getImplicitDSA(D, true);
17638       if (DVar.CKind != OMPC_shared) {
17639         Diag(ELoc, diag::err_omp_required_access)
17640             << getOpenMPClauseName(OMPC_lastprivate)
17641             << getOpenMPClauseName(OMPC_shared);
17642         reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17643         continue;
17644       }
17645     }
17646 
17647     // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
17648     //  A variable of class type (or array thereof) that appears in a
17649     //  lastprivate clause requires an accessible, unambiguous default
17650     //  constructor for the class type, unless the list item is also specified
17651     //  in a firstprivate clause.
17652     //  A variable of class type (or array thereof) that appears in a
17653     //  lastprivate clause requires an accessible, unambiguous copy assignment
17654     //  operator for the class type.
17655     Type = getASTContext().getBaseElementType(Type).getNonReferenceType();
17656     VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(),
17657                                   Type.getUnqualifiedType(), ".lastprivate.src",
17658                                   D->hasAttrs() ? &D->getAttrs() : nullptr);
17659     DeclRefExpr *PseudoSrcExpr =
17660         buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc);
17661     VarDecl *DstVD =
17662         buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst",
17663                      D->hasAttrs() ? &D->getAttrs() : nullptr);
17664     DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
17665     // For arrays generate assignment operation for single element and replace
17666     // it by the original array element in CodeGen.
17667     ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
17668                                                  PseudoDstExpr, PseudoSrcExpr);
17669     if (AssignmentOp.isInvalid())
17670       continue;
17671     AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
17672                                                /*DiscardedValue*/ false);
17673     if (AssignmentOp.isInvalid())
17674       continue;
17675 
17676     DeclRefExpr *Ref = nullptr;
17677     if (!VD && !SemaRef.CurContext->isDependentContext()) {
17678       if (TopDVar.CKind == OMPC_firstprivate) {
17679         Ref = TopDVar.PrivateCopy;
17680       } else {
17681         Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
17682         if (!isOpenMPCapturedDecl(D))
17683           ExprCaptures.push_back(Ref->getDecl());
17684       }
17685       if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
17686           (!isOpenMPCapturedDecl(D) &&
17687            Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
17688         ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
17689         if (!RefRes.isUsable())
17690           continue;
17691         ExprResult PostUpdateRes =
17692             SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
17693                                SimpleRefExpr, RefRes.get());
17694         if (!PostUpdateRes.isUsable())
17695           continue;
17696         ExprPostUpdates.push_back(
17697             SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
17698       }
17699     }
17700     DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
17701     Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17702                        ? RefExpr->IgnoreParens()
17703                        : Ref);
17704     SrcExprs.push_back(PseudoSrcExpr);
17705     DstExprs.push_back(PseudoDstExpr);
17706     AssignmentOps.push_back(AssignmentOp.get());
17707   }
17708 
17709   if (Vars.empty())
17710     return nullptr;
17711 
17712   return OMPLastprivateClause::Create(
17713       getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
17714       AssignmentOps, LPKind, LPKindLoc, ColonLoc,
17715       buildPreInits(getASTContext(), ExprCaptures),
17716       buildPostUpdate(SemaRef, ExprPostUpdates));
17717 }
17718 
ActOnOpenMPSharedClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)17719 OMPClause *SemaOpenMP::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
17720                                                SourceLocation StartLoc,
17721                                                SourceLocation LParenLoc,
17722                                                SourceLocation EndLoc) {
17723   SmallVector<Expr *, 8> Vars;
17724   for (Expr *RefExpr : VarList) {
17725     assert(RefExpr && "NULL expr in OpenMP lastprivate 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     }
17734     ValueDecl *D = Res.first;
17735     if (!D)
17736       continue;
17737 
17738     auto *VD = dyn_cast<VarDecl>(D);
17739     // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17740     // in a Construct]
17741     //  Variables with the predetermined data-sharing attributes may not be
17742     //  listed in data-sharing attributes clauses, except for the cases
17743     //  listed below. For these exceptions only, listing a predetermined
17744     //  variable in a data-sharing attribute clause is allowed and overrides
17745     //  the variable's predetermined data-sharing attributes.
17746     DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17747     if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
17748         DVar.RefExpr) {
17749       Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17750                                           << getOpenMPClauseName(OMPC_shared);
17751       reportOriginalDsa(SemaRef, DSAStack, D, DVar);
17752       continue;
17753     }
17754 
17755     DeclRefExpr *Ref = nullptr;
17756     if (!VD && isOpenMPCapturedDecl(D) &&
17757         !SemaRef.CurContext->isDependentContext())
17758       Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
17759     DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
17760     Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext())
17761                        ? RefExpr->IgnoreParens()
17762                        : Ref);
17763   }
17764 
17765   if (Vars.empty())
17766     return nullptr;
17767 
17768   return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17769                                  Vars);
17770 }
17771 
17772 namespace {
17773 class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
17774   DSAStackTy *Stack;
17775 
17776 public:
VisitDeclRefExpr(DeclRefExpr * E)17777   bool VisitDeclRefExpr(DeclRefExpr *E) {
17778     if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
17779       DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
17780       if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
17781         return false;
17782       if (DVar.CKind != OMPC_unknown)
17783         return true;
17784       DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
17785           VD,
17786           [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
17787             return isOpenMPPrivate(C) && !AppliedToPointee;
17788           },
17789           [](OpenMPDirectiveKind) { return true; },
17790           /*FromParent=*/true);
17791       return DVarPrivate.CKind != OMPC_unknown;
17792     }
17793     return false;
17794   }
VisitStmt(Stmt * S)17795   bool VisitStmt(Stmt *S) {
17796     for (Stmt *Child : S->children()) {
17797       if (Child && Visit(Child))
17798         return true;
17799     }
17800     return false;
17801   }
DSARefChecker(DSAStackTy * S)17802   explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
17803 };
17804 } // namespace
17805 
17806 namespace {
17807 // Transform MemberExpression for specified FieldDecl of current class to
17808 // DeclRefExpr to specified OMPCapturedExprDecl.
17809 class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
17810   typedef TreeTransform<TransformExprToCaptures> BaseTransform;
17811   ValueDecl *Field = nullptr;
17812   DeclRefExpr *CapturedExpr = nullptr;
17813 
17814 public:
TransformExprToCaptures(Sema & SemaRef,ValueDecl * FieldDecl)17815   TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
17816       : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
17817 
TransformMemberExpr(MemberExpr * E)17818   ExprResult TransformMemberExpr(MemberExpr *E) {
17819     if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
17820         E->getMemberDecl() == Field) {
17821       CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
17822       return CapturedExpr;
17823     }
17824     return BaseTransform::TransformMemberExpr(E);
17825   }
getCapturedExpr()17826   DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
17827 };
17828 } // namespace
17829 
17830 template <typename T, typename U>
filterLookupForUDReductionAndMapper(SmallVectorImpl<U> & Lookups,const llvm::function_ref<T (ValueDecl *)> Gen)17831 static T filterLookupForUDReductionAndMapper(
17832     SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
17833   for (U &Set : Lookups) {
17834     for (auto *D : Set) {
17835       if (T Res = Gen(cast<ValueDecl>(D)))
17836         return Res;
17837     }
17838   }
17839   return T();
17840 }
17841 
findAcceptableDecl(Sema & SemaRef,NamedDecl * D)17842 static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
17843   assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
17844 
17845   for (auto *RD : D->redecls()) {
17846     // Don't bother with extra checks if we already know this one isn't visible.
17847     if (RD == D)
17848       continue;
17849 
17850     auto ND = cast<NamedDecl>(RD);
17851     if (LookupResult::isVisible(SemaRef, ND))
17852       return ND;
17853   }
17854 
17855   return nullptr;
17856 }
17857 
17858 static void
argumentDependentLookup(Sema & SemaRef,const DeclarationNameInfo & Id,SourceLocation Loc,QualType Ty,SmallVectorImpl<UnresolvedSet<8>> & Lookups)17859 argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id,
17860                         SourceLocation Loc, QualType Ty,
17861                         SmallVectorImpl<UnresolvedSet<8>> &Lookups) {
17862   // Find all of the associated namespaces and classes based on the
17863   // arguments we have.
17864   Sema::AssociatedNamespaceSet AssociatedNamespaces;
17865   Sema::AssociatedClassSet AssociatedClasses;
17866   OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
17867   SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
17868                                              AssociatedClasses);
17869 
17870   // C++ [basic.lookup.argdep]p3:
17871   //   Let X be the lookup set produced by unqualified lookup (3.4.1)
17872   //   and let Y be the lookup set produced by argument dependent
17873   //   lookup (defined as follows). If X contains [...] then Y is
17874   //   empty. Otherwise Y is the set of declarations found in the
17875   //   namespaces associated with the argument types as described
17876   //   below. The set of declarations found by the lookup of the name
17877   //   is the union of X and Y.
17878   //
17879   // Here, we compute Y and add its members to the overloaded
17880   // candidate set.
17881   for (auto *NS : AssociatedNamespaces) {
17882     //   When considering an associated namespace, the lookup is the
17883     //   same as the lookup performed when the associated namespace is
17884     //   used as a qualifier (3.4.3.2) except that:
17885     //
17886     //     -- Any using-directives in the associated namespace are
17887     //        ignored.
17888     //
17889     //     -- Any namespace-scope friend functions declared in
17890     //        associated classes are visible within their respective
17891     //        namespaces even if they are not visible during an ordinary
17892     //        lookup (11.4).
17893     DeclContext::lookup_result R = NS->lookup(Id.getName());
17894     for (auto *D : R) {
17895       auto *Underlying = D;
17896       if (auto *USD = dyn_cast<UsingShadowDecl>(D))
17897         Underlying = USD->getTargetDecl();
17898 
17899       if (!isa<OMPDeclareReductionDecl>(Underlying) &&
17900           !isa<OMPDeclareMapperDecl>(Underlying))
17901         continue;
17902 
17903       if (!SemaRef.isVisible(D)) {
17904         D = findAcceptableDecl(SemaRef, D);
17905         if (!D)
17906           continue;
17907         if (auto *USD = dyn_cast<UsingShadowDecl>(D))
17908           Underlying = USD->getTargetDecl();
17909       }
17910       Lookups.emplace_back();
17911       Lookups.back().addDecl(Underlying);
17912     }
17913   }
17914 }
17915 
17916 static ExprResult
buildDeclareReductionRef(Sema & SemaRef,SourceLocation Loc,SourceRange Range,Scope * S,CXXScopeSpec & ReductionIdScopeSpec,const DeclarationNameInfo & ReductionId,QualType Ty,CXXCastPath & BasePath,Expr * UnresolvedReduction)17917 buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
17918                          Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
17919                          const DeclarationNameInfo &ReductionId, QualType Ty,
17920                          CXXCastPath &BasePath, Expr *UnresolvedReduction) {
17921   if (ReductionIdScopeSpec.isInvalid())
17922     return ExprError();
17923   SmallVector<UnresolvedSet<8>, 4> Lookups;
17924   if (S) {
17925     LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
17926     Lookup.suppressDiagnostics();
17927     while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec,
17928                                          /*ObjectType=*/QualType())) {
17929       NamedDecl *D = Lookup.getRepresentativeDecl();
17930       do {
17931         S = S->getParent();
17932       } while (S && !S->isDeclScope(D));
17933       if (S)
17934         S = S->getParent();
17935       Lookups.emplace_back();
17936       Lookups.back().append(Lookup.begin(), Lookup.end());
17937       Lookup.clear();
17938     }
17939   } else if (auto *ULE =
17940                  cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
17941     Lookups.push_back(UnresolvedSet<8>());
17942     Decl *PrevD = nullptr;
17943     for (NamedDecl *D : ULE->decls()) {
17944       if (D == PrevD)
17945         Lookups.push_back(UnresolvedSet<8>());
17946       else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
17947         Lookups.back().addDecl(DRD);
17948       PrevD = D;
17949     }
17950   }
17951   if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
17952       Ty->isInstantiationDependentType() ||
17953       Ty->containsUnexpandedParameterPack() ||
17954       filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
17955         return !D->isInvalidDecl() &&
17956                (D->getType()->isDependentType() ||
17957                 D->getType()->isInstantiationDependentType() ||
17958                 D->getType()->containsUnexpandedParameterPack());
17959       })) {
17960     UnresolvedSet<8> ResSet;
17961     for (const UnresolvedSet<8> &Set : Lookups) {
17962       if (Set.empty())
17963         continue;
17964       ResSet.append(Set.begin(), Set.end());
17965       // The last item marks the end of all declarations at the specified scope.
17966       ResSet.addDecl(Set[Set.size() - 1]);
17967     }
17968     return UnresolvedLookupExpr::Create(
17969         SemaRef.Context, /*NamingClass=*/nullptr,
17970         ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
17971         /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false,
17972         /*KnownInstantiationDependent=*/false);
17973   }
17974   // Lookup inside the classes.
17975   // C++ [over.match.oper]p3:
17976   //   For a unary operator @ with an operand of a type whose
17977   //   cv-unqualified version is T1, and for a binary operator @ with
17978   //   a left operand of a type whose cv-unqualified version is T1 and
17979   //   a right operand of a type whose cv-unqualified version is T2,
17980   //   three sets of candidate functions, designated member
17981   //   candidates, non-member candidates and built-in candidates, are
17982   //   constructed as follows:
17983   //     -- If T1 is a complete class type or a class currently being
17984   //        defined, the set of member candidates is the result of the
17985   //        qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
17986   //        the set of member candidates is empty.
17987   LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
17988   Lookup.suppressDiagnostics();
17989   if (const auto *TyRec = Ty->getAs<RecordType>()) {
17990     // Complete the type if it can be completed.
17991     // If the type is neither complete nor being defined, bail out now.
17992     if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() ||
17993         TyRec->getDecl()->getDefinition()) {
17994       Lookup.clear();
17995       SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
17996       if (Lookup.empty()) {
17997         Lookups.emplace_back();
17998         Lookups.back().append(Lookup.begin(), Lookup.end());
17999       }
18000     }
18001   }
18002   // Perform ADL.
18003   if (SemaRef.getLangOpts().CPlusPlus)
18004     argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
18005   if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18006           Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
18007             if (!D->isInvalidDecl() &&
18008                 SemaRef.Context.hasSameType(D->getType(), Ty))
18009               return D;
18010             return nullptr;
18011           }))
18012     return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
18013                                     VK_LValue, Loc);
18014   if (SemaRef.getLangOpts().CPlusPlus) {
18015     if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18016             Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
18017               if (!D->isInvalidDecl() &&
18018                   SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
18019                   !Ty.isMoreQualifiedThan(D->getType()))
18020                 return D;
18021               return nullptr;
18022             })) {
18023       CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
18024                          /*DetectVirtual=*/false);
18025       if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
18026         if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
18027                 VD->getType().getUnqualifiedType()))) {
18028           if (SemaRef.CheckBaseClassAccess(
18029                   Loc, VD->getType(), Ty, Paths.front(),
18030                   /*DiagID=*/0) != Sema::AR_inaccessible) {
18031             SemaRef.BuildBasePathArray(Paths, BasePath);
18032             return SemaRef.BuildDeclRefExpr(
18033                 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc);
18034           }
18035         }
18036       }
18037     }
18038   }
18039   if (ReductionIdScopeSpec.isSet()) {
18040     SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
18041         << Ty << Range;
18042     return ExprError();
18043   }
18044   return ExprEmpty();
18045 }
18046 
18047 namespace {
18048 /// Data for the reduction-based clauses.
18049 struct ReductionData {
18050   /// List of original reduction items.
18051   SmallVector<Expr *, 8> Vars;
18052   /// List of private copies of the reduction items.
18053   SmallVector<Expr *, 8> Privates;
18054   /// LHS expressions for the reduction_op expressions.
18055   SmallVector<Expr *, 8> LHSs;
18056   /// RHS expressions for the reduction_op expressions.
18057   SmallVector<Expr *, 8> RHSs;
18058   /// Reduction operation expression.
18059   SmallVector<Expr *, 8> ReductionOps;
18060   /// inscan copy operation expressions.
18061   SmallVector<Expr *, 8> InscanCopyOps;
18062   /// inscan copy temp array expressions for prefix sums.
18063   SmallVector<Expr *, 8> InscanCopyArrayTemps;
18064   /// inscan copy temp array element expressions for prefix sums.
18065   SmallVector<Expr *, 8> InscanCopyArrayElems;
18066   /// Taskgroup descriptors for the corresponding reduction items in
18067   /// in_reduction clauses.
18068   SmallVector<Expr *, 8> TaskgroupDescriptors;
18069   /// List of captures for clause.
18070   SmallVector<Decl *, 4> ExprCaptures;
18071   /// List of postupdate expressions.
18072   SmallVector<Expr *, 4> ExprPostUpdates;
18073   /// Reduction modifier.
18074   unsigned RedModifier = 0;
18075   ReductionData() = delete;
18076   /// Reserves required memory for the reduction data.
ReductionData__anon1dd12e447011::ReductionData18077   ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
18078     Vars.reserve(Size);
18079     Privates.reserve(Size);
18080     LHSs.reserve(Size);
18081     RHSs.reserve(Size);
18082     ReductionOps.reserve(Size);
18083     if (RedModifier == OMPC_REDUCTION_inscan) {
18084       InscanCopyOps.reserve(Size);
18085       InscanCopyArrayTemps.reserve(Size);
18086       InscanCopyArrayElems.reserve(Size);
18087     }
18088     TaskgroupDescriptors.reserve(Size);
18089     ExprCaptures.reserve(Size);
18090     ExprPostUpdates.reserve(Size);
18091   }
18092   /// Stores reduction item and reduction operation only (required for dependent
18093   /// reduction item).
push__anon1dd12e447011::ReductionData18094   void push(Expr *Item, Expr *ReductionOp) {
18095     Vars.emplace_back(Item);
18096     Privates.emplace_back(nullptr);
18097     LHSs.emplace_back(nullptr);
18098     RHSs.emplace_back(nullptr);
18099     ReductionOps.emplace_back(ReductionOp);
18100     TaskgroupDescriptors.emplace_back(nullptr);
18101     if (RedModifier == OMPC_REDUCTION_inscan) {
18102       InscanCopyOps.push_back(nullptr);
18103       InscanCopyArrayTemps.push_back(nullptr);
18104       InscanCopyArrayElems.push_back(nullptr);
18105     }
18106   }
18107   /// Stores reduction data.
push__anon1dd12e447011::ReductionData18108   void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
18109             Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
18110             Expr *CopyArrayElem) {
18111     Vars.emplace_back(Item);
18112     Privates.emplace_back(Private);
18113     LHSs.emplace_back(LHS);
18114     RHSs.emplace_back(RHS);
18115     ReductionOps.emplace_back(ReductionOp);
18116     TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
18117     if (RedModifier == OMPC_REDUCTION_inscan) {
18118       InscanCopyOps.push_back(CopyOp);
18119       InscanCopyArrayTemps.push_back(CopyArrayTemp);
18120       InscanCopyArrayElems.push_back(CopyArrayElem);
18121     } else {
18122       assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
18123              CopyArrayElem == nullptr &&
18124              "Copy operation must be used for inscan reductions only.");
18125     }
18126   }
18127 };
18128 } // namespace
18129 
checkOMPArraySectionConstantForReduction(ASTContext & Context,const ArraySectionExpr * OASE,bool & SingleElement,SmallVectorImpl<llvm::APSInt> & ArraySizes)18130 static bool checkOMPArraySectionConstantForReduction(
18131     ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
18132     SmallVectorImpl<llvm::APSInt> &ArraySizes) {
18133   const Expr *Length = OASE->getLength();
18134   if (Length == nullptr) {
18135     // For array sections of the form [1:] or [:], we would need to analyze
18136     // the lower bound...
18137     if (OASE->getColonLocFirst().isValid())
18138       return false;
18139 
18140     // This is an array subscript which has implicit length 1!
18141     SingleElement = true;
18142     ArraySizes.push_back(llvm::APSInt::get(1));
18143   } else {
18144     Expr::EvalResult Result;
18145     if (!Length->EvaluateAsInt(Result, Context))
18146       return false;
18147 
18148     llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18149     SingleElement = (ConstantLengthValue.getSExtValue() == 1);
18150     ArraySizes.push_back(ConstantLengthValue);
18151   }
18152 
18153   // Get the base of this array section and walk up from there.
18154   const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
18155 
18156   // We require length = 1 for all array sections except the right-most to
18157   // guarantee that the memory region is contiguous and has no holes in it.
18158   while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) {
18159     Length = TempOASE->getLength();
18160     if (Length == nullptr) {
18161       // For array sections of the form [1:] or [:], we would need to analyze
18162       // the lower bound...
18163       if (OASE->getColonLocFirst().isValid())
18164         return false;
18165 
18166       // This is an array subscript which has implicit length 1!
18167       ArraySizes.push_back(llvm::APSInt::get(1));
18168     } else {
18169       Expr::EvalResult Result;
18170       if (!Length->EvaluateAsInt(Result, Context))
18171         return false;
18172 
18173       llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18174       if (ConstantLengthValue.getSExtValue() != 1)
18175         return false;
18176 
18177       ArraySizes.push_back(ConstantLengthValue);
18178     }
18179     Base = TempOASE->getBase()->IgnoreParenImpCasts();
18180   }
18181 
18182   // If we have a single element, we don't need to add the implicit lengths.
18183   if (!SingleElement) {
18184     while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
18185       // Has implicit length 1!
18186       ArraySizes.push_back(llvm::APSInt::get(1));
18187       Base = TempASE->getBase()->IgnoreParenImpCasts();
18188     }
18189   }
18190 
18191   // This array section can be privatized as a single value or as a constant
18192   // sized array.
18193   return true;
18194 }
18195 
18196 static BinaryOperatorKind
getRelatedCompoundReductionOp(BinaryOperatorKind BOK)18197 getRelatedCompoundReductionOp(BinaryOperatorKind BOK) {
18198   if (BOK == BO_Add)
18199     return BO_AddAssign;
18200   if (BOK == BO_Mul)
18201     return BO_MulAssign;
18202   if (BOK == BO_And)
18203     return BO_AndAssign;
18204   if (BOK == BO_Or)
18205     return BO_OrAssign;
18206   if (BOK == BO_Xor)
18207     return BO_XorAssign;
18208   return BOK;
18209 }
18210 
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)18211 static bool actOnOMPReductionKindClause(
18212     Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
18213     ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
18214     SourceLocation ColonLoc, SourceLocation EndLoc,
18215     CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
18216     ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
18217   DeclarationName DN = ReductionId.getName();
18218   OverloadedOperatorKind OOK = DN.getCXXOverloadedOperator();
18219   BinaryOperatorKind BOK = BO_Comma;
18220 
18221   ASTContext &Context = S.Context;
18222   // OpenMP [2.14.3.6, reduction clause]
18223   // C
18224   // reduction-identifier is either an identifier or one of the following
18225   // operators: +, -, *,  &, |, ^, && and ||
18226   // C++
18227   // reduction-identifier is either an id-expression or one of the following
18228   // operators: +, -, *, &, |, ^, && and ||
18229   switch (OOK) {
18230   case OO_Plus:
18231     BOK = BO_Add;
18232     break;
18233   case OO_Minus:
18234     // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
18235     // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
18236     // reduction identifier.
18237     if (S.LangOpts.OpenMP > 52)
18238       BOK = BO_Comma;
18239     else
18240       BOK = BO_Add;
18241     break;
18242   case OO_Star:
18243     BOK = BO_Mul;
18244     break;
18245   case OO_Amp:
18246     BOK = BO_And;
18247     break;
18248   case OO_Pipe:
18249     BOK = BO_Or;
18250     break;
18251   case OO_Caret:
18252     BOK = BO_Xor;
18253     break;
18254   case OO_AmpAmp:
18255     BOK = BO_LAnd;
18256     break;
18257   case OO_PipePipe:
18258     BOK = BO_LOr;
18259     break;
18260   case OO_New:
18261   case OO_Delete:
18262   case OO_Array_New:
18263   case OO_Array_Delete:
18264   case OO_Slash:
18265   case OO_Percent:
18266   case OO_Tilde:
18267   case OO_Exclaim:
18268   case OO_Equal:
18269   case OO_Less:
18270   case OO_Greater:
18271   case OO_LessEqual:
18272   case OO_GreaterEqual:
18273   case OO_PlusEqual:
18274   case OO_MinusEqual:
18275   case OO_StarEqual:
18276   case OO_SlashEqual:
18277   case OO_PercentEqual:
18278   case OO_CaretEqual:
18279   case OO_AmpEqual:
18280   case OO_PipeEqual:
18281   case OO_LessLess:
18282   case OO_GreaterGreater:
18283   case OO_LessLessEqual:
18284   case OO_GreaterGreaterEqual:
18285   case OO_EqualEqual:
18286   case OO_ExclaimEqual:
18287   case OO_Spaceship:
18288   case OO_PlusPlus:
18289   case OO_MinusMinus:
18290   case OO_Comma:
18291   case OO_ArrowStar:
18292   case OO_Arrow:
18293   case OO_Call:
18294   case OO_Subscript:
18295   case OO_Conditional:
18296   case OO_Coawait:
18297   case NUM_OVERLOADED_OPERATORS:
18298     llvm_unreachable("Unexpected reduction identifier");
18299   case OO_None:
18300     if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
18301       if (II->isStr("max"))
18302         BOK = BO_GT;
18303       else if (II->isStr("min"))
18304         BOK = BO_LT;
18305     }
18306     break;
18307   }
18308 
18309   // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
18310   // A reduction clause with the minus (-) operator was deprecated
18311   if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
18312     S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
18313 
18314   SourceRange ReductionIdRange;
18315   if (ReductionIdScopeSpec.isValid())
18316     ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
18317   else
18318     ReductionIdRange.setBegin(ReductionId.getBeginLoc());
18319   ReductionIdRange.setEnd(ReductionId.getEndLoc());
18320 
18321   auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
18322   bool FirstIter = true;
18323   for (Expr *RefExpr : VarList) {
18324     assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
18325     // OpenMP [2.1, C/C++]
18326     //  A list item is a variable or array section, subject to the restrictions
18327     //  specified in Section 2.4 on page 42 and in each of the sections
18328     // describing clauses and directives for which a list appears.
18329     // OpenMP  [2.14.3.3, Restrictions, p.1]
18330     //  A variable that is part of another variable (as an array or
18331     //  structure element) cannot appear in a private clause.
18332     if (!FirstIter && IR != ER)
18333       ++IR;
18334     FirstIter = false;
18335     SourceLocation ELoc;
18336     SourceRange ERange;
18337     Expr *SimpleRefExpr = RefExpr;
18338     auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
18339                               /*AllowArraySection=*/true);
18340     if (Res.second) {
18341       // Try to find 'declare reduction' corresponding construct before using
18342       // builtin/overloaded operators.
18343       QualType Type = Context.DependentTy;
18344       CXXCastPath BasePath;
18345       ExprResult DeclareReductionRef = buildDeclareReductionRef(
18346           S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18347           ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
18348       Expr *ReductionOp = nullptr;
18349       if (S.CurContext->isDependentContext() &&
18350           (DeclareReductionRef.isUnset() ||
18351            isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
18352         ReductionOp = DeclareReductionRef.get();
18353       // It will be analyzed later.
18354       RD.push(RefExpr, ReductionOp);
18355     }
18356     ValueDecl *D = Res.first;
18357     if (!D)
18358       continue;
18359 
18360     Expr *TaskgroupDescriptor = nullptr;
18361     QualType Type;
18362     auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
18363     auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
18364     if (ASE) {
18365       Type = ASE->getType().getNonReferenceType();
18366     } else if (OASE) {
18367       QualType BaseType =
18368           ArraySectionExpr::getBaseOriginalType(OASE->getBase());
18369       if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
18370         Type = ATy->getElementType();
18371       else
18372         Type = BaseType->getPointeeType();
18373       Type = Type.getNonReferenceType();
18374     } else {
18375       Type = Context.getBaseElementType(D->getType().getNonReferenceType());
18376     }
18377     auto *VD = dyn_cast<VarDecl>(D);
18378 
18379     // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18380     //  A variable that appears in a private clause must not have an incomplete
18381     //  type or a reference type.
18382     if (S.RequireCompleteType(ELoc, D->getType(),
18383                               diag::err_omp_reduction_incomplete_type))
18384       continue;
18385     // OpenMP [2.14.3.6, reduction clause, Restrictions]
18386     // A list item that appears in a reduction clause must not be
18387     // const-qualified.
18388     if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
18389                                   /*AcceptIfMutable*/ false, ASE || OASE))
18390       continue;
18391 
18392     OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
18393     // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
18394     //  If a list-item is a reference type then it must bind to the same object
18395     //  for all threads of the team.
18396     if (!ASE && !OASE) {
18397       if (VD) {
18398         VarDecl *VDDef = VD->getDefinition();
18399         if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
18400           DSARefChecker Check(Stack);
18401           if (Check.Visit(VDDef->getInit())) {
18402             S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
18403                 << getOpenMPClauseName(ClauseKind) << ERange;
18404             S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
18405             continue;
18406           }
18407         }
18408       }
18409 
18410       // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18411       // in a Construct]
18412       //  Variables with the predetermined data-sharing attributes may not be
18413       //  listed in data-sharing attributes clauses, except for the cases
18414       //  listed below. For these exceptions only, listing a predetermined
18415       //  variable in a data-sharing attribute clause is allowed and overrides
18416       //  the variable's predetermined data-sharing attributes.
18417       // OpenMP [2.14.3.6, Restrictions, p.3]
18418       //  Any number of reduction clauses can be specified on the directive,
18419       //  but a list item can appear only once in the reduction clauses for that
18420       //  directive.
18421       DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
18422       if (DVar.CKind == OMPC_reduction) {
18423         S.Diag(ELoc, diag::err_omp_once_referenced)
18424             << getOpenMPClauseName(ClauseKind);
18425         if (DVar.RefExpr)
18426           S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
18427         continue;
18428       }
18429       if (DVar.CKind != OMPC_unknown) {
18430         S.Diag(ELoc, diag::err_omp_wrong_dsa)
18431             << getOpenMPClauseName(DVar.CKind)
18432             << getOpenMPClauseName(OMPC_reduction);
18433         reportOriginalDsa(S, Stack, D, DVar);
18434         continue;
18435       }
18436 
18437       // OpenMP [2.14.3.6, Restrictions, p.1]
18438       //  A list item that appears in a reduction clause of a worksharing
18439       //  construct must be shared in the parallel regions to which any of the
18440       //  worksharing regions arising from the worksharing construct bind.
18441       if (isOpenMPWorksharingDirective(CurrDir) &&
18442           !isOpenMPParallelDirective(CurrDir) &&
18443           !isOpenMPTeamsDirective(CurrDir)) {
18444         DVar = Stack->getImplicitDSA(D, true);
18445         if (DVar.CKind != OMPC_shared) {
18446           S.Diag(ELoc, diag::err_omp_required_access)
18447               << getOpenMPClauseName(OMPC_reduction)
18448               << getOpenMPClauseName(OMPC_shared);
18449           reportOriginalDsa(S, Stack, D, DVar);
18450           continue;
18451         }
18452       }
18453     } else {
18454       // Threadprivates cannot be shared between threads, so dignose if the base
18455       // is a threadprivate variable.
18456       DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
18457       if (DVar.CKind == OMPC_threadprivate) {
18458         S.Diag(ELoc, diag::err_omp_wrong_dsa)
18459             << getOpenMPClauseName(DVar.CKind)
18460             << getOpenMPClauseName(OMPC_reduction);
18461         reportOriginalDsa(S, Stack, D, DVar);
18462         continue;
18463       }
18464     }
18465 
18466     // Try to find 'declare reduction' corresponding construct before using
18467     // builtin/overloaded operators.
18468     CXXCastPath BasePath;
18469     ExprResult DeclareReductionRef = buildDeclareReductionRef(
18470         S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18471         ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
18472     if (DeclareReductionRef.isInvalid())
18473       continue;
18474     if (S.CurContext->isDependentContext() &&
18475         (DeclareReductionRef.isUnset() ||
18476          isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
18477       RD.push(RefExpr, DeclareReductionRef.get());
18478       continue;
18479     }
18480     if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
18481       // Not allowed reduction identifier is found.
18482       if (S.LangOpts.OpenMP > 52)
18483         S.Diag(ReductionId.getBeginLoc(),
18484                diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
18485             << Type << ReductionIdRange;
18486       else
18487         S.Diag(ReductionId.getBeginLoc(),
18488                diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
18489             << Type << ReductionIdRange;
18490       continue;
18491     }
18492 
18493     // OpenMP [2.14.3.6, reduction clause, Restrictions]
18494     // The type of a list item that appears in a reduction clause must be valid
18495     // for the reduction-identifier. For a max or min reduction in C, the type
18496     // of the list item must be an allowed arithmetic data type: char, int,
18497     // float, double, or _Bool, possibly modified with long, short, signed, or
18498     // unsigned. For a max or min reduction in C++, the type of the list item
18499     // must be an allowed arithmetic data type: char, wchar_t, int, float,
18500     // double, or bool, possibly modified with long, short, signed, or unsigned.
18501     if (DeclareReductionRef.isUnset()) {
18502       if ((BOK == BO_GT || BOK == BO_LT) &&
18503           !(Type->isScalarType() ||
18504             (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
18505         S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
18506             << getOpenMPClauseName(ClauseKind) << S.getLangOpts().CPlusPlus;
18507         if (!ASE && !OASE) {
18508           bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18509                                    VarDecl::DeclarationOnly;
18510           S.Diag(D->getLocation(),
18511                  IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18512               << D;
18513         }
18514         continue;
18515       }
18516       if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
18517           !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
18518         S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
18519             << getOpenMPClauseName(ClauseKind);
18520         if (!ASE && !OASE) {
18521           bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18522                                    VarDecl::DeclarationOnly;
18523           S.Diag(D->getLocation(),
18524                  IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18525               << D;
18526         }
18527         continue;
18528       }
18529     }
18530 
18531     Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
18532     VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
18533                                   D->hasAttrs() ? &D->getAttrs() : nullptr);
18534     VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
18535                                   D->hasAttrs() ? &D->getAttrs() : nullptr);
18536     QualType PrivateTy = Type;
18537 
18538     // Try if we can determine constant lengths for all array sections and avoid
18539     // the VLA.
18540     bool ConstantLengthOASE = false;
18541     if (OASE) {
18542       bool SingleElement;
18543       llvm::SmallVector<llvm::APSInt, 4> ArraySizes;
18544       ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
18545           Context, OASE, SingleElement, ArraySizes);
18546 
18547       // If we don't have a single element, we must emit a constant array type.
18548       if (ConstantLengthOASE && !SingleElement) {
18549         for (llvm::APSInt &Size : ArraySizes)
18550           PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
18551                                                    ArraySizeModifier::Normal,
18552                                                    /*IndexTypeQuals=*/0);
18553       }
18554     }
18555 
18556     if ((OASE && !ConstantLengthOASE) ||
18557         (!OASE && !ASE &&
18558          D->getType().getNonReferenceType()->isVariablyModifiedType())) {
18559       if (!Context.getTargetInfo().isVLASupported()) {
18560         if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
18561           S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18562           S.Diag(ELoc, diag::note_vla_unsupported);
18563           continue;
18564         } else {
18565           S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18566           S.targetDiag(ELoc, diag::note_vla_unsupported);
18567         }
18568       }
18569       // For arrays/array sections only:
18570       // Create pseudo array type for private copy. The size for this array will
18571       // be generated during codegen.
18572       // For array subscripts or single variables Private Ty is the same as Type
18573       // (type of the variable or single array element).
18574       PrivateTy = Context.getVariableArrayType(
18575           Type,
18576           new (Context)
18577               OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
18578           ArraySizeModifier::Normal, /*IndexTypeQuals=*/0, SourceRange());
18579     } else if (!ASE && !OASE &&
18580                Context.getAsArrayType(D->getType().getNonReferenceType())) {
18581       PrivateTy = D->getType().getNonReferenceType();
18582     }
18583     // Private copy.
18584     VarDecl *PrivateVD =
18585         buildVarDecl(S, ELoc, PrivateTy, D->getName(),
18586                      D->hasAttrs() ? &D->getAttrs() : nullptr,
18587                      VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18588     // Add initializer for private variable.
18589     Expr *Init = nullptr;
18590     DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
18591     DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
18592     if (DeclareReductionRef.isUsable()) {
18593       auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
18594       auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
18595       if (DRD->getInitializer()) {
18596         Init = DRDRef;
18597         RHSVD->setInit(DRDRef);
18598         RHSVD->setInitStyle(VarDecl::CallInit);
18599       }
18600     } else {
18601       switch (BOK) {
18602       case BO_Add:
18603       case BO_Xor:
18604       case BO_Or:
18605       case BO_LOr:
18606         // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
18607         if (Type->isScalarType() || Type->isAnyComplexType())
18608           Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
18609         break;
18610       case BO_Mul:
18611       case BO_LAnd:
18612         if (Type->isScalarType() || Type->isAnyComplexType()) {
18613           // '*' and '&&' reduction ops - initializer is '1'.
18614           Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
18615         }
18616         break;
18617       case BO_And: {
18618         // '&' reduction op - initializer is '~0'.
18619         QualType OrigType = Type;
18620         if (auto *ComplexTy = OrigType->getAs<ComplexType>())
18621           Type = ComplexTy->getElementType();
18622         if (Type->isRealFloatingType()) {
18623           llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
18624               Context.getFloatTypeSemantics(Type));
18625           Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
18626                                          Type, ELoc);
18627         } else if (Type->isScalarType()) {
18628           uint64_t Size = Context.getTypeSize(Type);
18629           QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
18630           llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
18631           Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
18632         }
18633         if (Init && OrigType->isAnyComplexType()) {
18634           // Init = 0xFFFF + 0xFFFFi;
18635           auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
18636           Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
18637         }
18638         Type = OrigType;
18639         break;
18640       }
18641       case BO_LT:
18642       case BO_GT: {
18643         // 'min' reduction op - initializer is 'Largest representable number in
18644         // the reduction list item type'.
18645         // 'max' reduction op - initializer is 'Least representable number in
18646         // the reduction list item type'.
18647         if (Type->isIntegerType() || Type->isPointerType()) {
18648           bool IsSigned = Type->hasSignedIntegerRepresentation();
18649           uint64_t Size = Context.getTypeSize(Type);
18650           QualType IntTy =
18651               Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
18652           llvm::APInt InitValue =
18653               (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
18654                                         : llvm::APInt::getMinValue(Size)
18655               : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
18656                              : llvm::APInt::getMaxValue(Size);
18657           Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
18658           if (Type->isPointerType()) {
18659             // Cast to pointer type.
18660             ExprResult CastExpr = S.BuildCStyleCastExpr(
18661                 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
18662             if (CastExpr.isInvalid())
18663               continue;
18664             Init = CastExpr.get();
18665           }
18666         } else if (Type->isRealFloatingType()) {
18667           llvm::APFloat InitValue = llvm::APFloat::getLargest(
18668               Context.getFloatTypeSemantics(Type), BOK != BO_LT);
18669           Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
18670                                          Type, ELoc);
18671         }
18672         break;
18673       }
18674       case BO_PtrMemD:
18675       case BO_PtrMemI:
18676       case BO_MulAssign:
18677       case BO_Div:
18678       case BO_Rem:
18679       case BO_Sub:
18680       case BO_Shl:
18681       case BO_Shr:
18682       case BO_LE:
18683       case BO_GE:
18684       case BO_EQ:
18685       case BO_NE:
18686       case BO_Cmp:
18687       case BO_AndAssign:
18688       case BO_XorAssign:
18689       case BO_OrAssign:
18690       case BO_Assign:
18691       case BO_AddAssign:
18692       case BO_SubAssign:
18693       case BO_DivAssign:
18694       case BO_RemAssign:
18695       case BO_ShlAssign:
18696       case BO_ShrAssign:
18697       case BO_Comma:
18698         llvm_unreachable("Unexpected reduction operation");
18699       }
18700     }
18701     if (Init && DeclareReductionRef.isUnset()) {
18702       S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
18703       // Store initializer for single element in private copy. Will be used
18704       // during codegen.
18705       PrivateVD->setInit(RHSVD->getInit());
18706       PrivateVD->setInitStyle(RHSVD->getInitStyle());
18707     } else if (!Init) {
18708       S.ActOnUninitializedDecl(RHSVD);
18709       // Store initializer for single element in private copy. Will be used
18710       // during codegen.
18711       PrivateVD->setInit(RHSVD->getInit());
18712       PrivateVD->setInitStyle(RHSVD->getInitStyle());
18713     }
18714     if (RHSVD->isInvalidDecl())
18715       continue;
18716     if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
18717       S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
18718           << Type << ReductionIdRange;
18719       bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18720                                VarDecl::DeclarationOnly;
18721       S.Diag(D->getLocation(),
18722              IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18723           << D;
18724       continue;
18725     }
18726     DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
18727     ExprResult ReductionOp;
18728     if (DeclareReductionRef.isUsable()) {
18729       QualType RedTy = DeclareReductionRef.get()->getType();
18730       QualType PtrRedTy = Context.getPointerType(RedTy);
18731       ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
18732       ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
18733       if (!BasePath.empty()) {
18734         LHS = S.DefaultLvalueConversion(LHS.get());
18735         RHS = S.DefaultLvalueConversion(RHS.get());
18736         LHS = ImplicitCastExpr::Create(
18737             Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
18738             LHS.get()->getValueKind(), FPOptionsOverride());
18739         RHS = ImplicitCastExpr::Create(
18740             Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
18741             RHS.get()->getValueKind(), FPOptionsOverride());
18742       }
18743       FunctionProtoType::ExtProtoInfo EPI;
18744       QualType Params[] = {PtrRedTy, PtrRedTy};
18745       QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
18746       auto *OVE = new (Context) OpaqueValueExpr(
18747           ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
18748           S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
18749       Expr *Args[] = {LHS.get(), RHS.get()};
18750       ReductionOp =
18751           CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
18752                            S.CurFPFeatureOverrides());
18753     } else {
18754       BinaryOperatorKind CombBOK = getRelatedCompoundReductionOp(BOK);
18755       if (Type->isRecordType() && CombBOK != BOK) {
18756         Sema::TentativeAnalysisScope Trap(S);
18757         ReductionOp =
18758             S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
18759                          CombBOK, LHSDRE, RHSDRE);
18760       }
18761       if (!ReductionOp.isUsable()) {
18762         ReductionOp =
18763             S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
18764                          LHSDRE, RHSDRE);
18765         if (ReductionOp.isUsable()) {
18766           if (BOK != BO_LT && BOK != BO_GT) {
18767             ReductionOp =
18768                 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
18769                              BO_Assign, LHSDRE, ReductionOp.get());
18770           } else {
18771             auto *ConditionalOp = new (Context)
18772                 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
18773                                     RHSDRE, Type, VK_LValue, OK_Ordinary);
18774             ReductionOp =
18775                 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
18776                              BO_Assign, LHSDRE, ConditionalOp);
18777           }
18778         }
18779       }
18780       if (ReductionOp.isUsable())
18781         ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
18782                                             /*DiscardedValue*/ false);
18783       if (!ReductionOp.isUsable())
18784         continue;
18785     }
18786 
18787     // Add copy operations for inscan reductions.
18788     // LHS = RHS;
18789     ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
18790     if (ClauseKind == OMPC_reduction &&
18791         RD.RedModifier == OMPC_REDUCTION_inscan) {
18792       ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
18793       CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
18794                                RHS.get());
18795       if (!CopyOpRes.isUsable())
18796         continue;
18797       CopyOpRes =
18798           S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
18799       if (!CopyOpRes.isUsable())
18800         continue;
18801       // For simd directive and simd-based directives in simd mode no need to
18802       // construct temp array, need just a single temp element.
18803       if (Stack->getCurrentDirective() == OMPD_simd ||
18804           (S.getLangOpts().OpenMPSimd &&
18805            isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
18806         VarDecl *TempArrayVD =
18807             buildVarDecl(S, ELoc, PrivateTy, D->getName(),
18808                          D->hasAttrs() ? &D->getAttrs() : nullptr);
18809         // Add a constructor to the temp decl.
18810         S.ActOnUninitializedDecl(TempArrayVD);
18811         TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
18812       } else {
18813         // Build temp array for prefix sum.
18814         auto *Dim = new (S.Context)
18815             OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
18816         QualType ArrayTy = S.Context.getVariableArrayType(
18817             PrivateTy, Dim, ArraySizeModifier::Normal,
18818             /*IndexTypeQuals=*/0, {ELoc, ELoc});
18819         VarDecl *TempArrayVD =
18820             buildVarDecl(S, ELoc, ArrayTy, D->getName(),
18821                          D->hasAttrs() ? &D->getAttrs() : nullptr);
18822         // Add a constructor to the temp decl.
18823         S.ActOnUninitializedDecl(TempArrayVD);
18824         TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
18825         TempArrayElem =
18826             S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
18827         auto *Idx = new (S.Context)
18828             OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
18829         TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
18830                                                           ELoc, Idx, ELoc);
18831       }
18832     }
18833 
18834     // OpenMP [2.15.4.6, Restrictions, p.2]
18835     // A list item that appears in an in_reduction clause of a task construct
18836     // must appear in a task_reduction clause of a construct associated with a
18837     // taskgroup region that includes the participating task in its taskgroup
18838     // set. The construct associated with the innermost region that meets this
18839     // condition must specify the same reduction-identifier as the in_reduction
18840     // clause.
18841     if (ClauseKind == OMPC_in_reduction) {
18842       SourceRange ParentSR;
18843       BinaryOperatorKind ParentBOK;
18844       const Expr *ParentReductionOp = nullptr;
18845       Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
18846       DSAStackTy::DSAVarData ParentBOKDSA =
18847           Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
18848                                                   ParentBOKTD);
18849       DSAStackTy::DSAVarData ParentReductionOpDSA =
18850           Stack->getTopMostTaskgroupReductionData(
18851               D, ParentSR, ParentReductionOp, ParentReductionOpTD);
18852       bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
18853       bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
18854       if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
18855           (DeclareReductionRef.isUsable() && IsParentBOK) ||
18856           (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
18857         bool EmitError = true;
18858         if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
18859           llvm::FoldingSetNodeID RedId, ParentRedId;
18860           ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
18861           DeclareReductionRef.get()->Profile(RedId, Context,
18862                                              /*Canonical=*/true);
18863           EmitError = RedId != ParentRedId;
18864         }
18865         if (EmitError) {
18866           S.Diag(ReductionId.getBeginLoc(),
18867                  diag::err_omp_reduction_identifier_mismatch)
18868               << ReductionIdRange << RefExpr->getSourceRange();
18869           S.Diag(ParentSR.getBegin(),
18870                  diag::note_omp_previous_reduction_identifier)
18871               << ParentSR
18872               << (IsParentBOK ? ParentBOKDSA.RefExpr
18873                               : ParentReductionOpDSA.RefExpr)
18874                      ->getSourceRange();
18875           continue;
18876         }
18877       }
18878       TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
18879     }
18880 
18881     DeclRefExpr *Ref = nullptr;
18882     Expr *VarsExpr = RefExpr->IgnoreParens();
18883     if (!VD && !S.CurContext->isDependentContext()) {
18884       if (ASE || OASE) {
18885         TransformExprToCaptures RebuildToCapture(S, D);
18886         VarsExpr =
18887             RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
18888         Ref = RebuildToCapture.getCapturedExpr();
18889       } else {
18890         VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
18891       }
18892       if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
18893         RD.ExprCaptures.emplace_back(Ref->getDecl());
18894         if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
18895           ExprResult RefRes = S.DefaultLvalueConversion(Ref);
18896           if (!RefRes.isUsable())
18897             continue;
18898           ExprResult PostUpdateRes =
18899               S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
18900                            RefRes.get());
18901           if (!PostUpdateRes.isUsable())
18902             continue;
18903           if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
18904               Stack->getCurrentDirective() == OMPD_taskgroup) {
18905             S.Diag(RefExpr->getExprLoc(),
18906                    diag::err_omp_reduction_non_addressable_expression)
18907                 << RefExpr->getSourceRange();
18908             continue;
18909           }
18910           RD.ExprPostUpdates.emplace_back(
18911               S.IgnoredValueConversions(PostUpdateRes.get()).get());
18912         }
18913       }
18914     }
18915     // All reduction items are still marked as reduction (to do not increase
18916     // code base size).
18917     unsigned Modifier = RD.RedModifier;
18918     // Consider task_reductions as reductions with task modifier. Required for
18919     // correct analysis of in_reduction clauses.
18920     if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
18921       Modifier = OMPC_REDUCTION_task;
18922     Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
18923                   ASE || OASE);
18924     if (Modifier == OMPC_REDUCTION_task &&
18925         (CurrDir == OMPD_taskgroup ||
18926          ((isOpenMPParallelDirective(CurrDir) ||
18927            isOpenMPWorksharingDirective(CurrDir)) &&
18928           !isOpenMPSimdDirective(CurrDir)))) {
18929       if (DeclareReductionRef.isUsable())
18930         Stack->addTaskgroupReductionData(D, ReductionIdRange,
18931                                          DeclareReductionRef.get());
18932       else
18933         Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
18934     }
18935     RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
18936             TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
18937             TempArrayElem.get());
18938   }
18939   return RD.Vars.empty();
18940 }
18941 
ActOnOpenMPReductionClause(ArrayRef<Expr * > VarList,OpenMPReductionClauseModifier Modifier,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ModifierLoc,SourceLocation ColonLoc,SourceLocation EndLoc,CXXScopeSpec & ReductionIdScopeSpec,const DeclarationNameInfo & ReductionId,ArrayRef<Expr * > UnresolvedReductions)18942 OMPClause *SemaOpenMP::ActOnOpenMPReductionClause(
18943     ArrayRef<Expr *> VarList, OpenMPReductionClauseModifier Modifier,
18944     SourceLocation StartLoc, SourceLocation LParenLoc,
18945     SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
18946     CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
18947     ArrayRef<Expr *> UnresolvedReductions) {
18948   if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
18949     Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
18950         << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
18951                                    /*Last=*/OMPC_REDUCTION_unknown)
18952         << getOpenMPClauseName(OMPC_reduction);
18953     return nullptr;
18954   }
18955   // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
18956   // A reduction clause with the inscan reduction-modifier may only appear on a
18957   // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
18958   // construct, a parallel worksharing-loop construct or a parallel
18959   // worksharing-loop SIMD construct.
18960   if (Modifier == OMPC_REDUCTION_inscan &&
18961       (DSAStack->getCurrentDirective() != OMPD_for &&
18962        DSAStack->getCurrentDirective() != OMPD_for_simd &&
18963        DSAStack->getCurrentDirective() != OMPD_simd &&
18964        DSAStack->getCurrentDirective() != OMPD_parallel_for &&
18965        DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
18966     Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
18967     return nullptr;
18968   }
18969 
18970   ReductionData RD(VarList.size(), Modifier);
18971   if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
18972                                   StartLoc, LParenLoc, ColonLoc, EndLoc,
18973                                   ReductionIdScopeSpec, ReductionId,
18974                                   UnresolvedReductions, RD))
18975     return nullptr;
18976 
18977   return OMPReductionClause::Create(
18978       getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
18979       Modifier, RD.Vars,
18980       ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
18981       RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
18982       RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
18983       buildPreInits(getASTContext(), RD.ExprCaptures),
18984       buildPostUpdate(SemaRef, RD.ExprPostUpdates));
18985 }
18986 
ActOnOpenMPTaskReductionClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ColonLoc,SourceLocation EndLoc,CXXScopeSpec & ReductionIdScopeSpec,const DeclarationNameInfo & ReductionId,ArrayRef<Expr * > UnresolvedReductions)18987 OMPClause *SemaOpenMP::ActOnOpenMPTaskReductionClause(
18988     ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
18989     SourceLocation ColonLoc, SourceLocation EndLoc,
18990     CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
18991     ArrayRef<Expr *> UnresolvedReductions) {
18992   ReductionData RD(VarList.size());
18993   if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction,
18994                                   VarList, StartLoc, LParenLoc, ColonLoc,
18995                                   EndLoc, ReductionIdScopeSpec, ReductionId,
18996                                   UnresolvedReductions, RD))
18997     return nullptr;
18998 
18999   return OMPTaskReductionClause::Create(
19000       getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19001       ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19002       RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
19003       buildPreInits(getASTContext(), RD.ExprCaptures),
19004       buildPostUpdate(SemaRef, RD.ExprPostUpdates));
19005 }
19006 
ActOnOpenMPInReductionClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ColonLoc,SourceLocation EndLoc,CXXScopeSpec & ReductionIdScopeSpec,const DeclarationNameInfo & ReductionId,ArrayRef<Expr * > UnresolvedReductions)19007 OMPClause *SemaOpenMP::ActOnOpenMPInReductionClause(
19008     ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19009     SourceLocation ColonLoc, SourceLocation EndLoc,
19010     CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19011     ArrayRef<Expr *> UnresolvedReductions) {
19012   ReductionData RD(VarList.size());
19013   if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList,
19014                                   StartLoc, LParenLoc, ColonLoc, EndLoc,
19015                                   ReductionIdScopeSpec, ReductionId,
19016                                   UnresolvedReductions, RD))
19017     return nullptr;
19018 
19019   return OMPInReductionClause::Create(
19020       getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19021       ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19022       RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
19023       buildPreInits(getASTContext(), RD.ExprCaptures),
19024       buildPostUpdate(SemaRef, RD.ExprPostUpdates));
19025 }
19026 
CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,SourceLocation LinLoc)19027 bool SemaOpenMP::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
19028                                            SourceLocation LinLoc) {
19029   if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
19030       LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
19031     Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
19032         << getLangOpts().CPlusPlus;
19033     return true;
19034   }
19035   return false;
19036 }
19037 
CheckOpenMPLinearDecl(const ValueDecl * D,SourceLocation ELoc,OpenMPLinearClauseKind LinKind,QualType Type,bool IsDeclareSimd)19038 bool SemaOpenMP::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc,
19039                                        OpenMPLinearClauseKind LinKind,
19040                                        QualType Type, bool IsDeclareSimd) {
19041   const auto *VD = dyn_cast_or_null<VarDecl>(D);
19042   // A variable must not have an incomplete type or a reference type.
19043   if (SemaRef.RequireCompleteType(ELoc, Type,
19044                                   diag::err_omp_linear_incomplete_type))
19045     return true;
19046   if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
19047       !Type->isReferenceType()) {
19048     Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
19049         << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
19050     return true;
19051   }
19052   Type = Type.getNonReferenceType();
19053 
19054   // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19055   // A variable that is privatized must not have a const-qualified type
19056   // unless it is of class type with a mutable member. This restriction does
19057   // not apply to the firstprivate clause, nor to the linear clause on
19058   // declarative directives (like declare simd).
19059   if (!IsDeclareSimd &&
19060       rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc))
19061     return true;
19062 
19063   // A list item must be of integral or pointer type.
19064   Type = Type.getUnqualifiedType().getCanonicalType();
19065   const auto *Ty = Type.getTypePtrOrNull();
19066   if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
19067               !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) {
19068     Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
19069     if (D) {
19070       bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19071                                VarDecl::DeclarationOnly;
19072       Diag(D->getLocation(),
19073            IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19074           << D;
19075     }
19076     return true;
19077   }
19078   return false;
19079 }
19080 
ActOnOpenMPLinearClause(ArrayRef<Expr * > VarList,Expr * Step,SourceLocation StartLoc,SourceLocation LParenLoc,OpenMPLinearClauseKind LinKind,SourceLocation LinLoc,SourceLocation ColonLoc,SourceLocation StepModifierLoc,SourceLocation EndLoc)19081 OMPClause *SemaOpenMP::ActOnOpenMPLinearClause(
19082     ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
19083     SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
19084     SourceLocation LinLoc, SourceLocation ColonLoc,
19085     SourceLocation StepModifierLoc, SourceLocation EndLoc) {
19086   SmallVector<Expr *, 8> Vars;
19087   SmallVector<Expr *, 8> Privates;
19088   SmallVector<Expr *, 8> Inits;
19089   SmallVector<Decl *, 4> ExprCaptures;
19090   SmallVector<Expr *, 4> ExprPostUpdates;
19091   // OpenMP 5.2 [Section 5.4.6, linear clause]
19092   // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
19093   // 'ref'
19094   if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
19095       getLangOpts().OpenMP >= 52)
19096     Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
19097   if (CheckOpenMPLinearModifier(LinKind, LinLoc))
19098     LinKind = OMPC_LINEAR_val;
19099   for (Expr *RefExpr : VarList) {
19100     assert(RefExpr && "NULL expr in OpenMP linear clause.");
19101     SourceLocation ELoc;
19102     SourceRange ERange;
19103     Expr *SimpleRefExpr = RefExpr;
19104     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19105     if (Res.second) {
19106       // It will be analyzed later.
19107       Vars.push_back(RefExpr);
19108       Privates.push_back(nullptr);
19109       Inits.push_back(nullptr);
19110     }
19111     ValueDecl *D = Res.first;
19112     if (!D)
19113       continue;
19114 
19115     QualType Type = D->getType();
19116     auto *VD = dyn_cast<VarDecl>(D);
19117 
19118     // OpenMP [2.14.3.7, linear clause]
19119     //  A list-item cannot appear in more than one linear clause.
19120     //  A list-item that appears in a linear clause cannot appear in any
19121     //  other data-sharing attribute clause.
19122     DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19123     if (DVar.RefExpr) {
19124       Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
19125                                           << getOpenMPClauseName(OMPC_linear);
19126       reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19127       continue;
19128     }
19129 
19130     if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
19131       continue;
19132     Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19133 
19134     // Build private copy of original var.
19135     VarDecl *Private =
19136         buildVarDecl(SemaRef, ELoc, Type, D->getName(),
19137                      D->hasAttrs() ? &D->getAttrs() : nullptr,
19138                      VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19139     DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc);
19140     // Build var to save initial value.
19141     VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start");
19142     Expr *InitExpr;
19143     DeclRefExpr *Ref = nullptr;
19144     if (!VD && !SemaRef.CurContext->isDependentContext()) {
19145       Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19146       if (!isOpenMPCapturedDecl(D)) {
19147         ExprCaptures.push_back(Ref->getDecl());
19148         if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19149           ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
19150           if (!RefRes.isUsable())
19151             continue;
19152           ExprResult PostUpdateRes =
19153               SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
19154                                  SimpleRefExpr, RefRes.get());
19155           if (!PostUpdateRes.isUsable())
19156             continue;
19157           ExprPostUpdates.push_back(
19158               SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
19159         }
19160       }
19161     }
19162     if (LinKind == OMPC_LINEAR_uval)
19163       InitExpr = VD ? VD->getInit() : SimpleRefExpr;
19164     else
19165       InitExpr = VD ? SimpleRefExpr : Ref;
19166     SemaRef.AddInitializerToDecl(
19167         Init, SemaRef.DefaultLvalueConversion(InitExpr).get(),
19168         /*DirectInit=*/false);
19169     DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc);
19170 
19171     DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
19172     Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19173                        ? RefExpr->IgnoreParens()
19174                        : Ref);
19175     Privates.push_back(PrivateRef);
19176     Inits.push_back(InitRef);
19177   }
19178 
19179   if (Vars.empty())
19180     return nullptr;
19181 
19182   Expr *StepExpr = Step;
19183   Expr *CalcStepExpr = nullptr;
19184   if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
19185       !Step->isInstantiationDependent() &&
19186       !Step->containsUnexpandedParameterPack()) {
19187     SourceLocation StepLoc = Step->getBeginLoc();
19188     ExprResult Val = PerformOpenMPImplicitIntegerConversion(StepLoc, Step);
19189     if (Val.isInvalid())
19190       return nullptr;
19191     StepExpr = Val.get();
19192 
19193     // Build var to save the step value.
19194     VarDecl *SaveVar =
19195         buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step");
19196     ExprResult SaveRef =
19197         buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc);
19198     ExprResult CalcStep = SemaRef.BuildBinOp(
19199         SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr);
19200     CalcStep =
19201         SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false);
19202 
19203     // Warn about zero linear step (it would be probably better specified as
19204     // making corresponding variables 'const').
19205     if (std::optional<llvm::APSInt> Result =
19206             StepExpr->getIntegerConstantExpr(getASTContext())) {
19207       if (!Result->isNegative() && !Result->isStrictlyPositive())
19208         Diag(StepLoc, diag::warn_omp_linear_step_zero)
19209             << Vars[0] << (Vars.size() > 1);
19210     } else if (CalcStep.isUsable()) {
19211       // Calculate the step beforehand instead of doing this on each iteration.
19212       // (This is not used if the number of iterations may be kfold-ed).
19213       CalcStepExpr = CalcStep.get();
19214     }
19215   }
19216 
19217   return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind,
19218                                  LinLoc, ColonLoc, StepModifierLoc, EndLoc,
19219                                  Vars, Privates, Inits, StepExpr, CalcStepExpr,
19220                                  buildPreInits(getASTContext(), ExprCaptures),
19221                                  buildPostUpdate(SemaRef, ExprPostUpdates));
19222 }
19223 
FinishOpenMPLinearClause(OMPLinearClause & Clause,DeclRefExpr * IV,Expr * NumIterations,Sema & SemaRef,Scope * S,DSAStackTy * Stack)19224 static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
19225                                      Expr *NumIterations, Sema &SemaRef,
19226                                      Scope *S, DSAStackTy *Stack) {
19227   // Walk the vars and build update/final expressions for the CodeGen.
19228   SmallVector<Expr *, 8> Updates;
19229   SmallVector<Expr *, 8> Finals;
19230   SmallVector<Expr *, 8> UsedExprs;
19231   Expr *Step = Clause.getStep();
19232   Expr *CalcStep = Clause.getCalcStep();
19233   // OpenMP [2.14.3.7, linear clause]
19234   // If linear-step is not specified it is assumed to be 1.
19235   if (!Step)
19236     Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
19237   else if (CalcStep)
19238     Step = cast<BinaryOperator>(CalcStep)->getLHS();
19239   bool HasErrors = false;
19240   auto CurInit = Clause.inits().begin();
19241   auto CurPrivate = Clause.privates().begin();
19242   OpenMPLinearClauseKind LinKind = Clause.getModifier();
19243   for (Expr *RefExpr : Clause.varlists()) {
19244     SourceLocation ELoc;
19245     SourceRange ERange;
19246     Expr *SimpleRefExpr = RefExpr;
19247     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19248     ValueDecl *D = Res.first;
19249     if (Res.second || !D) {
19250       Updates.push_back(nullptr);
19251       Finals.push_back(nullptr);
19252       HasErrors = true;
19253       continue;
19254     }
19255     auto &&Info = Stack->isLoopControlVariable(D);
19256     // OpenMP [2.15.11, distribute simd Construct]
19257     // A list item may not appear in a linear clause, unless it is the loop
19258     // iteration variable.
19259     if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
19260         isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
19261       SemaRef.Diag(ELoc,
19262                    diag::err_omp_linear_distribute_var_non_loop_iteration);
19263       Updates.push_back(nullptr);
19264       Finals.push_back(nullptr);
19265       HasErrors = true;
19266       continue;
19267     }
19268     Expr *InitExpr = *CurInit;
19269 
19270     // Build privatized reference to the current linear var.
19271     auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
19272     Expr *CapturedRef;
19273     if (LinKind == OMPC_LINEAR_uval)
19274       CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
19275     else
19276       CapturedRef =
19277           buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
19278                            DE->getType().getUnqualifiedType(), DE->getExprLoc(),
19279                            /*RefersToCapture=*/true);
19280 
19281     // Build update: Var = InitExpr + IV * Step
19282     ExprResult Update;
19283     if (!Info.first)
19284       Update = buildCounterUpdate(
19285           SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
19286           /*Subtract=*/false, /*IsNonRectangularLB=*/false);
19287     else
19288       Update = *CurPrivate;
19289     Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
19290                                          /*DiscardedValue*/ false);
19291 
19292     // Build final: Var = PrivCopy;
19293     ExprResult Final;
19294     if (!Info.first)
19295       Final = SemaRef.BuildBinOp(
19296           S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
19297           SemaRef.DefaultLvalueConversion(*CurPrivate).get());
19298     else
19299       Final = *CurPrivate;
19300     Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
19301                                         /*DiscardedValue*/ false);
19302 
19303     if (!Update.isUsable() || !Final.isUsable()) {
19304       Updates.push_back(nullptr);
19305       Finals.push_back(nullptr);
19306       UsedExprs.push_back(nullptr);
19307       HasErrors = true;
19308     } else {
19309       Updates.push_back(Update.get());
19310       Finals.push_back(Final.get());
19311       if (!Info.first)
19312         UsedExprs.push_back(SimpleRefExpr);
19313     }
19314     ++CurInit;
19315     ++CurPrivate;
19316   }
19317   if (Expr *S = Clause.getStep())
19318     UsedExprs.push_back(S);
19319   // Fill the remaining part with the nullptr.
19320   UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
19321   Clause.setUpdates(Updates);
19322   Clause.setFinals(Finals);
19323   Clause.setUsedExprs(UsedExprs);
19324   return HasErrors;
19325 }
19326 
ActOnOpenMPAlignedClause(ArrayRef<Expr * > VarList,Expr * Alignment,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ColonLoc,SourceLocation EndLoc)19327 OMPClause *SemaOpenMP::ActOnOpenMPAlignedClause(
19328     ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
19329     SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
19330   SmallVector<Expr *, 8> Vars;
19331   for (Expr *RefExpr : VarList) {
19332     assert(RefExpr && "NULL expr in OpenMP linear clause.");
19333     SourceLocation ELoc;
19334     SourceRange ERange;
19335     Expr *SimpleRefExpr = RefExpr;
19336     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19337     if (Res.second) {
19338       // It will be analyzed later.
19339       Vars.push_back(RefExpr);
19340     }
19341     ValueDecl *D = Res.first;
19342     if (!D)
19343       continue;
19344 
19345     QualType QType = D->getType();
19346     auto *VD = dyn_cast<VarDecl>(D);
19347 
19348     // OpenMP  [2.8.1, simd construct, Restrictions]
19349     // The type of list items appearing in the aligned clause must be
19350     // array, pointer, reference to array, or reference to pointer.
19351     QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19352     const Type *Ty = QType.getTypePtrOrNull();
19353     if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
19354       Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
19355           << QType << getLangOpts().CPlusPlus << ERange;
19356       bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19357                                VarDecl::DeclarationOnly;
19358       Diag(D->getLocation(),
19359            IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19360           << D;
19361       continue;
19362     }
19363 
19364     // OpenMP  [2.8.1, simd construct, Restrictions]
19365     // A list-item cannot appear in more than one aligned clause.
19366     if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
19367       Diag(ELoc, diag::err_omp_used_in_clause_twice)
19368           << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
19369       Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
19370           << getOpenMPClauseName(OMPC_aligned);
19371       continue;
19372     }
19373 
19374     DeclRefExpr *Ref = nullptr;
19375     if (!VD && isOpenMPCapturedDecl(D))
19376       Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19377     Vars.push_back(SemaRef
19378                        .DefaultFunctionArrayConversion(
19379                            (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
19380                        .get());
19381   }
19382 
19383   // OpenMP [2.8.1, simd construct, Description]
19384   // The parameter of the aligned clause, alignment, must be a constant
19385   // positive integer expression.
19386   // If no optional parameter is specified, implementation-defined default
19387   // alignments for SIMD instructions on the target platforms are assumed.
19388   if (Alignment != nullptr) {
19389     ExprResult AlignResult =
19390         VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
19391     if (AlignResult.isInvalid())
19392       return nullptr;
19393     Alignment = AlignResult.get();
19394   }
19395   if (Vars.empty())
19396     return nullptr;
19397 
19398   return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc,
19399                                   ColonLoc, EndLoc, Vars, Alignment);
19400 }
19401 
ActOnOpenMPCopyinClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)19402 OMPClause *SemaOpenMP::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
19403                                                SourceLocation StartLoc,
19404                                                SourceLocation LParenLoc,
19405                                                SourceLocation EndLoc) {
19406   SmallVector<Expr *, 8> Vars;
19407   SmallVector<Expr *, 8> SrcExprs;
19408   SmallVector<Expr *, 8> DstExprs;
19409   SmallVector<Expr *, 8> AssignmentOps;
19410   for (Expr *RefExpr : VarList) {
19411     assert(RefExpr && "NULL expr in OpenMP copyin clause.");
19412     if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19413       // It will be analyzed later.
19414       Vars.push_back(RefExpr);
19415       SrcExprs.push_back(nullptr);
19416       DstExprs.push_back(nullptr);
19417       AssignmentOps.push_back(nullptr);
19418       continue;
19419     }
19420 
19421     SourceLocation ELoc = RefExpr->getExprLoc();
19422     // OpenMP [2.1, C/C++]
19423     //  A list item is a variable name.
19424     // OpenMP  [2.14.4.1, Restrictions, p.1]
19425     //  A list item that appears in a copyin clause must be threadprivate.
19426     auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
19427     if (!DE || !isa<VarDecl>(DE->getDecl())) {
19428       Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
19429           << 0 << RefExpr->getSourceRange();
19430       continue;
19431     }
19432 
19433     Decl *D = DE->getDecl();
19434     auto *VD = cast<VarDecl>(D);
19435 
19436     QualType Type = VD->getType();
19437     if (Type->isDependentType() || Type->isInstantiationDependentType()) {
19438       // It will be analyzed later.
19439       Vars.push_back(DE);
19440       SrcExprs.push_back(nullptr);
19441       DstExprs.push_back(nullptr);
19442       AssignmentOps.push_back(nullptr);
19443       continue;
19444     }
19445 
19446     // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
19447     //  A list item that appears in a copyin clause must be threadprivate.
19448     if (!DSAStack->isThreadPrivate(VD)) {
19449       Diag(ELoc, diag::err_omp_required_access)
19450           << getOpenMPClauseName(OMPC_copyin)
19451           << getOpenMPDirectiveName(OMPD_threadprivate);
19452       continue;
19453     }
19454 
19455     // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
19456     //  A variable of class type (or array thereof) that appears in a
19457     //  copyin clause requires an accessible, unambiguous copy assignment
19458     //  operator for the class type.
19459     QualType ElemType =
19460         getASTContext().getBaseElementType(Type).getNonReferenceType();
19461     VarDecl *SrcVD =
19462         buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
19463                      ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
19464     DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
19465         SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
19466     VarDecl *DstVD =
19467         buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst",
19468                      VD->hasAttrs() ? &VD->getAttrs() : nullptr);
19469     DeclRefExpr *PseudoDstExpr =
19470         buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc());
19471     // For arrays generate assignment operation for single element and replace
19472     // it by the original array element in CodeGen.
19473     ExprResult AssignmentOp =
19474         SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
19475                            PseudoDstExpr, PseudoSrcExpr);
19476     if (AssignmentOp.isInvalid())
19477       continue;
19478     AssignmentOp =
19479         SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
19480                                     /*DiscardedValue*/ false);
19481     if (AssignmentOp.isInvalid())
19482       continue;
19483 
19484     DSAStack->addDSA(VD, DE, OMPC_copyin);
19485     Vars.push_back(DE);
19486     SrcExprs.push_back(PseudoSrcExpr);
19487     DstExprs.push_back(PseudoDstExpr);
19488     AssignmentOps.push_back(AssignmentOp.get());
19489   }
19490 
19491   if (Vars.empty())
19492     return nullptr;
19493 
19494   return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19495                                  Vars, SrcExprs, DstExprs, AssignmentOps);
19496 }
19497 
ActOnOpenMPCopyprivateClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)19498 OMPClause *SemaOpenMP::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
19499                                                     SourceLocation StartLoc,
19500                                                     SourceLocation LParenLoc,
19501                                                     SourceLocation EndLoc) {
19502   SmallVector<Expr *, 8> Vars;
19503   SmallVector<Expr *, 8> SrcExprs;
19504   SmallVector<Expr *, 8> DstExprs;
19505   SmallVector<Expr *, 8> AssignmentOps;
19506   for (Expr *RefExpr : VarList) {
19507     assert(RefExpr && "NULL expr in OpenMP linear clause.");
19508     SourceLocation ELoc;
19509     SourceRange ERange;
19510     Expr *SimpleRefExpr = RefExpr;
19511     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19512     if (Res.second) {
19513       // It will be analyzed later.
19514       Vars.push_back(RefExpr);
19515       SrcExprs.push_back(nullptr);
19516       DstExprs.push_back(nullptr);
19517       AssignmentOps.push_back(nullptr);
19518     }
19519     ValueDecl *D = Res.first;
19520     if (!D)
19521       continue;
19522 
19523     QualType Type = D->getType();
19524     auto *VD = dyn_cast<VarDecl>(D);
19525 
19526     // OpenMP [2.14.4.2, Restrictions, p.2]
19527     //  A list item that appears in a copyprivate clause may not appear in a
19528     //  private or firstprivate clause on the single construct.
19529     if (!VD || !DSAStack->isThreadPrivate(VD)) {
19530       DSAStackTy::DSAVarData DVar =
19531           DSAStack->getTopDSA(D, /*FromParent=*/false);
19532       if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
19533           DVar.RefExpr) {
19534         Diag(ELoc, diag::err_omp_wrong_dsa)
19535             << getOpenMPClauseName(DVar.CKind)
19536             << getOpenMPClauseName(OMPC_copyprivate);
19537         reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19538         continue;
19539       }
19540 
19541       // OpenMP [2.11.4.2, Restrictions, p.1]
19542       //  All list items that appear in a copyprivate clause must be either
19543       //  threadprivate or private in the enclosing context.
19544       if (DVar.CKind == OMPC_unknown) {
19545         DVar = DSAStack->getImplicitDSA(D, false);
19546         if (DVar.CKind == OMPC_shared) {
19547           Diag(ELoc, diag::err_omp_required_access)
19548               << getOpenMPClauseName(OMPC_copyprivate)
19549               << "threadprivate or private in the enclosing context";
19550           reportOriginalDsa(SemaRef, DSAStack, D, DVar);
19551           continue;
19552         }
19553       }
19554     }
19555 
19556     // Variably modified types are not supported.
19557     if (!Type->isAnyPointerType() && Type->isVariablyModifiedType()) {
19558       Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19559           << getOpenMPClauseName(OMPC_copyprivate) << Type
19560           << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
19561       bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19562                                VarDecl::DeclarationOnly;
19563       Diag(D->getLocation(),
19564            IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19565           << D;
19566       continue;
19567     }
19568 
19569     // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
19570     //  A variable of class type (or array thereof) that appears in a
19571     //  copyin clause requires an accessible, unambiguous copy assignment
19572     //  operator for the class type.
19573     Type = getASTContext()
19574                .getBaseElementType(Type.getNonReferenceType())
19575                .getUnqualifiedType();
19576     VarDecl *SrcVD =
19577         buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
19578                      D->hasAttrs() ? &D->getAttrs() : nullptr);
19579     DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc);
19580     VarDecl *DstVD =
19581         buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
19582                      D->hasAttrs() ? &D->getAttrs() : nullptr);
19583     DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
19584     ExprResult AssignmentOp = SemaRef.BuildBinOp(
19585         DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
19586     if (AssignmentOp.isInvalid())
19587       continue;
19588     AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
19589                                                /*DiscardedValue*/ false);
19590     if (AssignmentOp.isInvalid())
19591       continue;
19592 
19593     // No need to mark vars as copyprivate, they are already threadprivate or
19594     // implicitly private.
19595     assert(VD || isOpenMPCapturedDecl(D));
19596     Vars.push_back(
19597         VD ? RefExpr->IgnoreParens()
19598            : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false));
19599     SrcExprs.push_back(PseudoSrcExpr);
19600     DstExprs.push_back(PseudoDstExpr);
19601     AssignmentOps.push_back(AssignmentOp.get());
19602   }
19603 
19604   if (Vars.empty())
19605     return nullptr;
19606 
19607   return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc,
19608                                       EndLoc, Vars, SrcExprs, DstExprs,
19609                                       AssignmentOps);
19610 }
19611 
ActOnOpenMPFlushClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)19612 OMPClause *SemaOpenMP::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
19613                                               SourceLocation StartLoc,
19614                                               SourceLocation LParenLoc,
19615                                               SourceLocation EndLoc) {
19616   if (VarList.empty())
19617     return nullptr;
19618 
19619   return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19620                                 VarList);
19621 }
19622 
19623 /// Tries to find omp_depend_t. type.
findOMPDependT(Sema & S,SourceLocation Loc,DSAStackTy * Stack,bool Diagnose=true)19624 static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
19625                            bool Diagnose = true) {
19626   QualType OMPDependT = Stack->getOMPDependT();
19627   if (!OMPDependT.isNull())
19628     return true;
19629   IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
19630   ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
19631   if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
19632     if (Diagnose)
19633       S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
19634     return false;
19635   }
19636   Stack->setOMPDependT(PT.get());
19637   return true;
19638 }
19639 
ActOnOpenMPDepobjClause(Expr * Depobj,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)19640 OMPClause *SemaOpenMP::ActOnOpenMPDepobjClause(Expr *Depobj,
19641                                                SourceLocation StartLoc,
19642                                                SourceLocation LParenLoc,
19643                                                SourceLocation EndLoc) {
19644   if (!Depobj)
19645     return nullptr;
19646 
19647   bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack);
19648 
19649   // OpenMP 5.0, 2.17.10.1 depobj Construct
19650   // depobj is an lvalue expression of type omp_depend_t.
19651   if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
19652       !Depobj->isInstantiationDependent() &&
19653       !Depobj->containsUnexpandedParameterPack() &&
19654       (OMPDependTFound && !getASTContext().typesAreCompatible(
19655                               DSAStack->getOMPDependT(), Depobj->getType(),
19656                               /*CompareUnqualified=*/true))) {
19657     Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19658         << 0 << Depobj->getType() << Depobj->getSourceRange();
19659   }
19660 
19661   if (!Depobj->isLValue()) {
19662     Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19663         << 1 << Depobj->getSourceRange();
19664   }
19665 
19666   return OMPDepobjClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19667                                  Depobj);
19668 }
19669 
19670 namespace {
19671 // Utility struct that gathers the related info for doacross clause.
19672 struct DoacrossDataInfoTy {
19673   // The list of expressions.
19674   SmallVector<Expr *, 8> Vars;
19675   // The OperatorOffset for doacross loop.
19676   DSAStackTy::OperatorOffsetTy OpsOffs;
19677   // The depended loop count.
19678   llvm::APSInt TotalDepCount;
19679 };
19680 } // namespace
19681 static DoacrossDataInfoTy
ProcessOpenMPDoacrossClauseCommon(Sema & SemaRef,bool IsSource,ArrayRef<Expr * > VarList,DSAStackTy * Stack,SourceLocation EndLoc)19682 ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource,
19683                                   ArrayRef<Expr *> VarList, DSAStackTy *Stack,
19684                                   SourceLocation EndLoc) {
19685 
19686   SmallVector<Expr *, 8> Vars;
19687   DSAStackTy::OperatorOffsetTy OpsOffs;
19688   llvm::APSInt DepCounter(/*BitWidth=*/32);
19689   llvm::APSInt TotalDepCount(/*BitWidth=*/32);
19690 
19691   if (const Expr *OrderedCountExpr =
19692           Stack->getParentOrderedRegionParam().first) {
19693     TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
19694     TotalDepCount.setIsUnsigned(/*Val=*/true);
19695   }
19696 
19697   for (Expr *RefExpr : VarList) {
19698     assert(RefExpr && "NULL expr in OpenMP doacross clause.");
19699     if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19700       // It will be analyzed later.
19701       Vars.push_back(RefExpr);
19702       continue;
19703     }
19704 
19705     SourceLocation ELoc = RefExpr->getExprLoc();
19706     Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
19707     if (!IsSource) {
19708       if (Stack->getParentOrderedRegionParam().first &&
19709           DepCounter >= TotalDepCount) {
19710         SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
19711         continue;
19712       }
19713       ++DepCounter;
19714       // OpenMP  [2.13.9, Summary]
19715       // depend(dependence-type : vec), where dependence-type is:
19716       // 'sink' and where vec is the iteration vector, which has the form:
19717       //  x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
19718       // where n is the value specified by the ordered clause in the loop
19719       // directive, xi denotes the loop iteration variable of the i-th nested
19720       // loop associated with the loop directive, and di is a constant
19721       // non-negative integer.
19722       if (SemaRef.CurContext->isDependentContext()) {
19723         // It will be analyzed later.
19724         Vars.push_back(RefExpr);
19725         continue;
19726       }
19727       SimpleExpr = SimpleExpr->IgnoreImplicit();
19728       OverloadedOperatorKind OOK = OO_None;
19729       SourceLocation OOLoc;
19730       Expr *LHS = SimpleExpr;
19731       Expr *RHS = nullptr;
19732       if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
19733         OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
19734         OOLoc = BO->getOperatorLoc();
19735         LHS = BO->getLHS()->IgnoreParenImpCasts();
19736         RHS = BO->getRHS()->IgnoreParenImpCasts();
19737       } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
19738         OOK = OCE->getOperator();
19739         OOLoc = OCE->getOperatorLoc();
19740         LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
19741         RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
19742       } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
19743         OOK = MCE->getMethodDecl()
19744                   ->getNameInfo()
19745                   .getName()
19746                   .getCXXOverloadedOperator();
19747         OOLoc = MCE->getCallee()->getExprLoc();
19748         LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
19749         RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
19750       }
19751       SourceLocation ELoc;
19752       SourceRange ERange;
19753       auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
19754       if (Res.second) {
19755         // It will be analyzed later.
19756         Vars.push_back(RefExpr);
19757       }
19758       ValueDecl *D = Res.first;
19759       if (!D)
19760         continue;
19761 
19762       if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
19763         SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
19764         continue;
19765       }
19766       if (RHS) {
19767         ExprResult RHSRes =
19768             SemaRef.OpenMP().VerifyPositiveIntegerConstantInClause(
19769                 RHS, OMPC_depend, /*StrictlyPositive=*/false);
19770         if (RHSRes.isInvalid())
19771           continue;
19772       }
19773       if (!SemaRef.CurContext->isDependentContext() &&
19774           Stack->getParentOrderedRegionParam().first &&
19775           DepCounter != Stack->isParentLoopControlVariable(D).first) {
19776         const ValueDecl *VD =
19777             Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
19778         if (VD)
19779           SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19780               << 1 << VD;
19781         else
19782           SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19783               << 0;
19784         continue;
19785       }
19786       OpsOffs.emplace_back(RHS, OOK);
19787     }
19788     Vars.push_back(RefExpr->IgnoreParenImpCasts());
19789   }
19790   if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
19791       TotalDepCount > VarList.size() &&
19792       Stack->getParentOrderedRegionParam().first &&
19793       Stack->getParentLoopControlVariable(VarList.size() + 1)) {
19794     SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
19795         << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
19796   }
19797   return {Vars, OpsOffs, TotalDepCount};
19798 }
19799 
ActOnOpenMPDependClause(const OMPDependClause::DependDataTy & Data,Expr * DepModifier,ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)19800 OMPClause *SemaOpenMP::ActOnOpenMPDependClause(
19801     const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
19802     ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19803     SourceLocation EndLoc) {
19804   OpenMPDependClauseKind DepKind = Data.DepKind;
19805   SourceLocation DepLoc = Data.DepLoc;
19806   if (DSAStack->getCurrentDirective() == OMPD_ordered &&
19807       DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
19808     Diag(DepLoc, diag::err_omp_unexpected_clause_value)
19809         << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
19810     return nullptr;
19811   }
19812   if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
19813       DepKind == OMPC_DEPEND_mutexinoutset) {
19814     Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
19815     return nullptr;
19816   }
19817   if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
19818        DSAStack->getCurrentDirective() == OMPD_depobj) &&
19819       (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
19820        DepKind == OMPC_DEPEND_sink ||
19821        ((getLangOpts().OpenMP < 50 ||
19822          DSAStack->getCurrentDirective() == OMPD_depobj) &&
19823         DepKind == OMPC_DEPEND_depobj))) {
19824     SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
19825                                        OMPC_DEPEND_outallmemory,
19826                                        OMPC_DEPEND_inoutallmemory};
19827     if (getLangOpts().OpenMP < 50 ||
19828         DSAStack->getCurrentDirective() == OMPD_depobj)
19829       Except.push_back(OMPC_DEPEND_depobj);
19830     if (getLangOpts().OpenMP < 51)
19831       Except.push_back(OMPC_DEPEND_inoutset);
19832     std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
19833                                ? "depend modifier(iterator) or "
19834                                : "";
19835     Diag(DepLoc, diag::err_omp_unexpected_clause_value)
19836         << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
19837                                               /*Last=*/OMPC_DEPEND_unknown,
19838                                               Except)
19839         << getOpenMPClauseName(OMPC_depend);
19840     return nullptr;
19841   }
19842   if (DepModifier &&
19843       (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
19844     Diag(DepModifier->getExprLoc(),
19845          diag::err_omp_depend_sink_source_with_modifier);
19846     return nullptr;
19847   }
19848   if (DepModifier &&
19849       !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
19850     Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
19851 
19852   SmallVector<Expr *, 8> Vars;
19853   DSAStackTy::OperatorOffsetTy OpsOffs;
19854   llvm::APSInt TotalDepCount(/*BitWidth=*/32);
19855 
19856   if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
19857     DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
19858         SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
19859     Vars = VarOffset.Vars;
19860     OpsOffs = VarOffset.OpsOffs;
19861     TotalDepCount = VarOffset.TotalDepCount;
19862   } else {
19863     for (Expr *RefExpr : VarList) {
19864       assert(RefExpr && "NULL expr in OpenMP shared clause.");
19865       if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19866         // It will be analyzed later.
19867         Vars.push_back(RefExpr);
19868         continue;
19869       }
19870 
19871       SourceLocation ELoc = RefExpr->getExprLoc();
19872       Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
19873       if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
19874         bool OMPDependTFound = getLangOpts().OpenMP >= 50;
19875         if (OMPDependTFound)
19876           OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack,
19877                                            DepKind == OMPC_DEPEND_depobj);
19878         if (DepKind == OMPC_DEPEND_depobj) {
19879           // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
19880           // List items used in depend clauses with the depobj dependence type
19881           // must be expressions of the omp_depend_t type.
19882           if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
19883               !RefExpr->isInstantiationDependent() &&
19884               !RefExpr->containsUnexpandedParameterPack() &&
19885               (OMPDependTFound &&
19886                !getASTContext().hasSameUnqualifiedType(
19887                    DSAStack->getOMPDependT(), RefExpr->getType()))) {
19888             Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
19889                 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
19890             continue;
19891           }
19892           if (!RefExpr->isLValue()) {
19893             Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
19894                 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
19895             continue;
19896           }
19897         } else {
19898           // OpenMP 5.0 [2.17.11, Restrictions]
19899           // List items used in depend clauses cannot be zero-length array
19900           // sections.
19901           QualType ExprTy = RefExpr->getType().getNonReferenceType();
19902           const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
19903           if (OASE) {
19904             QualType BaseType =
19905                 ArraySectionExpr::getBaseOriginalType(OASE->getBase());
19906             if (BaseType.isNull())
19907               return nullptr;
19908             if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
19909               ExprTy = ATy->getElementType();
19910             else
19911               ExprTy = BaseType->getPointeeType();
19912             if (BaseType.isNull() || ExprTy.isNull())
19913               return nullptr;
19914             ExprTy = ExprTy.getNonReferenceType();
19915             const Expr *Length = OASE->getLength();
19916             Expr::EvalResult Result;
19917             if (Length && !Length->isValueDependent() &&
19918                 Length->EvaluateAsInt(Result, getASTContext()) &&
19919                 Result.Val.getInt().isZero()) {
19920               Diag(ELoc,
19921                    diag::err_omp_depend_zero_length_array_section_not_allowed)
19922                   << SimpleExpr->getSourceRange();
19923               continue;
19924             }
19925           }
19926 
19927           // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
19928           // List items used in depend clauses with the in, out, inout,
19929           // inoutset, or mutexinoutset dependence types cannot be
19930           // expressions of the omp_depend_t type.
19931           if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
19932               !RefExpr->isInstantiationDependent() &&
19933               !RefExpr->containsUnexpandedParameterPack() &&
19934               (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
19935                (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
19936                                        ExprTy.getTypePtr()))) {
19937             Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
19938                 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
19939                 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
19940                 << RefExpr->getSourceRange();
19941             continue;
19942           }
19943 
19944           auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
19945           if (ASE && !ASE->getBase()->isTypeDependent() &&
19946               !ASE->getBase()
19947                    ->getType()
19948                    .getNonReferenceType()
19949                    ->isPointerType() &&
19950               !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
19951             Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
19952                 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
19953                 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
19954                 << RefExpr->getSourceRange();
19955             continue;
19956           }
19957 
19958           ExprResult Res;
19959           {
19960             Sema::TentativeAnalysisScope Trap(SemaRef);
19961             Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
19962                                                RefExpr->IgnoreParenImpCasts());
19963           }
19964           if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
19965               !isa<OMPArrayShapingExpr>(SimpleExpr)) {
19966             Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
19967                 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
19968                 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
19969                 << RefExpr->getSourceRange();
19970             continue;
19971           }
19972         }
19973       }
19974       Vars.push_back(RefExpr->IgnoreParenImpCasts());
19975     }
19976   }
19977 
19978   if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
19979       DepKind != OMPC_DEPEND_outallmemory &&
19980       DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
19981     return nullptr;
19982 
19983   auto *C = OMPDependClause::Create(
19984       getASTContext(), StartLoc, LParenLoc, EndLoc,
19985       {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
19986       TotalDepCount.getZExtValue());
19987   if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
19988       DSAStack->isParentOrderedRegion())
19989     DSAStack->addDoacrossDependClause(C, OpsOffs);
19990   return C;
19991 }
19992 
ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier,Expr * Device,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ModifierLoc,SourceLocation EndLoc)19993 OMPClause *SemaOpenMP::ActOnOpenMPDeviceClause(
19994     OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc,
19995     SourceLocation LParenLoc, SourceLocation ModifierLoc,
19996     SourceLocation EndLoc) {
19997   assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
19998          "Unexpected device modifier in OpenMP < 50.");
19999 
20000   bool ErrorFound = false;
20001   if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
20002     std::string Values =
20003         getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
20004     Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
20005         << Values << getOpenMPClauseName(OMPC_device);
20006     ErrorFound = true;
20007   }
20008 
20009   Expr *ValExpr = Device;
20010   Stmt *HelperValStmt = nullptr;
20011 
20012   // OpenMP [2.9.1, Restrictions]
20013   // The device expression must evaluate to a non-negative integer value.
20014   ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device,
20015                                           /*StrictlyPositive=*/false) ||
20016                ErrorFound;
20017   if (ErrorFound)
20018     return nullptr;
20019 
20020   // OpenMP 5.0 [2.12.5, Restrictions]
20021   // In case of ancestor device-modifier, a requires directive with
20022   // the reverse_offload clause must be specified.
20023   if (Modifier == OMPC_DEVICE_ancestor) {
20024     if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
20025       SemaRef.targetDiag(
20026           StartLoc,
20027           diag::err_omp_device_ancestor_without_requires_reverse_offload);
20028       ErrorFound = true;
20029     }
20030   }
20031 
20032   OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
20033   OpenMPDirectiveKind CaptureRegion =
20034       getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP);
20035   if (CaptureRegion != OMPD_unknown &&
20036       !SemaRef.CurContext->isDependentContext()) {
20037     ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
20038     llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20039     ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
20040     HelperValStmt = buildPreInits(getASTContext(), Captures);
20041   }
20042 
20043   return new (getASTContext())
20044       OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
20045                       LParenLoc, ModifierLoc, EndLoc);
20046 }
20047 
checkTypeMappable(SourceLocation SL,SourceRange SR,Sema & SemaRef,DSAStackTy * Stack,QualType QTy,bool FullCheck=true)20048 static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
20049                               DSAStackTy *Stack, QualType QTy,
20050                               bool FullCheck = true) {
20051   if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
20052     return false;
20053   if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
20054       !QTy.isTriviallyCopyableType(SemaRef.Context))
20055     SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
20056   return true;
20057 }
20058 
20059 /// Return true if it can be proven that the provided array expression
20060 /// (array section or array subscript) does NOT specify the whole size of the
20061 /// array whose base type is \a BaseQTy.
checkArrayExpressionDoesNotReferToWholeSize(Sema & SemaRef,const Expr * E,QualType BaseQTy)20062 static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
20063                                                         const Expr *E,
20064                                                         QualType BaseQTy) {
20065   const auto *OASE = dyn_cast<ArraySectionExpr>(E);
20066 
20067   // If this is an array subscript, it refers to the whole size if the size of
20068   // the dimension is constant and equals 1. Also, an array section assumes the
20069   // format of an array subscript if no colon is used.
20070   if (isa<ArraySubscriptExpr>(E) ||
20071       (OASE && OASE->getColonLocFirst().isInvalid())) {
20072     if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20073       return ATy->getSExtSize() != 1;
20074     // Size can't be evaluated statically.
20075     return false;
20076   }
20077 
20078   assert(OASE && "Expecting array section if not an array subscript.");
20079   const Expr *LowerBound = OASE->getLowerBound();
20080   const Expr *Length = OASE->getLength();
20081 
20082   // If there is a lower bound that does not evaluates to zero, we are not
20083   // covering the whole dimension.
20084   if (LowerBound) {
20085     Expr::EvalResult Result;
20086     if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
20087       return false; // Can't get the integer value as a constant.
20088 
20089     llvm::APSInt ConstLowerBound = Result.Val.getInt();
20090     if (ConstLowerBound.getSExtValue())
20091       return true;
20092   }
20093 
20094   // If we don't have a length we covering the whole dimension.
20095   if (!Length)
20096     return false;
20097 
20098   // If the base is a pointer, we don't have a way to get the size of the
20099   // pointee.
20100   if (BaseQTy->isPointerType())
20101     return false;
20102 
20103   // We can only check if the length is the same as the size of the dimension
20104   // if we have a constant array.
20105   const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
20106   if (!CATy)
20107     return false;
20108 
20109   Expr::EvalResult Result;
20110   if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20111     return false; // Can't get the integer value as a constant.
20112 
20113   llvm::APSInt ConstLength = Result.Val.getInt();
20114   return CATy->getSExtSize() != ConstLength.getSExtValue();
20115 }
20116 
20117 // Return true if it can be proven that the provided array expression (array
20118 // section or array subscript) does NOT specify a single element of the array
20119 // whose base type is \a BaseQTy.
checkArrayExpressionDoesNotReferToUnitySize(Sema & SemaRef,const Expr * E,QualType BaseQTy)20120 static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
20121                                                         const Expr *E,
20122                                                         QualType BaseQTy) {
20123   const auto *OASE = dyn_cast<ArraySectionExpr>(E);
20124 
20125   // An array subscript always refer to a single element. Also, an array section
20126   // assumes the format of an array subscript if no colon is used.
20127   if (isa<ArraySubscriptExpr>(E) ||
20128       (OASE && OASE->getColonLocFirst().isInvalid()))
20129     return false;
20130 
20131   assert(OASE && "Expecting array section if not an array subscript.");
20132   const Expr *Length = OASE->getLength();
20133 
20134   // If we don't have a length we have to check if the array has unitary size
20135   // for this dimension. Also, we should always expect a length if the base type
20136   // is pointer.
20137   if (!Length) {
20138     if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20139       return ATy->getSExtSize() != 1;
20140     // We cannot assume anything.
20141     return false;
20142   }
20143 
20144   // Check if the length evaluates to 1.
20145   Expr::EvalResult Result;
20146   if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20147     return false; // Can't get the integer value as a constant.
20148 
20149   llvm::APSInt ConstLength = Result.Val.getInt();
20150   return ConstLength.getSExtValue() != 1;
20151 }
20152 
20153 // The base of elements of list in a map clause have to be either:
20154 //  - a reference to variable or field.
20155 //  - a member expression.
20156 //  - an array expression.
20157 //
20158 // E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
20159 // reference to 'r'.
20160 //
20161 // If we have:
20162 //
20163 // struct SS {
20164 //   Bla S;
20165 //   foo() {
20166 //     #pragma omp target map (S.Arr[:12]);
20167 //   }
20168 // }
20169 //
20170 // We want to retrieve the member expression 'this->S';
20171 
20172 // OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
20173 //  If a list item is an array section, it must specify contiguous storage.
20174 //
20175 // For this restriction it is sufficient that we make sure only references
20176 // to variables or fields and array expressions, and that no array sections
20177 // exist except in the rightmost expression (unless they cover the whole
20178 // dimension of the array). E.g. these would be invalid:
20179 //
20180 //   r.ArrS[3:5].Arr[6:7]
20181 //
20182 //   r.ArrS[3:5].x
20183 //
20184 // but these would be valid:
20185 //   r.ArrS[3].Arr[6:7]
20186 //
20187 //   r.ArrS[3].x
20188 namespace {
20189 class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
20190   Sema &SemaRef;
20191   OpenMPClauseKind CKind = OMPC_unknown;
20192   OpenMPDirectiveKind DKind = OMPD_unknown;
20193   OMPClauseMappableExprCommon::MappableExprComponentList &Components;
20194   bool IsNonContiguous = false;
20195   bool NoDiagnose = false;
20196   const Expr *RelevantExpr = nullptr;
20197   bool AllowUnitySizeArraySection = true;
20198   bool AllowWholeSizeArraySection = true;
20199   bool AllowAnotherPtr = true;
20200   SourceLocation ELoc;
20201   SourceRange ERange;
20202 
emitErrorMsg()20203   void emitErrorMsg() {
20204     // If nothing else worked, this is not a valid map clause expression.
20205     if (SemaRef.getLangOpts().OpenMP < 50) {
20206       SemaRef.Diag(ELoc,
20207                    diag::err_omp_expected_named_var_member_or_array_expression)
20208           << ERange;
20209     } else {
20210       SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20211           << getOpenMPClauseName(CKind) << ERange;
20212     }
20213   }
20214 
20215 public:
VisitDeclRefExpr(DeclRefExpr * DRE)20216   bool VisitDeclRefExpr(DeclRefExpr *DRE) {
20217     if (!isa<VarDecl>(DRE->getDecl())) {
20218       emitErrorMsg();
20219       return false;
20220     }
20221     assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20222     RelevantExpr = DRE;
20223     // Record the component.
20224     Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
20225     return true;
20226   }
20227 
VisitMemberExpr(MemberExpr * ME)20228   bool VisitMemberExpr(MemberExpr *ME) {
20229     Expr *E = ME;
20230     Expr *BaseE = ME->getBase()->IgnoreParenCasts();
20231 
20232     if (isa<CXXThisExpr>(BaseE)) {
20233       assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20234       // We found a base expression: this->Val.
20235       RelevantExpr = ME;
20236     } else {
20237       E = BaseE;
20238     }
20239 
20240     if (!isa<FieldDecl>(ME->getMemberDecl())) {
20241       if (!NoDiagnose) {
20242         SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
20243             << ME->getSourceRange();
20244         return false;
20245       }
20246       if (RelevantExpr)
20247         return false;
20248       return Visit(E);
20249     }
20250 
20251     auto *FD = cast<FieldDecl>(ME->getMemberDecl());
20252 
20253     // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
20254     //  A bit-field cannot appear in a map clause.
20255     //
20256     if (FD->isBitField()) {
20257       if (!NoDiagnose) {
20258         SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
20259             << ME->getSourceRange() << getOpenMPClauseName(CKind);
20260         return false;
20261       }
20262       if (RelevantExpr)
20263         return false;
20264       return Visit(E);
20265     }
20266 
20267     // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20268     //  If the type of a list item is a reference to a type T then the type
20269     //  will be considered to be T for all purposes of this clause.
20270     QualType CurType = BaseE->getType().getNonReferenceType();
20271 
20272     // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
20273     //  A list item cannot be a variable that is a member of a structure with
20274     //  a union type.
20275     //
20276     if (CurType->isUnionType()) {
20277       if (!NoDiagnose) {
20278         SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
20279             << ME->getSourceRange();
20280         return false;
20281       }
20282       return RelevantExpr || Visit(E);
20283     }
20284 
20285     // If we got a member expression, we should not expect any array section
20286     // before that:
20287     //
20288     // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
20289     //  If a list item is an element of a structure, only the rightmost symbol
20290     //  of the variable reference can be an array section.
20291     //
20292     AllowUnitySizeArraySection = false;
20293     AllowWholeSizeArraySection = false;
20294 
20295     // Record the component.
20296     Components.emplace_back(ME, FD, IsNonContiguous);
20297     return RelevantExpr || Visit(E);
20298   }
20299 
VisitArraySubscriptExpr(ArraySubscriptExpr * AE)20300   bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
20301     Expr *E = AE->getBase()->IgnoreParenImpCasts();
20302 
20303     if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
20304       if (!NoDiagnose) {
20305         SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20306             << 0 << AE->getSourceRange();
20307         return false;
20308       }
20309       return RelevantExpr || Visit(E);
20310     }
20311 
20312     // If we got an array subscript that express the whole dimension we
20313     // can have any array expressions before. If it only expressing part of
20314     // the dimension, we can only have unitary-size array expressions.
20315     if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef, AE, E->getType()))
20316       AllowWholeSizeArraySection = false;
20317 
20318     if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
20319       Expr::EvalResult Result;
20320       if (!AE->getIdx()->isValueDependent() &&
20321           AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
20322           !Result.Val.getInt().isZero()) {
20323         SemaRef.Diag(AE->getIdx()->getExprLoc(),
20324                      diag::err_omp_invalid_map_this_expr);
20325         SemaRef.Diag(AE->getIdx()->getExprLoc(),
20326                      diag::note_omp_invalid_subscript_on_this_ptr_map);
20327       }
20328       assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20329       RelevantExpr = TE;
20330     }
20331 
20332     // Record the component - we don't have any declaration associated.
20333     Components.emplace_back(AE, nullptr, IsNonContiguous);
20334 
20335     return RelevantExpr || Visit(E);
20336   }
20337 
VisitArraySectionExpr(ArraySectionExpr * OASE)20338   bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
20339     // After OMP 5.0  Array section in reduction clause will be implicitly
20340     // mapped
20341     assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
20342            "Array sections cannot be implicitly mapped.");
20343     Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20344     QualType CurType =
20345         ArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
20346 
20347     // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20348     //  If the type of a list item is a reference to a type T then the type
20349     //  will be considered to be T for all purposes of this clause.
20350     if (CurType->isReferenceType())
20351       CurType = CurType->getPointeeType();
20352 
20353     bool IsPointer = CurType->isAnyPointerType();
20354 
20355     if (!IsPointer && !CurType->isArrayType()) {
20356       SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20357           << 0 << OASE->getSourceRange();
20358       return false;
20359     }
20360 
20361     bool NotWhole =
20362         checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
20363     bool NotUnity =
20364         checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
20365 
20366     if (AllowWholeSizeArraySection) {
20367       // Any array section is currently allowed. Allowing a whole size array
20368       // section implies allowing a unity array section as well.
20369       //
20370       // If this array section refers to the whole dimension we can still
20371       // accept other array sections before this one, except if the base is a
20372       // pointer. Otherwise, only unitary sections are accepted.
20373       if (NotWhole || IsPointer)
20374         AllowWholeSizeArraySection = false;
20375     } else if (DKind == OMPD_target_update &&
20376                SemaRef.getLangOpts().OpenMP >= 50) {
20377       if (IsPointer && !AllowAnotherPtr)
20378         SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
20379             << /*array of unknown bound */ 1;
20380       else
20381         IsNonContiguous = true;
20382     } else if (AllowUnitySizeArraySection && NotUnity) {
20383       // A unity or whole array section is not allowed and that is not
20384       // compatible with the properties of the current array section.
20385       if (NoDiagnose)
20386         return false;
20387       SemaRef.Diag(ELoc,
20388                    diag::err_array_section_does_not_specify_contiguous_storage)
20389           << OASE->getSourceRange();
20390       return false;
20391     }
20392 
20393     if (IsPointer)
20394       AllowAnotherPtr = false;
20395 
20396     if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
20397       Expr::EvalResult ResultR;
20398       Expr::EvalResult ResultL;
20399       if (!OASE->getLength()->isValueDependent() &&
20400           OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
20401           !ResultR.Val.getInt().isOne()) {
20402         SemaRef.Diag(OASE->getLength()->getExprLoc(),
20403                      diag::err_omp_invalid_map_this_expr);
20404         SemaRef.Diag(OASE->getLength()->getExprLoc(),
20405                      diag::note_omp_invalid_length_on_this_ptr_mapping);
20406       }
20407       if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
20408           OASE->getLowerBound()->EvaluateAsInt(ResultL,
20409                                                SemaRef.getASTContext()) &&
20410           !ResultL.Val.getInt().isZero()) {
20411         SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
20412                      diag::err_omp_invalid_map_this_expr);
20413         SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
20414                      diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
20415       }
20416       assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20417       RelevantExpr = TE;
20418     }
20419 
20420     // Record the component - we don't have any declaration associated.
20421     Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
20422     return RelevantExpr || Visit(E);
20423   }
VisitOMPArrayShapingExpr(OMPArrayShapingExpr * E)20424   bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
20425     Expr *Base = E->getBase();
20426 
20427     // Record the component - we don't have any declaration associated.
20428     Components.emplace_back(E, nullptr, IsNonContiguous);
20429 
20430     return Visit(Base->IgnoreParenImpCasts());
20431   }
20432 
VisitUnaryOperator(UnaryOperator * UO)20433   bool VisitUnaryOperator(UnaryOperator *UO) {
20434     if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
20435         UO->getOpcode() != UO_Deref) {
20436       emitErrorMsg();
20437       return false;
20438     }
20439     if (!RelevantExpr) {
20440       // Record the component if haven't found base decl.
20441       Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
20442     }
20443     return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
20444   }
VisitBinaryOperator(BinaryOperator * BO)20445   bool VisitBinaryOperator(BinaryOperator *BO) {
20446     if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
20447       emitErrorMsg();
20448       return false;
20449     }
20450 
20451     // Pointer arithmetic is the only thing we expect to happen here so after we
20452     // make sure the binary operator is a pointer type, the only thing we need
20453     // to do is to visit the subtree that has the same type as root (so that we
20454     // know the other subtree is just an offset)
20455     Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
20456     Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
20457     Components.emplace_back(BO, nullptr, false);
20458     assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
20459             RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
20460            "Either LHS or RHS have base decl inside");
20461     if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
20462       return RelevantExpr || Visit(LE);
20463     return RelevantExpr || Visit(RE);
20464   }
VisitCXXThisExpr(CXXThisExpr * CTE)20465   bool VisitCXXThisExpr(CXXThisExpr *CTE) {
20466     assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20467     RelevantExpr = CTE;
20468     Components.emplace_back(CTE, nullptr, IsNonContiguous);
20469     return true;
20470   }
VisitCXXOperatorCallExpr(CXXOperatorCallExpr * COCE)20471   bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
20472     assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20473     Components.emplace_back(COCE, nullptr, IsNonContiguous);
20474     return true;
20475   }
VisitOpaqueValueExpr(OpaqueValueExpr * E)20476   bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
20477     Expr *Source = E->getSourceExpr();
20478     if (!Source) {
20479       emitErrorMsg();
20480       return false;
20481     }
20482     return Visit(Source);
20483   }
VisitStmt(Stmt *)20484   bool VisitStmt(Stmt *) {
20485     emitErrorMsg();
20486     return false;
20487   }
getFoundBase() const20488   const Expr *getFoundBase() const { return RelevantExpr; }
MapBaseChecker(Sema & SemaRef,OpenMPClauseKind CKind,OpenMPDirectiveKind DKind,OMPClauseMappableExprCommon::MappableExprComponentList & Components,bool NoDiagnose,SourceLocation & ELoc,SourceRange & ERange)20489   explicit MapBaseChecker(
20490       Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
20491       OMPClauseMappableExprCommon::MappableExprComponentList &Components,
20492       bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
20493       : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
20494         NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
20495 };
20496 } // namespace
20497 
20498 /// Return the expression of the base of the mappable expression or null if it
20499 /// cannot be determined and do all the necessary checks to see if the
20500 /// expression is valid as a standalone mappable expression. In the process,
20501 /// record all the components of the expression.
checkMapClauseExpressionBase(Sema & SemaRef,Expr * E,OMPClauseMappableExprCommon::MappableExprComponentList & CurComponents,OpenMPClauseKind CKind,OpenMPDirectiveKind DKind,bool NoDiagnose)20502 static const Expr *checkMapClauseExpressionBase(
20503     Sema &SemaRef, Expr *E,
20504     OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
20505     OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
20506   SourceLocation ELoc = E->getExprLoc();
20507   SourceRange ERange = E->getSourceRange();
20508   MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
20509                          ERange);
20510   if (Checker.Visit(E->IgnoreParens())) {
20511     // Check if the highest dimension array section has length specified
20512     if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
20513         (CKind == OMPC_to || CKind == OMPC_from)) {
20514       auto CI = CurComponents.rbegin();
20515       auto CE = CurComponents.rend();
20516       for (; CI != CE; ++CI) {
20517         const auto *OASE =
20518             dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
20519         if (!OASE)
20520           continue;
20521         if (OASE && OASE->getLength())
20522           break;
20523         SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
20524             << ERange;
20525       }
20526     }
20527     return Checker.getFoundBase();
20528   }
20529   return nullptr;
20530 }
20531 
20532 // Return true if expression E associated with value VD has conflicts with other
20533 // map information.
checkMapConflicts(Sema & SemaRef,DSAStackTy * DSAS,const ValueDecl * VD,const Expr * E,bool CurrentRegionOnly,OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents,OpenMPClauseKind CKind)20534 static bool checkMapConflicts(
20535     Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
20536     bool CurrentRegionOnly,
20537     OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents,
20538     OpenMPClauseKind CKind) {
20539   assert(VD && E);
20540   SourceLocation ELoc = E->getExprLoc();
20541   SourceRange ERange = E->getSourceRange();
20542 
20543   // In order to easily check the conflicts we need to match each component of
20544   // the expression under test with the components of the expressions that are
20545   // already in the stack.
20546 
20547   assert(!CurComponents.empty() && "Map clause expression with no components!");
20548   assert(CurComponents.back().getAssociatedDeclaration() == VD &&
20549          "Map clause expression with unexpected base!");
20550 
20551   // Variables to help detecting enclosing problems in data environment nests.
20552   bool IsEnclosedByDataEnvironmentExpr = false;
20553   const Expr *EnclosingExpr = nullptr;
20554 
20555   bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
20556       VD, CurrentRegionOnly,
20557       [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
20558        ERange, CKind, &EnclosingExpr,
20559        CurComponents](OMPClauseMappableExprCommon::MappableExprComponentListRef
20560                           StackComponents,
20561                       OpenMPClauseKind Kind) {
20562         if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
20563           return false;
20564         assert(!StackComponents.empty() &&
20565                "Map clause expression with no components!");
20566         assert(StackComponents.back().getAssociatedDeclaration() == VD &&
20567                "Map clause expression with unexpected base!");
20568         (void)VD;
20569 
20570         // The whole expression in the stack.
20571         const Expr *RE = StackComponents.front().getAssociatedExpression();
20572 
20573         // Expressions must start from the same base. Here we detect at which
20574         // point both expressions diverge from each other and see if we can
20575         // detect if the memory referred to both expressions is contiguous and
20576         // do not overlap.
20577         auto CI = CurComponents.rbegin();
20578         auto CE = CurComponents.rend();
20579         auto SI = StackComponents.rbegin();
20580         auto SE = StackComponents.rend();
20581         for (; CI != CE && SI != SE; ++CI, ++SI) {
20582 
20583           // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
20584           //  At most one list item can be an array item derived from a given
20585           //  variable in map clauses of the same construct.
20586           if (CurrentRegionOnly &&
20587               (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
20588                isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
20589                isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
20590               (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
20591                isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
20592                isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
20593             SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
20594                          diag::err_omp_multiple_array_items_in_map_clause)
20595                 << CI->getAssociatedExpression()->getSourceRange();
20596             SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
20597                          diag::note_used_here)
20598                 << SI->getAssociatedExpression()->getSourceRange();
20599             return true;
20600           }
20601 
20602           // Do both expressions have the same kind?
20603           if (CI->getAssociatedExpression()->getStmtClass() !=
20604               SI->getAssociatedExpression()->getStmtClass())
20605             break;
20606 
20607           // Are we dealing with different variables/fields?
20608           if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
20609             break;
20610         }
20611         // Check if the extra components of the expressions in the enclosing
20612         // data environment are redundant for the current base declaration.
20613         // If they are, the maps completely overlap, which is legal.
20614         for (; SI != SE; ++SI) {
20615           QualType Type;
20616           if (const auto *ASE =
20617                   dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
20618             Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
20619           } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
20620                          SI->getAssociatedExpression())) {
20621             const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20622             Type = ArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
20623           } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
20624                          SI->getAssociatedExpression())) {
20625             Type = OASE->getBase()->getType()->getPointeeType();
20626           }
20627           if (Type.isNull() || Type->isAnyPointerType() ||
20628               checkArrayExpressionDoesNotReferToWholeSize(
20629                   SemaRef, SI->getAssociatedExpression(), Type))
20630             break;
20631         }
20632 
20633         // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
20634         //  List items of map clauses in the same construct must not share
20635         //  original storage.
20636         //
20637         // If the expressions are exactly the same or one is a subset of the
20638         // other, it means they are sharing storage.
20639         if (CI == CE && SI == SE) {
20640           if (CurrentRegionOnly) {
20641             if (CKind == OMPC_map) {
20642               SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20643             } else {
20644               assert(CKind == OMPC_to || CKind == OMPC_from);
20645               SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20646                   << ERange;
20647             }
20648             SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20649                 << RE->getSourceRange();
20650             return true;
20651           }
20652           // If we find the same expression in the enclosing data environment,
20653           // that is legal.
20654           IsEnclosedByDataEnvironmentExpr = true;
20655           return false;
20656         }
20657 
20658         QualType DerivedType =
20659             std::prev(CI)->getAssociatedDeclaration()->getType();
20660         SourceLocation DerivedLoc =
20661             std::prev(CI)->getAssociatedExpression()->getExprLoc();
20662 
20663         // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20664         //  If the type of a list item is a reference to a type T then the type
20665         //  will be considered to be T for all purposes of this clause.
20666         DerivedType = DerivedType.getNonReferenceType();
20667 
20668         // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
20669         //  A variable for which the type is pointer and an array section
20670         //  derived from that variable must not appear as list items of map
20671         //  clauses of the same construct.
20672         //
20673         // Also, cover one of the cases in:
20674         // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
20675         //  If any part of the original storage of a list item has corresponding
20676         //  storage in the device data environment, all of the original storage
20677         //  must have corresponding storage in the device data environment.
20678         //
20679         if (DerivedType->isAnyPointerType()) {
20680           if (CI == CE || SI == SE) {
20681             SemaRef.Diag(
20682                 DerivedLoc,
20683                 diag::err_omp_pointer_mapped_along_with_derived_section)
20684                 << DerivedLoc;
20685             SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20686                 << RE->getSourceRange();
20687             return true;
20688           }
20689           if (CI->getAssociatedExpression()->getStmtClass() !=
20690                   SI->getAssociatedExpression()->getStmtClass() ||
20691               CI->getAssociatedDeclaration()->getCanonicalDecl() ==
20692                   SI->getAssociatedDeclaration()->getCanonicalDecl()) {
20693             assert(CI != CE && SI != SE);
20694             SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
20695                 << DerivedLoc;
20696             SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20697                 << RE->getSourceRange();
20698             return true;
20699           }
20700         }
20701 
20702         // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
20703         //  List items of map clauses in the same construct must not share
20704         //  original storage.
20705         //
20706         // An expression is a subset of the other.
20707         if (CurrentRegionOnly && (CI == CE || SI == SE)) {
20708           if (CKind == OMPC_map) {
20709             if (CI != CE || SI != SE) {
20710               // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
20711               // a pointer.
20712               auto Begin =
20713                   CI != CE ? CurComponents.begin() : StackComponents.begin();
20714               auto End = CI != CE ? CurComponents.end() : StackComponents.end();
20715               auto It = Begin;
20716               while (It != End && !It->getAssociatedDeclaration())
20717                 std::advance(It, 1);
20718               assert(It != End &&
20719                      "Expected at least one component with the declaration.");
20720               if (It != Begin && It->getAssociatedDeclaration()
20721                                      ->getType()
20722                                      .getCanonicalType()
20723                                      ->isAnyPointerType()) {
20724                 IsEnclosedByDataEnvironmentExpr = false;
20725                 EnclosingExpr = nullptr;
20726                 return false;
20727               }
20728             }
20729             SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20730           } else {
20731             assert(CKind == OMPC_to || CKind == OMPC_from);
20732             SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20733                 << ERange;
20734           }
20735           SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20736               << RE->getSourceRange();
20737           return true;
20738         }
20739 
20740         // The current expression uses the same base as other expression in the
20741         // data environment but does not contain it completely.
20742         if (!CurrentRegionOnly && SI != SE)
20743           EnclosingExpr = RE;
20744 
20745         // The current expression is a subset of the expression in the data
20746         // environment.
20747         IsEnclosedByDataEnvironmentExpr |=
20748             (!CurrentRegionOnly && CI != CE && SI == SE);
20749 
20750         return false;
20751       });
20752 
20753   if (CurrentRegionOnly)
20754     return FoundError;
20755 
20756   // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
20757   //  If any part of the original storage of a list item has corresponding
20758   //  storage in the device data environment, all of the original storage must
20759   //  have corresponding storage in the device data environment.
20760   // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
20761   //  If a list item is an element of a structure, and a different element of
20762   //  the structure has a corresponding list item in the device data environment
20763   //  prior to a task encountering the construct associated with the map clause,
20764   //  then the list item must also have a corresponding list item in the device
20765   //  data environment prior to the task encountering the construct.
20766   //
20767   if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
20768     SemaRef.Diag(ELoc,
20769                  diag::err_omp_original_storage_is_shared_and_does_not_contain)
20770         << ERange;
20771     SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
20772         << EnclosingExpr->getSourceRange();
20773     return true;
20774   }
20775 
20776   return FoundError;
20777 }
20778 
20779 // Look up the user-defined mapper given the mapper name and mapped type, and
20780 // build a reference to it.
buildUserDefinedMapperRef(Sema & SemaRef,Scope * S,CXXScopeSpec & MapperIdScopeSpec,const DeclarationNameInfo & MapperId,QualType Type,Expr * UnresolvedMapper)20781 static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
20782                                             CXXScopeSpec &MapperIdScopeSpec,
20783                                             const DeclarationNameInfo &MapperId,
20784                                             QualType Type,
20785                                             Expr *UnresolvedMapper) {
20786   if (MapperIdScopeSpec.isInvalid())
20787     return ExprError();
20788   // Get the actual type for the array type.
20789   if (Type->isArrayType()) {
20790     assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
20791     Type = Type->getAsArrayTypeUnsafe()->getElementType().getCanonicalType();
20792   }
20793   // Find all user-defined mappers with the given MapperId.
20794   SmallVector<UnresolvedSet<8>, 4> Lookups;
20795   LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
20796   Lookup.suppressDiagnostics();
20797   if (S) {
20798     while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
20799                                          /*ObjectType=*/QualType())) {
20800       NamedDecl *D = Lookup.getRepresentativeDecl();
20801       while (S && !S->isDeclScope(D))
20802         S = S->getParent();
20803       if (S)
20804         S = S->getParent();
20805       Lookups.emplace_back();
20806       Lookups.back().append(Lookup.begin(), Lookup.end());
20807       Lookup.clear();
20808     }
20809   } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
20810     // Extract the user-defined mappers with the given MapperId.
20811     Lookups.push_back(UnresolvedSet<8>());
20812     for (NamedDecl *D : ULE->decls()) {
20813       auto *DMD = cast<OMPDeclareMapperDecl>(D);
20814       assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
20815       Lookups.back().addDecl(DMD);
20816     }
20817   }
20818   // Defer the lookup for dependent types. The results will be passed through
20819   // UnresolvedMapper on instantiation.
20820   if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
20821       Type->isInstantiationDependentType() ||
20822       Type->containsUnexpandedParameterPack() ||
20823       filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
20824         return !D->isInvalidDecl() &&
20825                (D->getType()->isDependentType() ||
20826                 D->getType()->isInstantiationDependentType() ||
20827                 D->getType()->containsUnexpandedParameterPack());
20828       })) {
20829     UnresolvedSet<8> URS;
20830     for (const UnresolvedSet<8> &Set : Lookups) {
20831       if (Set.empty())
20832         continue;
20833       URS.append(Set.begin(), Set.end());
20834     }
20835     return UnresolvedLookupExpr::Create(
20836         SemaRef.Context, /*NamingClass=*/nullptr,
20837         MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
20838         /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false,
20839         /*KnownInstantiationDependent=*/false);
20840   }
20841   SourceLocation Loc = MapperId.getLoc();
20842   // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
20843   //  The type must be of struct, union or class type in C and C++
20844   if (!Type->isStructureOrClassType() && !Type->isUnionType() &&
20845       (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
20846     SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
20847     return ExprError();
20848   }
20849   // Perform argument dependent lookup.
20850   if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
20851     argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
20852   // Return the first user-defined mapper with the desired type.
20853   if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
20854           Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
20855             if (!D->isInvalidDecl() &&
20856                 SemaRef.Context.hasSameType(D->getType(), Type))
20857               return D;
20858             return nullptr;
20859           }))
20860     return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
20861   // Find the first user-defined mapper with a type derived from the desired
20862   // type.
20863   if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
20864           Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
20865             if (!D->isInvalidDecl() &&
20866                 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
20867                 !Type.isMoreQualifiedThan(D->getType()))
20868               return D;
20869             return nullptr;
20870           })) {
20871     CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
20872                        /*DetectVirtual=*/false);
20873     if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
20874       if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
20875               VD->getType().getUnqualifiedType()))) {
20876         if (SemaRef.CheckBaseClassAccess(
20877                 Loc, VD->getType(), Type, Paths.front(),
20878                 /*DiagID=*/0) != Sema::AR_inaccessible) {
20879           return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
20880         }
20881       }
20882     }
20883   }
20884   // Report error if a mapper is specified, but cannot be found.
20885   if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
20886     SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
20887         << Type << MapperId.getName();
20888     return ExprError();
20889   }
20890   return ExprEmpty();
20891 }
20892 
20893 namespace {
20894 // Utility struct that gathers all the related lists associated with a mappable
20895 // expression.
20896 struct MappableVarListInfo {
20897   // The list of expressions.
20898   ArrayRef<Expr *> VarList;
20899   // The list of processed expressions.
20900   SmallVector<Expr *, 16> ProcessedVarList;
20901   // The mappble components for each expression.
20902   OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents;
20903   // The base declaration of the variable.
20904   SmallVector<ValueDecl *, 16> VarBaseDeclarations;
20905   // The reference to the user-defined mapper associated with every expression.
20906   SmallVector<Expr *, 16> UDMapperList;
20907 
MappableVarListInfo__anon1dd12e447711::MappableVarListInfo20908   MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
20909     // We have a list of components and base declarations for each entry in the
20910     // variable list.
20911     VarComponents.reserve(VarList.size());
20912     VarBaseDeclarations.reserve(VarList.size());
20913   }
20914 };
20915 } // namespace
20916 
20917 // Check the validity of the provided variable list for the provided clause kind
20918 // \a CKind. In the check process the valid expressions, mappable expression
20919 // components, variables, and user-defined mappers are extracted and used to
20920 // fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
20921 // UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
20922 // 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=std::nullopt,bool IsMapTypeImplicit=false,bool NoDiagnose=false)20923 static void checkMappableExpressionList(
20924     Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
20925     MappableVarListInfo &MVLI, SourceLocation StartLoc,
20926     CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
20927     ArrayRef<Expr *> UnresolvedMappers,
20928     OpenMPMapClauseKind MapType = OMPC_MAP_unknown,
20929     ArrayRef<OpenMPMapModifierKind> Modifiers = std::nullopt,
20930     bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
20931   // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
20932   assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
20933          "Unexpected clause kind with mappable expressions!");
20934 
20935   // If the identifier of user-defined mapper is not specified, it is "default".
20936   // We do not change the actual name in this clause to distinguish whether a
20937   // mapper is specified explicitly, i.e., it is not explicitly specified when
20938   // MapperId.getName() is empty.
20939   if (!MapperId.getName() || MapperId.getName().isEmpty()) {
20940     auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
20941     MapperId.setName(DeclNames.getIdentifier(
20942         &SemaRef.getASTContext().Idents.get("default")));
20943     MapperId.setLoc(StartLoc);
20944   }
20945 
20946   // Iterators to find the current unresolved mapper expression.
20947   auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
20948   bool UpdateUMIt = false;
20949   Expr *UnresolvedMapper = nullptr;
20950 
20951   bool HasHoldModifier =
20952       llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
20953 
20954   // Keep track of the mappable components and base declarations in this clause.
20955   // Each entry in the list is going to have a list of components associated. We
20956   // record each set of the components so that we can build the clause later on.
20957   // In the end we should have the same amount of declarations and component
20958   // lists.
20959 
20960   for (Expr *RE : MVLI.VarList) {
20961     assert(RE && "Null expr in omp to/from/map clause");
20962     SourceLocation ELoc = RE->getExprLoc();
20963 
20964     // Find the current unresolved mapper expression.
20965     if (UpdateUMIt && UMIt != UMEnd) {
20966       UMIt++;
20967       assert(
20968           UMIt != UMEnd &&
20969           "Expect the size of UnresolvedMappers to match with that of VarList");
20970     }
20971     UpdateUMIt = true;
20972     if (UMIt != UMEnd)
20973       UnresolvedMapper = *UMIt;
20974 
20975     const Expr *VE = RE->IgnoreParenLValueCasts();
20976 
20977     if (VE->isValueDependent() || VE->isTypeDependent() ||
20978         VE->isInstantiationDependent() ||
20979         VE->containsUnexpandedParameterPack()) {
20980       // Try to find the associated user-defined mapper.
20981       ExprResult ER = buildUserDefinedMapperRef(
20982           SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
20983           VE->getType().getCanonicalType(), UnresolvedMapper);
20984       if (ER.isInvalid())
20985         continue;
20986       MVLI.UDMapperList.push_back(ER.get());
20987       // We can only analyze this information once the missing information is
20988       // resolved.
20989       MVLI.ProcessedVarList.push_back(RE);
20990       continue;
20991     }
20992 
20993     Expr *SimpleExpr = RE->IgnoreParenCasts();
20994 
20995     if (!RE->isLValue()) {
20996       if (SemaRef.getLangOpts().OpenMP < 50) {
20997         SemaRef.Diag(
20998             ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
20999             << RE->getSourceRange();
21000       } else {
21001         SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21002             << getOpenMPClauseName(CKind) << RE->getSourceRange();
21003       }
21004       continue;
21005     }
21006 
21007     OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
21008     ValueDecl *CurDeclaration = nullptr;
21009 
21010     // Obtain the array or member expression bases if required. Also, fill the
21011     // components array with all the components identified in the process.
21012     const Expr *BE =
21013         checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
21014                                      DSAS->getCurrentDirective(), NoDiagnose);
21015     if (!BE)
21016       continue;
21017 
21018     assert(!CurComponents.empty() &&
21019            "Invalid mappable expression information.");
21020 
21021     if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
21022       // Add store "this" pointer to class in DSAStackTy for future checking
21023       DSAS->addMappedClassesQualTypes(TE->getType());
21024       // Try to find the associated user-defined mapper.
21025       ExprResult ER = buildUserDefinedMapperRef(
21026           SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21027           VE->getType().getCanonicalType(), UnresolvedMapper);
21028       if (ER.isInvalid())
21029         continue;
21030       MVLI.UDMapperList.push_back(ER.get());
21031       // Skip restriction checking for variable or field declarations
21032       MVLI.ProcessedVarList.push_back(RE);
21033       MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21034       MVLI.VarComponents.back().append(CurComponents.begin(),
21035                                        CurComponents.end());
21036       MVLI.VarBaseDeclarations.push_back(nullptr);
21037       continue;
21038     }
21039 
21040     // For the following checks, we rely on the base declaration which is
21041     // expected to be associated with the last component. The declaration is
21042     // expected to be a variable or a field (if 'this' is being mapped).
21043     CurDeclaration = CurComponents.back().getAssociatedDeclaration();
21044     assert(CurDeclaration && "Null decl on map clause.");
21045     assert(
21046         CurDeclaration->isCanonicalDecl() &&
21047         "Expecting components to have associated only canonical declarations.");
21048 
21049     auto *VD = dyn_cast<VarDecl>(CurDeclaration);
21050     const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
21051 
21052     assert((VD || FD) && "Only variables or fields are expected here!");
21053     (void)FD;
21054 
21055     // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
21056     // threadprivate variables cannot appear in a map clause.
21057     // OpenMP 4.5 [2.10.5, target update Construct]
21058     // threadprivate variables cannot appear in a from clause.
21059     if (VD && DSAS->isThreadPrivate(VD)) {
21060       if (NoDiagnose)
21061         continue;
21062       DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21063       SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
21064           << getOpenMPClauseName(CKind);
21065       reportOriginalDsa(SemaRef, DSAS, VD, DVar);
21066       continue;
21067     }
21068 
21069     // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21070     //  A list item cannot appear in both a map clause and a data-sharing
21071     //  attribute clause on the same construct.
21072 
21073     // Check conflicts with other map clause expressions. We check the conflicts
21074     // with the current construct separately from the enclosing data
21075     // environment, because the restrictions are different. We only have to
21076     // check conflicts across regions for the map clauses.
21077     if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21078                           /*CurrentRegionOnly=*/true, CurComponents, CKind))
21079       break;
21080     if (CKind == OMPC_map &&
21081         (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
21082         checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21083                           /*CurrentRegionOnly=*/false, CurComponents, CKind))
21084       break;
21085 
21086     // OpenMP 4.5 [2.10.5, target update Construct]
21087     // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21088     //  If the type of a list item is a reference to a type T then the type will
21089     //  be considered to be T for all purposes of this clause.
21090     auto I = llvm::find_if(
21091         CurComponents,
21092         [](const OMPClauseMappableExprCommon::MappableComponent &MC) {
21093           return MC.getAssociatedDeclaration();
21094         });
21095     assert(I != CurComponents.end() && "Null decl on map clause.");
21096     (void)I;
21097     QualType Type;
21098     auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
21099     auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens());
21100     auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
21101     if (ASE) {
21102       Type = ASE->getType().getNonReferenceType();
21103     } else if (OASE) {
21104       QualType BaseType =
21105           ArraySectionExpr::getBaseOriginalType(OASE->getBase());
21106       if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21107         Type = ATy->getElementType();
21108       else
21109         Type = BaseType->getPointeeType();
21110       Type = Type.getNonReferenceType();
21111     } else if (OAShE) {
21112       Type = OAShE->getBase()->getType()->getPointeeType();
21113     } else {
21114       Type = VE->getType();
21115     }
21116 
21117     // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
21118     // A list item in a to or from clause must have a mappable type.
21119     // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21120     //  A list item must have a mappable type.
21121     if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
21122                            DSAS, Type, /*FullCheck=*/true))
21123       continue;
21124 
21125     if (CKind == OMPC_map) {
21126       // target enter data
21127       // OpenMP [2.10.2, Restrictions, p. 99]
21128       // A map-type must be specified in all map clauses and must be either
21129       // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
21130       // no map type is present.
21131       OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
21132       if (DKind == OMPD_target_enter_data &&
21133           !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
21134             SemaRef.getLangOpts().OpenMP >= 52)) {
21135         SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21136             << (IsMapTypeImplicit ? 1 : 0)
21137             << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21138             << getOpenMPDirectiveName(DKind);
21139         continue;
21140       }
21141 
21142       // target exit_data
21143       // OpenMP [2.10.3, Restrictions, p. 102]
21144       // A map-type must be specified in all map clauses and must be either
21145       // from, release, or delete. Starting with OpenMP 5.2 the default map
21146       // type is `from` if no map type is present.
21147       if (DKind == OMPD_target_exit_data &&
21148           !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
21149             MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
21150         SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21151             << (IsMapTypeImplicit ? 1 : 0)
21152             << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21153             << getOpenMPDirectiveName(DKind);
21154         continue;
21155       }
21156 
21157       // The 'ompx_hold' modifier is specifically intended to be used on a
21158       // 'target' or 'target data' directive to prevent data from being unmapped
21159       // during the associated statement.  It is not permitted on a 'target
21160       // enter data' or 'target exit data' directive, which have no associated
21161       // statement.
21162       if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
21163           HasHoldModifier) {
21164         SemaRef.Diag(StartLoc,
21165                      diag::err_omp_invalid_map_type_modifier_for_directive)
21166             << getOpenMPSimpleClauseTypeName(OMPC_map,
21167                                              OMPC_MAP_MODIFIER_ompx_hold)
21168             << getOpenMPDirectiveName(DKind);
21169         continue;
21170       }
21171 
21172       // target, target data
21173       // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
21174       // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
21175       // A map-type in a map clause must be to, from, tofrom or alloc
21176       if ((DKind == OMPD_target_data ||
21177            isOpenMPTargetExecutionDirective(DKind)) &&
21178           !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
21179             MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
21180         SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21181             << (IsMapTypeImplicit ? 1 : 0)
21182             << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21183             << getOpenMPDirectiveName(DKind);
21184         continue;
21185       }
21186 
21187       // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
21188       // A list item cannot appear in both a map clause and a data-sharing
21189       // attribute clause on the same construct
21190       //
21191       // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
21192       // A list item cannot appear in both a map clause and a data-sharing
21193       // attribute clause on the same construct unless the construct is a
21194       // combined construct.
21195       if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
21196                   isOpenMPTargetExecutionDirective(DKind)) ||
21197                  DKind == OMPD_target)) {
21198         DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21199         if (isOpenMPPrivate(DVar.CKind)) {
21200           SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
21201               << getOpenMPClauseName(DVar.CKind)
21202               << getOpenMPClauseName(OMPC_map)
21203               << getOpenMPDirectiveName(DSAS->getCurrentDirective());
21204           reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
21205           continue;
21206         }
21207       }
21208     }
21209 
21210     // Try to find the associated user-defined mapper.
21211     ExprResult ER = buildUserDefinedMapperRef(
21212         SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21213         Type.getCanonicalType(), UnresolvedMapper);
21214     if (ER.isInvalid())
21215       continue;
21216     MVLI.UDMapperList.push_back(ER.get());
21217 
21218     // Save the current expression.
21219     MVLI.ProcessedVarList.push_back(RE);
21220 
21221     // Store the components in the stack so that they can be used to check
21222     // against other clauses later on.
21223     DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
21224                                           /*WhereFoundClauseKind=*/OMPC_map);
21225 
21226     // Save the components and declaration to create the clause. For purposes of
21227     // the clause creation, any component list that has base 'this' uses
21228     // null as base declaration.
21229     MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21230     MVLI.VarComponents.back().append(CurComponents.begin(),
21231                                      CurComponents.end());
21232     MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
21233                                                            : CurDeclaration);
21234   }
21235 }
21236 
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)21237 OMPClause *SemaOpenMP::ActOnOpenMPMapClause(
21238     Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
21239     ArrayRef<SourceLocation> MapTypeModifiersLoc,
21240     CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
21241     OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
21242     SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
21243     const OMPVarListLocTy &Locs, bool NoDiagnose,
21244     ArrayRef<Expr *> UnresolvedMappers) {
21245   OpenMPMapModifierKind Modifiers[] = {
21246       OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
21247       OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
21248       OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown};
21249   SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers];
21250 
21251   if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
21252                               BuiltinType::OMPIterator))
21253     Diag(IteratorModifier->getExprLoc(),
21254          diag::err_omp_map_modifier_not_iterator);
21255 
21256   // Process map-type-modifiers, flag errors for duplicate modifiers.
21257   unsigned Count = 0;
21258   for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
21259     if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
21260         llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
21261       Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
21262       continue;
21263     }
21264     assert(Count < NumberOfOMPMapClauseModifiers &&
21265            "Modifiers exceed the allowed number of map type modifiers");
21266     Modifiers[Count] = MapTypeModifiers[I];
21267     ModifiersLoc[Count] = MapTypeModifiersLoc[I];
21268     ++Count;
21269   }
21270 
21271   MappableVarListInfo MVLI(VarList);
21272   checkMappableExpressionList(SemaRef, DSAStack, OMPC_map, MVLI, Locs.StartLoc,
21273                               MapperIdScopeSpec, MapperId, UnresolvedMappers,
21274                               MapType, Modifiers, IsMapTypeImplicit,
21275                               NoDiagnose);
21276 
21277   // We need to produce a map clause even if we don't have variables so that
21278   // other diagnostics related with non-existing map clauses are accurate.
21279   return OMPMapClause::Create(
21280       getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
21281       MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
21282       ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
21283       MapperId, MapType, IsMapTypeImplicit, MapLoc);
21284 }
21285 
ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,TypeResult ParsedType)21286 QualType SemaOpenMP::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
21287                                                      TypeResult ParsedType) {
21288   assert(ParsedType.isUsable());
21289 
21290   QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get());
21291   if (ReductionType.isNull())
21292     return QualType();
21293 
21294   // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
21295   // A type name in a declare reduction directive cannot be a function type, an
21296   // array type, a reference type, or a type qualified with const, volatile or
21297   // restrict.
21298   if (ReductionType.hasQualifiers()) {
21299     Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
21300     return QualType();
21301   }
21302 
21303   if (ReductionType->isFunctionType()) {
21304     Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
21305     return QualType();
21306   }
21307   if (ReductionType->isReferenceType()) {
21308     Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
21309     return QualType();
21310   }
21311   if (ReductionType->isArrayType()) {
21312     Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
21313     return QualType();
21314   }
21315   return ReductionType;
21316 }
21317 
21318 SemaOpenMP::DeclGroupPtrTy
ActOnOpenMPDeclareReductionDirectiveStart(Scope * S,DeclContext * DC,DeclarationName Name,ArrayRef<std::pair<QualType,SourceLocation>> ReductionTypes,AccessSpecifier AS,Decl * PrevDeclInScope)21319 SemaOpenMP::ActOnOpenMPDeclareReductionDirectiveStart(
21320     Scope *S, DeclContext *DC, DeclarationName Name,
21321     ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
21322     AccessSpecifier AS, Decl *PrevDeclInScope) {
21323   SmallVector<Decl *, 8> Decls;
21324   Decls.reserve(ReductionTypes.size());
21325 
21326   LookupResult Lookup(SemaRef, Name, SourceLocation(),
21327                       Sema::LookupOMPReductionName,
21328                       SemaRef.forRedeclarationInCurContext());
21329   // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
21330   // A reduction-identifier may not be re-declared in the current scope for the
21331   // same type or for a type that is compatible according to the base language
21332   // rules.
21333   llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21334   OMPDeclareReductionDecl *PrevDRD = nullptr;
21335   bool InCompoundScope = true;
21336   if (S != nullptr) {
21337     // Find previous declaration with the same name not referenced in other
21338     // declarations.
21339     FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
21340     InCompoundScope =
21341         (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
21342     SemaRef.LookupName(Lookup, S);
21343     SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
21344                                  /*AllowInlineNamespace=*/false);
21345     llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
21346     LookupResult::Filter Filter = Lookup.makeFilter();
21347     while (Filter.hasNext()) {
21348       auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
21349       if (InCompoundScope) {
21350         auto I = UsedAsPrevious.find(PrevDecl);
21351         if (I == UsedAsPrevious.end())
21352           UsedAsPrevious[PrevDecl] = false;
21353         if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
21354           UsedAsPrevious[D] = true;
21355       }
21356       PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21357           PrevDecl->getLocation();
21358     }
21359     Filter.done();
21360     if (InCompoundScope) {
21361       for (const auto &PrevData : UsedAsPrevious) {
21362         if (!PrevData.second) {
21363           PrevDRD = PrevData.first;
21364           break;
21365         }
21366       }
21367     }
21368   } else if (PrevDeclInScope != nullptr) {
21369     auto *PrevDRDInScope = PrevDRD =
21370         cast<OMPDeclareReductionDecl>(PrevDeclInScope);
21371     do {
21372       PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
21373           PrevDRDInScope->getLocation();
21374       PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
21375     } while (PrevDRDInScope != nullptr);
21376   }
21377   for (const auto &TyData : ReductionTypes) {
21378     const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
21379     bool Invalid = false;
21380     if (I != PreviousRedeclTypes.end()) {
21381       Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
21382           << TyData.first;
21383       Diag(I->second, diag::note_previous_definition);
21384       Invalid = true;
21385     }
21386     PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
21387     auto *DRD = OMPDeclareReductionDecl::Create(
21388         getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
21389     DC->addDecl(DRD);
21390     DRD->setAccess(AS);
21391     Decls.push_back(DRD);
21392     if (Invalid)
21393       DRD->setInvalidDecl();
21394     else
21395       PrevDRD = DRD;
21396   }
21397 
21398   return DeclGroupPtrTy::make(
21399       DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size()));
21400 }
21401 
ActOnOpenMPDeclareReductionCombinerStart(Scope * S,Decl * D)21402 void SemaOpenMP::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
21403   auto *DRD = cast<OMPDeclareReductionDecl>(D);
21404 
21405   // Enter new function scope.
21406   SemaRef.PushFunctionScope();
21407   SemaRef.setFunctionHasBranchProtectedScope();
21408   SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
21409 
21410   if (S != nullptr)
21411     SemaRef.PushDeclContext(S, DRD);
21412   else
21413     SemaRef.CurContext = DRD;
21414 
21415   SemaRef.PushExpressionEvaluationContext(
21416       Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
21417 
21418   QualType ReductionType = DRD->getType();
21419   // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
21420   // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
21421   // uses semantics of argument handles by value, but it should be passed by
21422   // reference. C lang does not support references, so pass all parameters as
21423   // pointers.
21424   // Create 'T omp_in;' variable.
21425   VarDecl *OmpInParm =
21426       buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in");
21427   // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
21428   // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
21429   // uses semantics of argument handles by value, but it should be passed by
21430   // reference. C lang does not support references, so pass all parameters as
21431   // pointers.
21432   // Create 'T omp_out;' variable.
21433   VarDecl *OmpOutParm =
21434       buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out");
21435   if (S != nullptr) {
21436     SemaRef.PushOnScopeChains(OmpInParm, S);
21437     SemaRef.PushOnScopeChains(OmpOutParm, S);
21438   } else {
21439     DRD->addDecl(OmpInParm);
21440     DRD->addDecl(OmpOutParm);
21441   }
21442   Expr *InE =
21443       ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation());
21444   Expr *OutE =
21445       ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation());
21446   DRD->setCombinerData(InE, OutE);
21447 }
21448 
ActOnOpenMPDeclareReductionCombinerEnd(Decl * D,Expr * Combiner)21449 void SemaOpenMP::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D,
21450                                                         Expr *Combiner) {
21451   auto *DRD = cast<OMPDeclareReductionDecl>(D);
21452   SemaRef.DiscardCleanupsInEvaluationContext();
21453   SemaRef.PopExpressionEvaluationContext();
21454 
21455   SemaRef.PopDeclContext();
21456   SemaRef.PopFunctionScopeInfo();
21457 
21458   if (Combiner != nullptr)
21459     DRD->setCombiner(Combiner);
21460   else
21461     DRD->setInvalidDecl();
21462 }
21463 
ActOnOpenMPDeclareReductionInitializerStart(Scope * S,Decl * D)21464 VarDecl *SemaOpenMP::ActOnOpenMPDeclareReductionInitializerStart(Scope *S,
21465                                                                  Decl *D) {
21466   auto *DRD = cast<OMPDeclareReductionDecl>(D);
21467 
21468   // Enter new function scope.
21469   SemaRef.PushFunctionScope();
21470   SemaRef.setFunctionHasBranchProtectedScope();
21471 
21472   if (S != nullptr)
21473     SemaRef.PushDeclContext(S, DRD);
21474   else
21475     SemaRef.CurContext = DRD;
21476 
21477   SemaRef.PushExpressionEvaluationContext(
21478       Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
21479 
21480   QualType ReductionType = DRD->getType();
21481   // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
21482   // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
21483   // uses semantics of argument handles by value, but it should be passed by
21484   // reference. C lang does not support references, so pass all parameters as
21485   // pointers.
21486   // Create 'T omp_priv;' variable.
21487   VarDecl *OmpPrivParm =
21488       buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv");
21489   // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
21490   // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
21491   // uses semantics of argument handles by value, but it should be passed by
21492   // reference. C lang does not support references, so pass all parameters as
21493   // pointers.
21494   // Create 'T omp_orig;' variable.
21495   VarDecl *OmpOrigParm =
21496       buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig");
21497   if (S != nullptr) {
21498     SemaRef.PushOnScopeChains(OmpPrivParm, S);
21499     SemaRef.PushOnScopeChains(OmpOrigParm, S);
21500   } else {
21501     DRD->addDecl(OmpPrivParm);
21502     DRD->addDecl(OmpOrigParm);
21503   }
21504   Expr *OrigE =
21505       ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation());
21506   Expr *PrivE =
21507       ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation());
21508   DRD->setInitializerData(OrigE, PrivE);
21509   return OmpPrivParm;
21510 }
21511 
ActOnOpenMPDeclareReductionInitializerEnd(Decl * D,Expr * Initializer,VarDecl * OmpPrivParm)21512 void SemaOpenMP::ActOnOpenMPDeclareReductionInitializerEnd(
21513     Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
21514   auto *DRD = cast<OMPDeclareReductionDecl>(D);
21515   SemaRef.DiscardCleanupsInEvaluationContext();
21516   SemaRef.PopExpressionEvaluationContext();
21517 
21518   SemaRef.PopDeclContext();
21519   SemaRef.PopFunctionScopeInfo();
21520 
21521   if (Initializer != nullptr) {
21522     DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
21523   } else if (OmpPrivParm->hasInit()) {
21524     DRD->setInitializer(OmpPrivParm->getInit(),
21525                         OmpPrivParm->isDirectInit()
21526                             ? OMPDeclareReductionInitKind::Direct
21527                             : OMPDeclareReductionInitKind::Copy);
21528   } else {
21529     DRD->setInvalidDecl();
21530   }
21531 }
21532 
ActOnOpenMPDeclareReductionDirectiveEnd(Scope * S,DeclGroupPtrTy DeclReductions,bool IsValid)21533 SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareReductionDirectiveEnd(
21534     Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
21535   for (Decl *D : DeclReductions.get()) {
21536     if (IsValid) {
21537       if (S)
21538         SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
21539                                   /*AddToContext=*/false);
21540     } else {
21541       D->setInvalidDecl();
21542     }
21543   }
21544   return DeclReductions;
21545 }
21546 
ActOnOpenMPDeclareMapperVarDecl(Scope * S,Declarator & D)21547 TypeResult SemaOpenMP::ActOnOpenMPDeclareMapperVarDecl(Scope *S,
21548                                                        Declarator &D) {
21549   TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
21550   QualType T = TInfo->getType();
21551   if (D.isInvalidType())
21552     return true;
21553 
21554   if (getLangOpts().CPlusPlus) {
21555     // Check that there are no default arguments (C++ only).
21556     SemaRef.CheckExtraCXXDefaultArguments(D);
21557   }
21558 
21559   return SemaRef.CreateParsedType(T, TInfo);
21560 }
21561 
ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,TypeResult ParsedType)21562 QualType SemaOpenMP::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
21563                                                   TypeResult ParsedType) {
21564   assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
21565 
21566   QualType MapperType = SemaRef.GetTypeFromParser(ParsedType.get());
21567   assert(!MapperType.isNull() && "Expect valid mapper type");
21568 
21569   // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21570   //  The type must be of struct, union or class type in C and C++
21571   if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
21572     Diag(TyLoc, diag::err_omp_mapper_wrong_type);
21573     return QualType();
21574   }
21575   return MapperType;
21576 }
21577 
ActOnOpenMPDeclareMapperDirective(Scope * S,DeclContext * DC,DeclarationName Name,QualType MapperType,SourceLocation StartLoc,DeclarationName VN,AccessSpecifier AS,Expr * MapperVarRef,ArrayRef<OMPClause * > Clauses,Decl * PrevDeclInScope)21578 SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareMapperDirective(
21579     Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
21580     SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
21581     Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
21582   LookupResult Lookup(SemaRef, Name, SourceLocation(),
21583                       Sema::LookupOMPMapperName,
21584                       SemaRef.forRedeclarationInCurContext());
21585   // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21586   //  A mapper-identifier may not be redeclared in the current scope for the
21587   //  same type or for a type that is compatible according to the base language
21588   //  rules.
21589   llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21590   OMPDeclareMapperDecl *PrevDMD = nullptr;
21591   bool InCompoundScope = true;
21592   if (S != nullptr) {
21593     // Find previous declaration with the same name not referenced in other
21594     // declarations.
21595     FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
21596     InCompoundScope =
21597         (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
21598     SemaRef.LookupName(Lookup, S);
21599     SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
21600                                  /*AllowInlineNamespace=*/false);
21601     llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
21602     LookupResult::Filter Filter = Lookup.makeFilter();
21603     while (Filter.hasNext()) {
21604       auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
21605       if (InCompoundScope) {
21606         auto I = UsedAsPrevious.find(PrevDecl);
21607         if (I == UsedAsPrevious.end())
21608           UsedAsPrevious[PrevDecl] = false;
21609         if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
21610           UsedAsPrevious[D] = true;
21611       }
21612       PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21613           PrevDecl->getLocation();
21614     }
21615     Filter.done();
21616     if (InCompoundScope) {
21617       for (const auto &PrevData : UsedAsPrevious) {
21618         if (!PrevData.second) {
21619           PrevDMD = PrevData.first;
21620           break;
21621         }
21622       }
21623     }
21624   } else if (PrevDeclInScope) {
21625     auto *PrevDMDInScope = PrevDMD =
21626         cast<OMPDeclareMapperDecl>(PrevDeclInScope);
21627     do {
21628       PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
21629           PrevDMDInScope->getLocation();
21630       PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
21631     } while (PrevDMDInScope != nullptr);
21632   }
21633   const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
21634   bool Invalid = false;
21635   if (I != PreviousRedeclTypes.end()) {
21636     Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
21637         << MapperType << Name;
21638     Diag(I->second, diag::note_previous_definition);
21639     Invalid = true;
21640   }
21641   // Build expressions for implicit maps of data members with 'default'
21642   // mappers.
21643   SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses.begin(),
21644                                                   Clauses.end());
21645   if (getLangOpts().OpenMP >= 50)
21646     processImplicitMapsWithDefaultMappers(SemaRef, DSAStack,
21647                                           ClausesWithImplicit);
21648   auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name,
21649                                            MapperType, VN, ClausesWithImplicit,
21650                                            PrevDMD);
21651   if (S)
21652     SemaRef.PushOnScopeChains(DMD, S);
21653   else
21654     DC->addDecl(DMD);
21655   DMD->setAccess(AS);
21656   if (Invalid)
21657     DMD->setInvalidDecl();
21658 
21659   auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
21660   VD->setDeclContext(DMD);
21661   VD->setLexicalDeclContext(DMD);
21662   DMD->addDecl(VD);
21663   DMD->setMapperVarRef(MapperVarRef);
21664 
21665   return DeclGroupPtrTy::make(DeclGroupRef(DMD));
21666 }
21667 
ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope * S,QualType MapperType,SourceLocation StartLoc,DeclarationName VN)21668 ExprResult SemaOpenMP::ActOnOpenMPDeclareMapperDirectiveVarDecl(
21669     Scope *S, QualType MapperType, SourceLocation StartLoc,
21670     DeclarationName VN) {
21671   TypeSourceInfo *TInfo =
21672       getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc);
21673   auto *VD = VarDecl::Create(
21674       getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc,
21675       StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None);
21676   if (S)
21677     SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false);
21678   Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc);
21679   DSAStack->addDeclareMapperVarRef(E);
21680   return E;
21681 }
21682 
ActOnOpenMPIteratorVarDecl(VarDecl * VD)21683 void SemaOpenMP::ActOnOpenMPIteratorVarDecl(VarDecl *VD) {
21684   if (DSAStack->getDeclareMapperVarRef())
21685     DSAStack->addIteratorVarDecl(VD);
21686 }
21687 
isOpenMPDeclareMapperVarDeclAllowed(const VarDecl * VD) const21688 bool SemaOpenMP::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const {
21689   assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
21690   const Expr *Ref = DSAStack->getDeclareMapperVarRef();
21691   if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
21692     if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
21693       return true;
21694     if (VD->isUsableInConstantExpressions(getASTContext()))
21695       return true;
21696     if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
21697       return true;
21698     return false;
21699   }
21700   return true;
21701 }
21702 
getOpenMPDeclareMapperVarName() const21703 const ValueDecl *SemaOpenMP::getOpenMPDeclareMapperVarName() const {
21704   assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
21705   return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
21706 }
21707 
ActOnOpenMPNumTeamsClause(Expr * NumTeams,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)21708 OMPClause *SemaOpenMP::ActOnOpenMPNumTeamsClause(Expr *NumTeams,
21709                                                  SourceLocation StartLoc,
21710                                                  SourceLocation LParenLoc,
21711                                                  SourceLocation EndLoc) {
21712   Expr *ValExpr = NumTeams;
21713   Stmt *HelperValStmt = nullptr;
21714 
21715   // OpenMP [teams Constrcut, Restrictions]
21716   // The num_teams expression must evaluate to a positive integer value.
21717   if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams,
21718                                  /*StrictlyPositive=*/true))
21719     return nullptr;
21720 
21721   OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
21722   OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
21723       DKind, OMPC_num_teams, getLangOpts().OpenMP);
21724   if (CaptureRegion != OMPD_unknown &&
21725       !SemaRef.CurContext->isDependentContext()) {
21726     ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
21727     llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21728     ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
21729     HelperValStmt = buildPreInits(getASTContext(), Captures);
21730   }
21731 
21732   return new (getASTContext()) OMPNumTeamsClause(
21733       ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
21734 }
21735 
ActOnOpenMPThreadLimitClause(Expr * ThreadLimit,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)21736 OMPClause *SemaOpenMP::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
21737                                                     SourceLocation StartLoc,
21738                                                     SourceLocation LParenLoc,
21739                                                     SourceLocation EndLoc) {
21740   Expr *ValExpr = ThreadLimit;
21741   Stmt *HelperValStmt = nullptr;
21742 
21743   // OpenMP [teams Constrcut, Restrictions]
21744   // The thread_limit expression must evaluate to a positive integer value.
21745   if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit,
21746                                  /*StrictlyPositive=*/true))
21747     return nullptr;
21748 
21749   OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
21750   OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
21751       DKind, OMPC_thread_limit, getLangOpts().OpenMP);
21752   if (CaptureRegion != OMPD_unknown &&
21753       !SemaRef.CurContext->isDependentContext()) {
21754     ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
21755     llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21756     ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
21757     HelperValStmt = buildPreInits(getASTContext(), Captures);
21758   }
21759 
21760   return new (getASTContext()) OMPThreadLimitClause(
21761       ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
21762 }
21763 
ActOnOpenMPPriorityClause(Expr * Priority,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)21764 OMPClause *SemaOpenMP::ActOnOpenMPPriorityClause(Expr *Priority,
21765                                                  SourceLocation StartLoc,
21766                                                  SourceLocation LParenLoc,
21767                                                  SourceLocation EndLoc) {
21768   Expr *ValExpr = Priority;
21769   Stmt *HelperValStmt = nullptr;
21770   OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
21771 
21772   // OpenMP [2.9.1, task Constrcut]
21773   // The priority-value is a non-negative numerical scalar expression.
21774   if (!isNonNegativeIntegerValue(
21775           ValExpr, SemaRef, OMPC_priority,
21776           /*StrictlyPositive=*/false, /*BuildCapture=*/true,
21777           DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
21778     return nullptr;
21779 
21780   return new (getASTContext()) OMPPriorityClause(
21781       ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
21782 }
21783 
ActOnOpenMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier,Expr * Grainsize,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ModifierLoc,SourceLocation EndLoc)21784 OMPClause *SemaOpenMP::ActOnOpenMPGrainsizeClause(
21785     OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
21786     SourceLocation StartLoc, SourceLocation LParenLoc,
21787     SourceLocation ModifierLoc, SourceLocation EndLoc) {
21788   assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
21789          "Unexpected grainsize modifier in OpenMP < 51.");
21790 
21791   if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
21792     std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
21793                                                  OMPC_GRAINSIZE_unknown);
21794     Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21795         << Values << getOpenMPClauseName(OMPC_grainsize);
21796     return nullptr;
21797   }
21798 
21799   Expr *ValExpr = Grainsize;
21800   Stmt *HelperValStmt = nullptr;
21801   OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
21802 
21803   // OpenMP [2.9.2, taskloop Constrcut]
21804   // The parameter of the grainsize clause must be a positive integer
21805   // expression.
21806   if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize,
21807                                  /*StrictlyPositive=*/true,
21808                                  /*BuildCapture=*/true,
21809                                  DSAStack->getCurrentDirective(),
21810                                  &CaptureRegion, &HelperValStmt))
21811     return nullptr;
21812 
21813   return new (getASTContext())
21814       OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
21815                          StartLoc, LParenLoc, ModifierLoc, EndLoc);
21816 }
21817 
ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier,Expr * NumTasks,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ModifierLoc,SourceLocation EndLoc)21818 OMPClause *SemaOpenMP::ActOnOpenMPNumTasksClause(
21819     OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
21820     SourceLocation StartLoc, SourceLocation LParenLoc,
21821     SourceLocation ModifierLoc, SourceLocation EndLoc) {
21822   assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
21823          "Unexpected num_tasks modifier in OpenMP < 51.");
21824 
21825   if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
21826     std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
21827                                                  OMPC_NUMTASKS_unknown);
21828     Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21829         << Values << getOpenMPClauseName(OMPC_num_tasks);
21830     return nullptr;
21831   }
21832 
21833   Expr *ValExpr = NumTasks;
21834   Stmt *HelperValStmt = nullptr;
21835   OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
21836 
21837   // OpenMP [2.9.2, taskloop Constrcut]
21838   // The parameter of the num_tasks clause must be a positive integer
21839   // expression.
21840   if (!isNonNegativeIntegerValue(
21841           ValExpr, SemaRef, OMPC_num_tasks,
21842           /*StrictlyPositive=*/true, /*BuildCapture=*/true,
21843           DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
21844     return nullptr;
21845 
21846   return new (getASTContext())
21847       OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
21848                         StartLoc, LParenLoc, ModifierLoc, EndLoc);
21849 }
21850 
ActOnOpenMPHintClause(Expr * Hint,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)21851 OMPClause *SemaOpenMP::ActOnOpenMPHintClause(Expr *Hint,
21852                                              SourceLocation StartLoc,
21853                                              SourceLocation LParenLoc,
21854                                              SourceLocation EndLoc) {
21855   // OpenMP [2.13.2, critical construct, Description]
21856   // ... where hint-expression is an integer constant expression that evaluates
21857   // to a valid lock hint.
21858   ExprResult HintExpr =
21859       VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
21860   if (HintExpr.isInvalid())
21861     return nullptr;
21862   return new (getASTContext())
21863       OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
21864 }
21865 
21866 /// Tries to find omp_event_handle_t type.
findOMPEventHandleT(Sema & S,SourceLocation Loc,DSAStackTy * Stack)21867 static bool findOMPEventHandleT(Sema &S, SourceLocation Loc,
21868                                 DSAStackTy *Stack) {
21869   QualType OMPEventHandleT = Stack->getOMPEventHandleT();
21870   if (!OMPEventHandleT.isNull())
21871     return true;
21872   IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
21873   ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
21874   if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
21875     S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
21876     return false;
21877   }
21878   Stack->setOMPEventHandleT(PT.get());
21879   return true;
21880 }
21881 
ActOnOpenMPDetachClause(Expr * Evt,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)21882 OMPClause *SemaOpenMP::ActOnOpenMPDetachClause(Expr *Evt,
21883                                                SourceLocation StartLoc,
21884                                                SourceLocation LParenLoc,
21885                                                SourceLocation EndLoc) {
21886   if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
21887       !Evt->isInstantiationDependent() &&
21888       !Evt->containsUnexpandedParameterPack()) {
21889     if (!findOMPEventHandleT(SemaRef, Evt->getExprLoc(), DSAStack))
21890       return nullptr;
21891     // OpenMP 5.0, 2.10.1 task Construct.
21892     // event-handle is a variable of the omp_event_handle_t type.
21893     auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
21894     if (!Ref) {
21895       Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
21896           << "omp_event_handle_t" << 0 << Evt->getSourceRange();
21897       return nullptr;
21898     }
21899     auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
21900     if (!VD) {
21901       Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
21902           << "omp_event_handle_t" << 0 << Evt->getSourceRange();
21903       return nullptr;
21904     }
21905     if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
21906                                                 VD->getType()) ||
21907         VD->getType().isConstant(getASTContext())) {
21908       Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
21909           << "omp_event_handle_t" << 1 << VD->getType()
21910           << Evt->getSourceRange();
21911       return nullptr;
21912     }
21913     // OpenMP 5.0, 2.10.1 task Construct
21914     // [detach clause]... The event-handle will be considered as if it was
21915     // specified on a firstprivate clause.
21916     DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
21917     if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
21918         DVar.RefExpr) {
21919       Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
21920           << getOpenMPClauseName(DVar.CKind)
21921           << getOpenMPClauseName(OMPC_firstprivate);
21922       reportOriginalDsa(SemaRef, DSAStack, VD, DVar);
21923       return nullptr;
21924     }
21925   }
21926 
21927   return new (getASTContext())
21928       OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
21929 }
21930 
ActOnOpenMPDistScheduleClause(OpenMPDistScheduleClauseKind Kind,Expr * ChunkSize,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation KindLoc,SourceLocation CommaLoc,SourceLocation EndLoc)21931 OMPClause *SemaOpenMP::ActOnOpenMPDistScheduleClause(
21932     OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
21933     SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
21934     SourceLocation EndLoc) {
21935   if (Kind == OMPC_DIST_SCHEDULE_unknown) {
21936     std::string Values;
21937     Values += "'";
21938     Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
21939     Values += "'";
21940     Diag(KindLoc, diag::err_omp_unexpected_clause_value)
21941         << Values << getOpenMPClauseName(OMPC_dist_schedule);
21942     return nullptr;
21943   }
21944   Expr *ValExpr = ChunkSize;
21945   Stmt *HelperValStmt = nullptr;
21946   if (ChunkSize) {
21947     if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
21948         !ChunkSize->isInstantiationDependent() &&
21949         !ChunkSize->containsUnexpandedParameterPack()) {
21950       SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
21951       ExprResult Val =
21952           PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
21953       if (Val.isInvalid())
21954         return nullptr;
21955 
21956       ValExpr = Val.get();
21957 
21958       // OpenMP [2.7.1, Restrictions]
21959       //  chunk_size must be a loop invariant integer expression with a positive
21960       //  value.
21961       if (std::optional<llvm::APSInt> Result =
21962               ValExpr->getIntegerConstantExpr(getASTContext())) {
21963         if (Result->isSigned() && !Result->isStrictlyPositive()) {
21964           Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
21965               << "dist_schedule" << ChunkSize->getSourceRange();
21966           return nullptr;
21967         }
21968       } else if (getOpenMPCaptureRegionForClause(
21969                      DSAStack->getCurrentDirective(), OMPC_dist_schedule,
21970                      getLangOpts().OpenMP) != OMPD_unknown &&
21971                  !SemaRef.CurContext->isDependentContext()) {
21972         ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
21973         llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21974         ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
21975         HelperValStmt = buildPreInits(getASTContext(), Captures);
21976       }
21977     }
21978   }
21979 
21980   return new (getASTContext())
21981       OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
21982                             Kind, ValExpr, HelperValStmt);
21983 }
21984 
ActOnOpenMPDefaultmapClause(OpenMPDefaultmapClauseModifier M,OpenMPDefaultmapClauseKind Kind,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation MLoc,SourceLocation KindLoc,SourceLocation EndLoc)21985 OMPClause *SemaOpenMP::ActOnOpenMPDefaultmapClause(
21986     OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind,
21987     SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
21988     SourceLocation KindLoc, SourceLocation EndLoc) {
21989   if (getLangOpts().OpenMP < 50) {
21990     if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
21991         Kind != OMPC_DEFAULTMAP_scalar) {
21992       std::string Value;
21993       SourceLocation Loc;
21994       Value += "'";
21995       if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
21996         Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
21997                                                OMPC_DEFAULTMAP_MODIFIER_tofrom);
21998         Loc = MLoc;
21999       } else {
22000         Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22001                                                OMPC_DEFAULTMAP_scalar);
22002         Loc = KindLoc;
22003       }
22004       Value += "'";
22005       Diag(Loc, diag::err_omp_unexpected_clause_value)
22006           << Value << getOpenMPClauseName(OMPC_defaultmap);
22007       return nullptr;
22008     }
22009   } else {
22010     bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
22011     bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
22012                             (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
22013     if (!isDefaultmapKind || !isDefaultmapModifier) {
22014       StringRef KindValue = "'scalar', 'aggregate', 'pointer'";
22015       if (getLangOpts().OpenMP == 50) {
22016         StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
22017                                   "'firstprivate', 'none', 'default'";
22018         if (!isDefaultmapKind && isDefaultmapModifier) {
22019           Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22020               << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22021         } else if (isDefaultmapKind && !isDefaultmapModifier) {
22022           Diag(MLoc, diag::err_omp_unexpected_clause_value)
22023               << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22024         } else {
22025           Diag(MLoc, diag::err_omp_unexpected_clause_value)
22026               << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22027           Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22028               << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22029         }
22030       } else {
22031         StringRef ModifierValue =
22032             "'alloc', 'from', 'to', 'tofrom', "
22033             "'firstprivate', 'none', 'default', 'present'";
22034         if (!isDefaultmapKind && isDefaultmapModifier) {
22035           Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22036               << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22037         } else if (isDefaultmapKind && !isDefaultmapModifier) {
22038           Diag(MLoc, diag::err_omp_unexpected_clause_value)
22039               << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22040         } else {
22041           Diag(MLoc, diag::err_omp_unexpected_clause_value)
22042               << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22043           Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22044               << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22045         }
22046       }
22047       return nullptr;
22048     }
22049 
22050     // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
22051     //  At most one defaultmap clause for each category can appear on the
22052     //  directive.
22053     if (DSAStack->checkDefaultmapCategory(Kind)) {
22054       Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
22055       return nullptr;
22056     }
22057   }
22058   if (Kind == OMPC_DEFAULTMAP_unknown) {
22059     // Variable category is not specified - mark all categories.
22060     DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
22061     DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
22062     DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
22063   } else {
22064     DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
22065   }
22066 
22067   return new (getASTContext())
22068       OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
22069 }
22070 
ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo & DTCI)22071 bool SemaOpenMP::ActOnStartOpenMPDeclareTargetContext(
22072     DeclareTargetContextInfo &DTCI) {
22073   DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
22074   if (!CurLexicalContext->isFileContext() &&
22075       !CurLexicalContext->isExternCContext() &&
22076       !CurLexicalContext->isExternCXXContext() &&
22077       !isa<CXXRecordDecl>(CurLexicalContext) &&
22078       !isa<ClassTemplateDecl>(CurLexicalContext) &&
22079       !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
22080       !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
22081     Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
22082     return false;
22083   }
22084 
22085   // Report affected OpenMP target offloading behavior when in HIP lang-mode.
22086   if (getLangOpts().HIP)
22087     Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
22088 
22089   DeclareTargetNesting.push_back(DTCI);
22090   return true;
22091 }
22092 
22093 const SemaOpenMP::DeclareTargetContextInfo
ActOnOpenMPEndDeclareTargetDirective()22094 SemaOpenMP::ActOnOpenMPEndDeclareTargetDirective() {
22095   assert(!DeclareTargetNesting.empty() &&
22096          "check isInOpenMPDeclareTargetContext() first!");
22097   return DeclareTargetNesting.pop_back_val();
22098 }
22099 
ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo & DTCI)22100 void SemaOpenMP::ActOnFinishedOpenMPDeclareTargetContext(
22101     DeclareTargetContextInfo &DTCI) {
22102   for (auto &It : DTCI.ExplicitlyMapped)
22103     ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
22104 }
22105 
DiagnoseUnterminatedOpenMPDeclareTarget()22106 void SemaOpenMP::DiagnoseUnterminatedOpenMPDeclareTarget() {
22107   if (DeclareTargetNesting.empty())
22108     return;
22109   DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
22110   Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
22111       << getOpenMPDirectiveName(DTCI.Kind);
22112 }
22113 
lookupOpenMPDeclareTargetName(Scope * CurScope,CXXScopeSpec & ScopeSpec,const DeclarationNameInfo & Id)22114 NamedDecl *SemaOpenMP::lookupOpenMPDeclareTargetName(
22115     Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
22116   LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName);
22117   SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
22118                            /*ObjectType=*/QualType(),
22119                            /*AllowBuiltinCreation=*/true);
22120 
22121   if (Lookup.isAmbiguous())
22122     return nullptr;
22123   Lookup.suppressDiagnostics();
22124 
22125   if (!Lookup.isSingleResult()) {
22126     VarOrFuncDeclFilterCCC CCC(SemaRef);
22127     if (TypoCorrection Corrected =
22128             SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
22129                                 CCC, Sema::CTK_ErrorRecovery)) {
22130       SemaRef.diagnoseTypo(Corrected,
22131                            PDiag(diag::err_undeclared_var_use_suggest)
22132                                << Id.getName());
22133       checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
22134       return nullptr;
22135     }
22136 
22137     Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
22138     return nullptr;
22139   }
22140 
22141   NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
22142   if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
22143       !isa<FunctionTemplateDecl>(ND)) {
22144     Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
22145     return nullptr;
22146   }
22147   return ND;
22148 }
22149 
ActOnOpenMPDeclareTargetName(NamedDecl * ND,SourceLocation Loc,OMPDeclareTargetDeclAttr::MapTypeTy MT,DeclareTargetContextInfo & DTCI)22150 void SemaOpenMP::ActOnOpenMPDeclareTargetName(
22151     NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
22152     DeclareTargetContextInfo &DTCI) {
22153   assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
22154           isa<FunctionTemplateDecl>(ND)) &&
22155          "Expected variable, function or function template.");
22156 
22157   if (auto *VD = dyn_cast<VarDecl>(ND)) {
22158     // Only global variables can be marked as declare target.
22159     if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22160         !VD->isStaticDataMember()) {
22161       Diag(Loc, diag::err_omp_declare_target_has_local_vars)
22162           << VD->getNameAsString();
22163       return;
22164     }
22165   }
22166   // Diagnose marking after use as it may lead to incorrect diagnosis and
22167   // codegen.
22168   if (getLangOpts().OpenMP >= 50 &&
22169       (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
22170     Diag(Loc, diag::warn_omp_declare_target_after_first_use);
22171 
22172   // Report affected OpenMP target offloading behavior when in HIP lang-mode.
22173   if (getLangOpts().HIP)
22174     Diag(Loc, diag::warn_hip_omp_target_directives);
22175 
22176   // Explicit declare target lists have precedence.
22177   const unsigned Level = -1;
22178 
22179   auto *VD = cast<ValueDecl>(ND);
22180   std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22181       OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22182   if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
22183       (*ActiveAttr)->getLevel() == Level) {
22184     Diag(Loc, diag::err_omp_device_type_mismatch)
22185         << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
22186         << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
22187                (*ActiveAttr)->getDevType());
22188     return;
22189   }
22190   if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
22191       (*ActiveAttr)->getLevel() == Level) {
22192     Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
22193     return;
22194   }
22195 
22196   if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
22197     return;
22198 
22199   Expr *IndirectE = nullptr;
22200   bool IsIndirect = false;
22201   if (DTCI.Indirect) {
22202     IndirectE = *DTCI.Indirect;
22203     if (!IndirectE)
22204       IsIndirect = true;
22205   }
22206   auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22207       getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level,
22208       SourceRange(Loc, Loc));
22209   ND->addAttr(A);
22210   if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
22211     ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
22212   checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
22213   if (auto *VD = dyn_cast<VarDecl>(ND);
22214       getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
22215       VD->hasGlobalStorage())
22216     ActOnOpenMPDeclareTargetInitializer(ND);
22217 }
22218 
checkDeclInTargetContext(SourceLocation SL,SourceRange SR,Sema & SemaRef,Decl * D)22219 static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
22220                                      Sema &SemaRef, Decl *D) {
22221   if (!D || !isa<VarDecl>(D))
22222     return;
22223   auto *VD = cast<VarDecl>(D);
22224   std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
22225       OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
22226   if (SemaRef.LangOpts.OpenMP >= 50 &&
22227       (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
22228        SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
22229       VD->hasGlobalStorage()) {
22230     if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
22231                    *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
22232       // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
22233       // If a lambda declaration and definition appears between a
22234       // declare target directive and the matching end declare target
22235       // directive, all variables that are captured by the lambda
22236       // expression must also appear in a to clause.
22237       SemaRef.Diag(VD->getLocation(),
22238                    diag::err_omp_lambda_capture_in_declare_target_not_to);
22239       SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
22240           << VD << 0 << SR;
22241       return;
22242     }
22243   }
22244   if (MapTy)
22245     return;
22246   SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
22247   SemaRef.Diag(SL, diag::note_used_here) << SR;
22248 }
22249 
checkValueDeclInTarget(SourceLocation SL,SourceRange SR,Sema & SemaRef,DSAStackTy * Stack,ValueDecl * VD)22250 static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR,
22251                                    Sema &SemaRef, DSAStackTy *Stack,
22252                                    ValueDecl *VD) {
22253   return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
22254          checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
22255                            /*FullCheck=*/false);
22256 }
22257 
checkDeclIsAllowedInOpenMPTarget(Expr * E,Decl * D,SourceLocation IdLoc)22258 void SemaOpenMP::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
22259                                                   SourceLocation IdLoc) {
22260   if (!D || D->isInvalidDecl())
22261     return;
22262   SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
22263   SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
22264   if (auto *VD = dyn_cast<VarDecl>(D)) {
22265     // Only global variables can be marked as declare target.
22266     if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22267         !VD->isStaticDataMember())
22268       return;
22269     // 2.10.6: threadprivate variable cannot appear in a declare target
22270     // directive.
22271     if (DSAStack->isThreadPrivate(VD)) {
22272       Diag(SL, diag::err_omp_threadprivate_in_target);
22273       reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false));
22274       return;
22275     }
22276   }
22277   if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
22278     D = FTD->getTemplatedDecl();
22279   if (auto *FD = dyn_cast<FunctionDecl>(D)) {
22280     std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
22281         OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
22282     if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
22283       Diag(IdLoc, diag::err_omp_function_in_link_clause);
22284       Diag(FD->getLocation(), diag::note_defined_here) << FD;
22285       return;
22286     }
22287   }
22288   if (auto *VD = dyn_cast<ValueDecl>(D)) {
22289     // Problem if any with var declared with incomplete type will be reported
22290     // as normal, so no need to check it here.
22291     if ((E || !VD->getType()->isIncompleteType()) &&
22292         !checkValueDeclInTarget(SL, SR, SemaRef, DSAStack, VD))
22293       return;
22294     if (!E && isInOpenMPDeclareTargetContext()) {
22295       // Checking declaration inside declare target region.
22296       if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
22297           isa<FunctionTemplateDecl>(D)) {
22298         std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22299             OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22300         unsigned Level = DeclareTargetNesting.size();
22301         if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
22302           return;
22303         DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
22304         Expr *IndirectE = nullptr;
22305         bool IsIndirect = false;
22306         if (DTCI.Indirect) {
22307           IndirectE = *DTCI.Indirect;
22308           if (!IndirectE)
22309             IsIndirect = true;
22310         }
22311         auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22312             getASTContext(),
22313             getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
22314                                        : OMPDeclareTargetDeclAttr::MT_To,
22315             DTCI.DT, IndirectE, IsIndirect, Level,
22316             SourceRange(DTCI.Loc, DTCI.Loc));
22317         D->addAttr(A);
22318         if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
22319           ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
22320       }
22321       return;
22322     }
22323   }
22324   if (!E)
22325     return;
22326   checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), SemaRef, D);
22327 }
22328 
22329 /// This class visits every VarDecl that the initializer references and adds
22330 /// OMPDeclareTargetDeclAttr to each of them.
22331 class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
22332   SmallVector<VarDecl *> DeclVector;
22333   Attr *A;
22334 
22335 public:
22336   /// A StmtVisitor class function that visits all DeclRefExpr and adds
22337   /// OMPDeclareTargetDeclAttr to them.
VisitDeclRefExpr(DeclRefExpr * Node)22338   void VisitDeclRefExpr(DeclRefExpr *Node) {
22339     if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
22340       VD->addAttr(A);
22341       DeclVector.push_back(VD);
22342     }
22343   }
22344   /// A function that iterates across each of the Expr's children.
VisitExpr(Expr * Ex)22345   void VisitExpr(Expr *Ex) {
22346     for (auto *Child : Ex->children()) {
22347       Visit(Child);
22348     }
22349   }
22350   /// A function that keeps a record of all the Decls that are variables, has
22351   /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
22352   /// each Decl one at a time and use the inherited 'visit' functions to look
22353   /// for DeclRefExpr.
declareTargetInitializer(Decl * TD)22354   void declareTargetInitializer(Decl *TD) {
22355     A = TD->getAttr<OMPDeclareTargetDeclAttr>();
22356     DeclVector.push_back(cast<VarDecl>(TD));
22357     while (!DeclVector.empty()) {
22358       VarDecl *TargetVarDecl = DeclVector.pop_back_val();
22359       if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
22360           TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
22361         if (Expr *Ex = TargetVarDecl->getInit())
22362           Visit(Ex);
22363       }
22364     }
22365   }
22366 };
22367 
22368 /// Adding OMPDeclareTargetDeclAttr to variables with static storage
22369 /// duration that are referenced in the initializer expression list of
22370 /// variables with static storage duration in declare target directive.
ActOnOpenMPDeclareTargetInitializer(Decl * TargetDecl)22371 void SemaOpenMP::ActOnOpenMPDeclareTargetInitializer(Decl *TargetDecl) {
22372   GlobalDeclRefChecker Checker;
22373   if (isa<VarDecl>(TargetDecl))
22374     Checker.declareTargetInitializer(TargetDecl);
22375 }
22376 
ActOnOpenMPToClause(ArrayRef<OpenMPMotionModifierKind> MotionModifiers,ArrayRef<SourceLocation> MotionModifiersLoc,CXXScopeSpec & MapperIdScopeSpec,DeclarationNameInfo & MapperId,SourceLocation ColonLoc,ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs,ArrayRef<Expr * > UnresolvedMappers)22377 OMPClause *SemaOpenMP::ActOnOpenMPToClause(
22378     ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
22379     ArrayRef<SourceLocation> MotionModifiersLoc,
22380     CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22381     SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22382     const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
22383   OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
22384                                           OMPC_MOTION_MODIFIER_unknown};
22385   SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
22386 
22387   // Process motion-modifiers, flag errors for duplicate modifiers.
22388   unsigned Count = 0;
22389   for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
22390     if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
22391         llvm::is_contained(Modifiers, MotionModifiers[I])) {
22392       Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22393       continue;
22394     }
22395     assert(Count < NumberOfOMPMotionModifiers &&
22396            "Modifiers exceed the allowed number of motion modifiers");
22397     Modifiers[Count] = MotionModifiers[I];
22398     ModifiersLoc[Count] = MotionModifiersLoc[I];
22399     ++Count;
22400   }
22401 
22402   MappableVarListInfo MVLI(VarList);
22403   checkMappableExpressionList(SemaRef, DSAStack, OMPC_to, MVLI, Locs.StartLoc,
22404                               MapperIdScopeSpec, MapperId, UnresolvedMappers);
22405   if (MVLI.ProcessedVarList.empty())
22406     return nullptr;
22407 
22408   return OMPToClause::Create(
22409       getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22410       MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22411       MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
22412 }
22413 
ActOnOpenMPFromClause(ArrayRef<OpenMPMotionModifierKind> MotionModifiers,ArrayRef<SourceLocation> MotionModifiersLoc,CXXScopeSpec & MapperIdScopeSpec,DeclarationNameInfo & MapperId,SourceLocation ColonLoc,ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs,ArrayRef<Expr * > UnresolvedMappers)22414 OMPClause *SemaOpenMP::ActOnOpenMPFromClause(
22415     ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
22416     ArrayRef<SourceLocation> MotionModifiersLoc,
22417     CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22418     SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22419     const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
22420   OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
22421                                           OMPC_MOTION_MODIFIER_unknown};
22422   SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
22423 
22424   // Process motion-modifiers, flag errors for duplicate modifiers.
22425   unsigned Count = 0;
22426   for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
22427     if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
22428         llvm::is_contained(Modifiers, MotionModifiers[I])) {
22429       Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22430       continue;
22431     }
22432     assert(Count < NumberOfOMPMotionModifiers &&
22433            "Modifiers exceed the allowed number of motion modifiers");
22434     Modifiers[Count] = MotionModifiers[I];
22435     ModifiersLoc[Count] = MotionModifiersLoc[I];
22436     ++Count;
22437   }
22438 
22439   MappableVarListInfo MVLI(VarList);
22440   checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
22441                               MapperIdScopeSpec, MapperId, UnresolvedMappers);
22442   if (MVLI.ProcessedVarList.empty())
22443     return nullptr;
22444 
22445   return OMPFromClause::Create(
22446       getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22447       MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22448       MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
22449 }
22450 
22451 OMPClause *
ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs)22452 SemaOpenMP::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
22453                                           const OMPVarListLocTy &Locs) {
22454   MappableVarListInfo MVLI(VarList);
22455   SmallVector<Expr *, 8> PrivateCopies;
22456   SmallVector<Expr *, 8> Inits;
22457 
22458   for (Expr *RefExpr : VarList) {
22459     assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
22460     SourceLocation ELoc;
22461     SourceRange ERange;
22462     Expr *SimpleRefExpr = RefExpr;
22463     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
22464     if (Res.second) {
22465       // It will be analyzed later.
22466       MVLI.ProcessedVarList.push_back(RefExpr);
22467       PrivateCopies.push_back(nullptr);
22468       Inits.push_back(nullptr);
22469     }
22470     ValueDecl *D = Res.first;
22471     if (!D)
22472       continue;
22473 
22474     QualType Type = D->getType();
22475     Type = Type.getNonReferenceType().getUnqualifiedType();
22476 
22477     auto *VD = dyn_cast<VarDecl>(D);
22478 
22479     // Item should be a pointer or reference to pointer.
22480     if (!Type->isPointerType()) {
22481       Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
22482           << 0 << RefExpr->getSourceRange();
22483       continue;
22484     }
22485 
22486     // Build the private variable and the expression that refers to it.
22487     auto VDPrivate =
22488         buildVarDecl(SemaRef, ELoc, Type, D->getName(),
22489                      D->hasAttrs() ? &D->getAttrs() : nullptr,
22490                      VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
22491     if (VDPrivate->isInvalidDecl())
22492       continue;
22493 
22494     SemaRef.CurContext->addDecl(VDPrivate);
22495     DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
22496         SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
22497 
22498     // Add temporary variable to initialize the private copy of the pointer.
22499     VarDecl *VDInit =
22500         buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp");
22501     DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
22502         SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
22503     SemaRef.AddInitializerToDecl(
22504         VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
22505         /*DirectInit=*/false);
22506 
22507     // If required, build a capture to implement the privatization initialized
22508     // with the current list item value.
22509     DeclRefExpr *Ref = nullptr;
22510     if (!VD)
22511       Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
22512     MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22513     PrivateCopies.push_back(VDPrivateRefExpr);
22514     Inits.push_back(VDInitRefExpr);
22515 
22516     // We need to add a data sharing attribute for this variable to make sure it
22517     // is correctly captured. A variable that shows up in a use_device_ptr has
22518     // similar properties of a first private variable.
22519     DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22520 
22521     // Create a mappable component for the list item. List items in this clause
22522     // only need a component.
22523     MVLI.VarBaseDeclarations.push_back(D);
22524     MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22525     MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
22526                                            /*IsNonContiguous=*/false);
22527   }
22528 
22529   if (MVLI.ProcessedVarList.empty())
22530     return nullptr;
22531 
22532   return OMPUseDevicePtrClause::Create(
22533       getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
22534       MVLI.VarBaseDeclarations, MVLI.VarComponents);
22535 }
22536 
22537 OMPClause *
ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs)22538 SemaOpenMP::ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList,
22539                                            const OMPVarListLocTy &Locs) {
22540   MappableVarListInfo MVLI(VarList);
22541 
22542   for (Expr *RefExpr : VarList) {
22543     assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
22544     SourceLocation ELoc;
22545     SourceRange ERange;
22546     Expr *SimpleRefExpr = RefExpr;
22547     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
22548                               /*AllowArraySection=*/true);
22549     if (Res.second) {
22550       // It will be analyzed later.
22551       MVLI.ProcessedVarList.push_back(RefExpr);
22552     }
22553     ValueDecl *D = Res.first;
22554     if (!D)
22555       continue;
22556     auto *VD = dyn_cast<VarDecl>(D);
22557 
22558     // If required, build a capture to implement the privatization initialized
22559     // with the current list item value.
22560     DeclRefExpr *Ref = nullptr;
22561     if (!VD)
22562       Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
22563     MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22564 
22565     // We need to add a data sharing attribute for this variable to make sure it
22566     // is correctly captured. A variable that shows up in a use_device_addr has
22567     // similar properties of a first private variable.
22568     DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22569 
22570     // Create a mappable component for the list item. List items in this clause
22571     // only need a component.
22572     MVLI.VarBaseDeclarations.push_back(D);
22573     MVLI.VarComponents.emplace_back();
22574     Expr *Component = SimpleRefExpr;
22575     if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
22576                isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
22577       Component =
22578           SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
22579     MVLI.VarComponents.back().emplace_back(Component, D,
22580                                            /*IsNonContiguous=*/false);
22581   }
22582 
22583   if (MVLI.ProcessedVarList.empty())
22584     return nullptr;
22585 
22586   return OMPUseDeviceAddrClause::Create(
22587       getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22588       MVLI.VarComponents);
22589 }
22590 
22591 OMPClause *
ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs)22592 SemaOpenMP::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
22593                                          const OMPVarListLocTy &Locs) {
22594   MappableVarListInfo MVLI(VarList);
22595   for (Expr *RefExpr : VarList) {
22596     assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
22597     SourceLocation ELoc;
22598     SourceRange ERange;
22599     Expr *SimpleRefExpr = RefExpr;
22600     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
22601     if (Res.second) {
22602       // It will be analyzed later.
22603       MVLI.ProcessedVarList.push_back(RefExpr);
22604     }
22605     ValueDecl *D = Res.first;
22606     if (!D)
22607       continue;
22608 
22609     QualType Type = D->getType();
22610     // item should be a pointer or array or reference to pointer or array
22611     if (!Type.getNonReferenceType()->isPointerType() &&
22612         !Type.getNonReferenceType()->isArrayType()) {
22613       Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
22614           << 0 << RefExpr->getSourceRange();
22615       continue;
22616     }
22617 
22618     // Check if the declaration in the clause does not show up in any data
22619     // sharing attribute.
22620     DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
22621     if (isOpenMPPrivate(DVar.CKind)) {
22622       Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22623           << getOpenMPClauseName(DVar.CKind)
22624           << getOpenMPClauseName(OMPC_is_device_ptr)
22625           << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
22626       reportOriginalDsa(SemaRef, DSAStack, D, DVar);
22627       continue;
22628     }
22629 
22630     const Expr *ConflictExpr;
22631     if (DSAStack->checkMappableExprComponentListsForDecl(
22632             D, /*CurrentRegionOnly=*/true,
22633             [&ConflictExpr](
22634                 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
22635                 OpenMPClauseKind) -> bool {
22636               ConflictExpr = R.front().getAssociatedExpression();
22637               return true;
22638             })) {
22639       Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
22640       Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
22641           << ConflictExpr->getSourceRange();
22642       continue;
22643     }
22644 
22645     // Store the components in the stack so that they can be used to check
22646     // against other clauses later on.
22647     OMPClauseMappableExprCommon::MappableComponent MC(
22648         SimpleRefExpr, D, /*IsNonContiguous=*/false);
22649     DSAStack->addMappableExpressionComponents(
22650         D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
22651 
22652     // Record the expression we've just processed.
22653     MVLI.ProcessedVarList.push_back(SimpleRefExpr);
22654 
22655     // Create a mappable component for the list item. List items in this clause
22656     // only need a component. We use a null declaration to signal fields in
22657     // 'this'.
22658     assert((isa<DeclRefExpr>(SimpleRefExpr) ||
22659             isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
22660            "Unexpected device pointer expression!");
22661     MVLI.VarBaseDeclarations.push_back(
22662         isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
22663     MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22664     MVLI.VarComponents.back().push_back(MC);
22665   }
22666 
22667   if (MVLI.ProcessedVarList.empty())
22668     return nullptr;
22669 
22670   return OMPIsDevicePtrClause::Create(
22671       getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22672       MVLI.VarComponents);
22673 }
22674 
22675 OMPClause *
ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs)22676 SemaOpenMP::ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr *> VarList,
22677                                            const OMPVarListLocTy &Locs) {
22678   MappableVarListInfo MVLI(VarList);
22679   for (Expr *RefExpr : VarList) {
22680     assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
22681     SourceLocation ELoc;
22682     SourceRange ERange;
22683     Expr *SimpleRefExpr = RefExpr;
22684     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
22685                               /*AllowArraySection=*/true);
22686     if (Res.second) {
22687       // It will be analyzed later.
22688       MVLI.ProcessedVarList.push_back(RefExpr);
22689     }
22690     ValueDecl *D = Res.first;
22691     if (!D)
22692       continue;
22693 
22694     // Check if the declaration in the clause does not show up in any data
22695     // sharing attribute.
22696     DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
22697     if (isOpenMPPrivate(DVar.CKind)) {
22698       Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22699           << getOpenMPClauseName(DVar.CKind)
22700           << getOpenMPClauseName(OMPC_has_device_addr)
22701           << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
22702       reportOriginalDsa(SemaRef, DSAStack, D, DVar);
22703       continue;
22704     }
22705 
22706     const Expr *ConflictExpr;
22707     if (DSAStack->checkMappableExprComponentListsForDecl(
22708             D, /*CurrentRegionOnly=*/true,
22709             [&ConflictExpr](
22710                 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
22711                 OpenMPClauseKind) -> bool {
22712               ConflictExpr = R.front().getAssociatedExpression();
22713               return true;
22714             })) {
22715       Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
22716       Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
22717           << ConflictExpr->getSourceRange();
22718       continue;
22719     }
22720 
22721     // Store the components in the stack so that they can be used to check
22722     // against other clauses later on.
22723     Expr *Component = SimpleRefExpr;
22724     auto *VD = dyn_cast<VarDecl>(D);
22725     if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
22726                isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
22727       Component =
22728           SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
22729     OMPClauseMappableExprCommon::MappableComponent MC(
22730         Component, D, /*IsNonContiguous=*/false);
22731     DSAStack->addMappableExpressionComponents(
22732         D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
22733 
22734     // Record the expression we've just processed.
22735     if (!VD && !SemaRef.CurContext->isDependentContext()) {
22736       DeclRefExpr *Ref =
22737           buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
22738       assert(Ref && "has_device_addr capture failed");
22739       MVLI.ProcessedVarList.push_back(Ref);
22740     } else
22741       MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
22742 
22743     // Create a mappable component for the list item. List items in this clause
22744     // only need a component. We use a null declaration to signal fields in
22745     // 'this'.
22746     assert((isa<DeclRefExpr>(SimpleRefExpr) ||
22747             isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
22748            "Unexpected device pointer expression!");
22749     MVLI.VarBaseDeclarations.push_back(
22750         isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
22751     MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22752     MVLI.VarComponents.back().push_back(MC);
22753   }
22754 
22755   if (MVLI.ProcessedVarList.empty())
22756     return nullptr;
22757 
22758   return OMPHasDeviceAddrClause::Create(
22759       getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22760       MVLI.VarComponents);
22761 }
22762 
ActOnOpenMPAllocateClause(Expr * Allocator,ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ColonLoc,SourceLocation EndLoc)22763 OMPClause *SemaOpenMP::ActOnOpenMPAllocateClause(
22764     Expr *Allocator, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
22765     SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
22766   if (Allocator) {
22767     // OpenMP [2.11.4 allocate Clause, Description]
22768     // allocator is an expression of omp_allocator_handle_t type.
22769     if (!findOMPAllocatorHandleT(SemaRef, Allocator->getExprLoc(), DSAStack))
22770       return nullptr;
22771 
22772     ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
22773     if (AllocatorRes.isInvalid())
22774       return nullptr;
22775     AllocatorRes = SemaRef.PerformImplicitConversion(
22776         AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
22777         Sema::AA_Initializing,
22778         /*AllowExplicit=*/true);
22779     if (AllocatorRes.isInvalid())
22780       return nullptr;
22781     Allocator = AllocatorRes.get();
22782   } else {
22783     // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
22784     // allocate clauses that appear on a target construct or on constructs in a
22785     // target region must specify an allocator expression unless a requires
22786     // directive with the dynamic_allocators clause is present in the same
22787     // compilation unit.
22788     if (getLangOpts().OpenMPIsTargetDevice &&
22789         !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
22790       SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
22791   }
22792   // Analyze and build list of variables.
22793   SmallVector<Expr *, 8> Vars;
22794   for (Expr *RefExpr : VarList) {
22795     assert(RefExpr && "NULL expr in OpenMP private clause.");
22796     SourceLocation ELoc;
22797     SourceRange ERange;
22798     Expr *SimpleRefExpr = RefExpr;
22799     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
22800     if (Res.second) {
22801       // It will be analyzed later.
22802       Vars.push_back(RefExpr);
22803     }
22804     ValueDecl *D = Res.first;
22805     if (!D)
22806       continue;
22807 
22808     auto *VD = dyn_cast<VarDecl>(D);
22809     DeclRefExpr *Ref = nullptr;
22810     if (!VD && !SemaRef.CurContext->isDependentContext())
22811       Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
22812     Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
22813                        ? RefExpr->IgnoreParens()
22814                        : Ref);
22815   }
22816 
22817   if (Vars.empty())
22818     return nullptr;
22819 
22820   if (Allocator)
22821     DSAStack->addInnerAllocatorExpr(Allocator);
22822   return OMPAllocateClause::Create(getASTContext(), StartLoc, LParenLoc,
22823                                    Allocator, ColonLoc, EndLoc, Vars);
22824 }
22825 
ActOnOpenMPNontemporalClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)22826 OMPClause *SemaOpenMP::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList,
22827                                                     SourceLocation StartLoc,
22828                                                     SourceLocation LParenLoc,
22829                                                     SourceLocation EndLoc) {
22830   SmallVector<Expr *, 8> Vars;
22831   for (Expr *RefExpr : VarList) {
22832     assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
22833     SourceLocation ELoc;
22834     SourceRange ERange;
22835     Expr *SimpleRefExpr = RefExpr;
22836     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
22837     if (Res.second)
22838       // It will be analyzed later.
22839       Vars.push_back(RefExpr);
22840     ValueDecl *D = Res.first;
22841     if (!D)
22842       continue;
22843 
22844     // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
22845     // A list-item cannot appear in more than one nontemporal clause.
22846     if (const Expr *PrevRef =
22847             DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
22848       Diag(ELoc, diag::err_omp_used_in_clause_twice)
22849           << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
22850       Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
22851           << getOpenMPClauseName(OMPC_nontemporal);
22852       continue;
22853     }
22854 
22855     Vars.push_back(RefExpr);
22856   }
22857 
22858   if (Vars.empty())
22859     return nullptr;
22860 
22861   return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc,
22862                                       EndLoc, Vars);
22863 }
22864 
ActOnOpenMPScopeDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)22865 StmtResult SemaOpenMP::ActOnOpenMPScopeDirective(ArrayRef<OMPClause *> Clauses,
22866                                                  Stmt *AStmt,
22867                                                  SourceLocation StartLoc,
22868                                                  SourceLocation EndLoc) {
22869   if (!AStmt)
22870     return StmtError();
22871 
22872   SemaRef.setFunctionHasBranchProtectedScope();
22873 
22874   return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
22875                                    AStmt);
22876 }
22877 
ActOnOpenMPInclusiveClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)22878 OMPClause *SemaOpenMP::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
22879                                                   SourceLocation StartLoc,
22880                                                   SourceLocation LParenLoc,
22881                                                   SourceLocation EndLoc) {
22882   SmallVector<Expr *, 8> Vars;
22883   for (Expr *RefExpr : VarList) {
22884     assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
22885     SourceLocation ELoc;
22886     SourceRange ERange;
22887     Expr *SimpleRefExpr = RefExpr;
22888     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
22889                               /*AllowArraySection=*/true);
22890     if (Res.second)
22891       // It will be analyzed later.
22892       Vars.push_back(RefExpr);
22893     ValueDecl *D = Res.first;
22894     if (!D)
22895       continue;
22896 
22897     const DSAStackTy::DSAVarData DVar =
22898         DSAStack->getTopDSA(D, /*FromParent=*/true);
22899     // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
22900     // A list item that appears in the inclusive or exclusive clause must appear
22901     // in a reduction clause with the inscan modifier on the enclosing
22902     // worksharing-loop, worksharing-loop SIMD, or simd construct.
22903     if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
22904       Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
22905           << RefExpr->getSourceRange();
22906 
22907     if (DSAStack->getParentDirective() != OMPD_unknown)
22908       DSAStack->markDeclAsUsedInScanDirective(D);
22909     Vars.push_back(RefExpr);
22910   }
22911 
22912   if (Vars.empty())
22913     return nullptr;
22914 
22915   return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
22916                                     EndLoc, Vars);
22917 }
22918 
ActOnOpenMPExclusiveClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)22919 OMPClause *SemaOpenMP::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
22920                                                   SourceLocation StartLoc,
22921                                                   SourceLocation LParenLoc,
22922                                                   SourceLocation EndLoc) {
22923   SmallVector<Expr *, 8> Vars;
22924   for (Expr *RefExpr : VarList) {
22925     assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
22926     SourceLocation ELoc;
22927     SourceRange ERange;
22928     Expr *SimpleRefExpr = RefExpr;
22929     auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
22930                               /*AllowArraySection=*/true);
22931     if (Res.second)
22932       // It will be analyzed later.
22933       Vars.push_back(RefExpr);
22934     ValueDecl *D = Res.first;
22935     if (!D)
22936       continue;
22937 
22938     OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
22939     DSAStackTy::DSAVarData DVar;
22940     if (ParentDirective != OMPD_unknown)
22941       DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
22942     // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
22943     // A list item that appears in the inclusive or exclusive clause must appear
22944     // in a reduction clause with the inscan modifier on the enclosing
22945     // worksharing-loop, worksharing-loop SIMD, or simd construct.
22946     if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
22947         DVar.Modifier != OMPC_REDUCTION_inscan) {
22948       Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
22949           << RefExpr->getSourceRange();
22950     } else {
22951       DSAStack->markDeclAsUsedInScanDirective(D);
22952     }
22953     Vars.push_back(RefExpr);
22954   }
22955 
22956   if (Vars.empty())
22957     return nullptr;
22958 
22959   return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
22960                                     EndLoc, Vars);
22961 }
22962 
22963 /// Tries to find omp_alloctrait_t type.
findOMPAlloctraitT(Sema & S,SourceLocation Loc,DSAStackTy * Stack)22964 static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
22965   QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
22966   if (!OMPAlloctraitT.isNull())
22967     return true;
22968   IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
22969   ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
22970   if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
22971     S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
22972     return false;
22973   }
22974   Stack->setOMPAlloctraitT(PT.get());
22975   return true;
22976 }
22977 
ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc,ArrayRef<UsesAllocatorsData> Data)22978 OMPClause *SemaOpenMP::ActOnOpenMPUsesAllocatorClause(
22979     SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
22980     ArrayRef<UsesAllocatorsData> Data) {
22981   ASTContext &Context = getASTContext();
22982   // OpenMP [2.12.5, target Construct]
22983   // allocator is an identifier of omp_allocator_handle_t type.
22984   if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack))
22985     return nullptr;
22986   // OpenMP [2.12.5, target Construct]
22987   // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
22988   if (llvm::any_of(
22989           Data,
22990           [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
22991       !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack))
22992     return nullptr;
22993   llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
22994   for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
22995     auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
22996     StringRef Allocator =
22997         OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
22998     DeclarationName AllocatorName = &Context.Idents.get(Allocator);
22999     PredefinedAllocators.insert(SemaRef.LookupSingleName(
23000         SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
23001   }
23002 
23003   SmallVector<OMPUsesAllocatorsClause::Data, 4> NewData;
23004   for (const UsesAllocatorsData &D : Data) {
23005     Expr *AllocatorExpr = nullptr;
23006     // Check allocator expression.
23007     if (D.Allocator->isTypeDependent()) {
23008       AllocatorExpr = D.Allocator;
23009     } else {
23010       // Traits were specified - need to assign new allocator to the specified
23011       // allocator, so it must be an lvalue.
23012       AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
23013       auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
23014       bool IsPredefinedAllocator = false;
23015       if (DRE) {
23016         OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
23017             getAllocatorKind(SemaRef, DSAStack, AllocatorExpr);
23018         IsPredefinedAllocator =
23019             AllocatorTy !=
23020             OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
23021       }
23022       QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
23023       QualType AllocatorExprType = AllocatorExpr->getType();
23024       bool IsTypeCompatible = IsPredefinedAllocator;
23025       IsTypeCompatible = IsTypeCompatible ||
23026                          Context.hasSameUnqualifiedType(AllocatorExprType,
23027                                                         OMPAllocatorHandleT);
23028       IsTypeCompatible =
23029           IsTypeCompatible ||
23030           Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
23031       bool IsNonConstantLValue =
23032           !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
23033       if (!DRE || !IsTypeCompatible ||
23034           (!IsPredefinedAllocator && !IsNonConstantLValue)) {
23035         Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
23036             << "omp_allocator_handle_t" << (DRE ? 1 : 0)
23037             << AllocatorExpr->getType() << D.Allocator->getSourceRange();
23038         continue;
23039       }
23040       // OpenMP [2.12.5, target Construct]
23041       // Predefined allocators appearing in a uses_allocators clause cannot have
23042       // traits specified.
23043       if (IsPredefinedAllocator && D.AllocatorTraits) {
23044         Diag(D.AllocatorTraits->getExprLoc(),
23045              diag::err_omp_predefined_allocator_with_traits)
23046             << D.AllocatorTraits->getSourceRange();
23047         Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
23048             << cast<NamedDecl>(DRE->getDecl())->getName()
23049             << D.Allocator->getSourceRange();
23050         continue;
23051       }
23052       // OpenMP [2.12.5, target Construct]
23053       // Non-predefined allocators appearing in a uses_allocators clause must
23054       // have traits specified.
23055       if (!IsPredefinedAllocator && !D.AllocatorTraits) {
23056         Diag(D.Allocator->getExprLoc(),
23057              diag::err_omp_nonpredefined_allocator_without_traits);
23058         continue;
23059       }
23060       // No allocator traits - just convert it to rvalue.
23061       if (!D.AllocatorTraits)
23062         AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
23063       DSAStack->addUsesAllocatorsDecl(
23064           DRE->getDecl(),
23065           IsPredefinedAllocator
23066               ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
23067               : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
23068     }
23069     Expr *AllocatorTraitsExpr = nullptr;
23070     if (D.AllocatorTraits) {
23071       if (D.AllocatorTraits->isTypeDependent()) {
23072         AllocatorTraitsExpr = D.AllocatorTraits;
23073       } else {
23074         // OpenMP [2.12.5, target Construct]
23075         // Arrays that contain allocator traits that appear in a uses_allocators
23076         // clause must be constant arrays, have constant values and be defined
23077         // in the same scope as the construct in which the clause appears.
23078         AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
23079         // Check that traits expr is a constant array.
23080         QualType TraitTy;
23081         if (const ArrayType *Ty =
23082                 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
23083           if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
23084             TraitTy = ConstArrayTy->getElementType();
23085         if (TraitTy.isNull() ||
23086             !(Context.hasSameUnqualifiedType(TraitTy,
23087                                              DSAStack->getOMPAlloctraitT()) ||
23088               Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
23089                                          /*CompareUnqualified=*/true))) {
23090           Diag(D.AllocatorTraits->getExprLoc(),
23091                diag::err_omp_expected_array_alloctraits)
23092               << AllocatorTraitsExpr->getType();
23093           continue;
23094         }
23095         // Do not map by default allocator traits if it is a standalone
23096         // variable.
23097         if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
23098           DSAStack->addUsesAllocatorsDecl(
23099               DRE->getDecl(),
23100               DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
23101       }
23102     }
23103     OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
23104     NewD.Allocator = AllocatorExpr;
23105     NewD.AllocatorTraits = AllocatorTraitsExpr;
23106     NewD.LParenLoc = D.LParenLoc;
23107     NewD.RParenLoc = D.RParenLoc;
23108   }
23109   return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc,
23110                                          EndLoc, NewData);
23111 }
23112 
ActOnOpenMPAffinityClause(SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ColonLoc,SourceLocation EndLoc,Expr * Modifier,ArrayRef<Expr * > Locators)23113 OMPClause *SemaOpenMP::ActOnOpenMPAffinityClause(
23114     SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
23115     SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
23116   SmallVector<Expr *, 8> Vars;
23117   for (Expr *RefExpr : Locators) {
23118     assert(RefExpr && "NULL expr in OpenMP shared clause.");
23119     if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
23120       // It will be analyzed later.
23121       Vars.push_back(RefExpr);
23122       continue;
23123     }
23124 
23125     SourceLocation ELoc = RefExpr->getExprLoc();
23126     Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
23127 
23128     if (!SimpleExpr->isLValue()) {
23129       Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23130           << 1 << 0 << RefExpr->getSourceRange();
23131       continue;
23132     }
23133 
23134     ExprResult Res;
23135     {
23136       Sema::TentativeAnalysisScope Trap(SemaRef);
23137       Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
23138     }
23139     if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
23140         !isa<OMPArrayShapingExpr>(SimpleExpr)) {
23141       Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23142           << 1 << 0 << RefExpr->getSourceRange();
23143       continue;
23144     }
23145     Vars.push_back(SimpleExpr);
23146   }
23147 
23148   return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc,
23149                                    ColonLoc, EndLoc, Modifier, Vars);
23150 }
23151 
ActOnOpenMPBindClause(OpenMPBindClauseKind Kind,SourceLocation KindLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)23152 OMPClause *SemaOpenMP::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind,
23153                                              SourceLocation KindLoc,
23154                                              SourceLocation StartLoc,
23155                                              SourceLocation LParenLoc,
23156                                              SourceLocation EndLoc) {
23157   if (Kind == OMPC_BIND_unknown) {
23158     Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23159         << getListOfPossibleValues(OMPC_bind, /*First=*/0,
23160                                    /*Last=*/unsigned(OMPC_BIND_unknown))
23161         << getOpenMPClauseName(OMPC_bind);
23162     return nullptr;
23163   }
23164 
23165   return OMPBindClause::Create(getASTContext(), Kind, KindLoc, StartLoc,
23166                                LParenLoc, EndLoc);
23167 }
23168 
ActOnOpenMPXDynCGroupMemClause(Expr * Size,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)23169 OMPClause *SemaOpenMP::ActOnOpenMPXDynCGroupMemClause(Expr *Size,
23170                                                       SourceLocation StartLoc,
23171                                                       SourceLocation LParenLoc,
23172                                                       SourceLocation EndLoc) {
23173   Expr *ValExpr = Size;
23174   Stmt *HelperValStmt = nullptr;
23175 
23176   // OpenMP [2.5, Restrictions]
23177   //  The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
23178   //  value.
23179   if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem,
23180                                  /*StrictlyPositive=*/false))
23181     return nullptr;
23182 
23183   OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23184   OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
23185       DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP);
23186   if (CaptureRegion != OMPD_unknown &&
23187       !SemaRef.CurContext->isDependentContext()) {
23188     ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23189     llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23190     ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23191     HelperValStmt = buildPreInits(getASTContext(), Captures);
23192   }
23193 
23194   return new (getASTContext()) OMPXDynCGroupMemClause(
23195       ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23196 }
23197 
ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType,SourceLocation DepLoc,SourceLocation ColonLoc,ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)23198 OMPClause *SemaOpenMP::ActOnOpenMPDoacrossClause(
23199     OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc,
23200     SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
23201     SourceLocation LParenLoc, SourceLocation EndLoc) {
23202 
23203   if (DSAStack->getCurrentDirective() == OMPD_ordered &&
23204       DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
23205       DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
23206       DepType != OMPC_DOACROSS_source_omp_cur_iteration &&
23207       DepType != OMPC_DOACROSS_source) {
23208     Diag(DepLoc, diag::err_omp_unexpected_clause_value)
23209         << "'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross);
23210     return nullptr;
23211   }
23212 
23213   SmallVector<Expr *, 8> Vars;
23214   DSAStackTy::OperatorOffsetTy OpsOffs;
23215   llvm::APSInt TotalDepCount(/*BitWidth=*/32);
23216   DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
23217       SemaRef,
23218       DepType == OMPC_DOACROSS_source ||
23219           DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
23220           DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
23221       VarList, DSAStack, EndLoc);
23222   Vars = VarOffset.Vars;
23223   OpsOffs = VarOffset.OpsOffs;
23224   TotalDepCount = VarOffset.TotalDepCount;
23225   auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc,
23226                                       EndLoc, DepType, DepLoc, ColonLoc, Vars,
23227                                       TotalDepCount.getZExtValue());
23228   if (DSAStack->isParentOrderedRegion())
23229     DSAStack->addDoacrossDependClause(C, OpsOffs);
23230   return C;
23231 }
23232 
ActOnOpenMPXAttributeClause(ArrayRef<const Attr * > Attrs,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)23233 OMPClause *SemaOpenMP::ActOnOpenMPXAttributeClause(ArrayRef<const Attr *> Attrs,
23234                                                    SourceLocation StartLoc,
23235                                                    SourceLocation LParenLoc,
23236                                                    SourceLocation EndLoc) {
23237   return new (getASTContext())
23238       OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
23239 }
23240 
ActOnOpenMPXBareClause(SourceLocation StartLoc,SourceLocation EndLoc)23241 OMPClause *SemaOpenMP::ActOnOpenMPXBareClause(SourceLocation StartLoc,
23242                                               SourceLocation EndLoc) {
23243   return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
23244 }
23245 
ActOnOMPArraySectionExpr(Expr * Base,SourceLocation LBLoc,Expr * LowerBound,SourceLocation ColonLocFirst,SourceLocation ColonLocSecond,Expr * Length,Expr * Stride,SourceLocation RBLoc)23246 ExprResult SemaOpenMP::ActOnOMPArraySectionExpr(
23247     Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
23248     SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
23249     Expr *Stride, SourceLocation RBLoc) {
23250   ASTContext &Context = getASTContext();
23251   if (Base->hasPlaceholderType() &&
23252       !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23253     ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
23254     if (Result.isInvalid())
23255       return ExprError();
23256     Base = Result.get();
23257   }
23258   if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
23259     ExprResult Result = SemaRef.CheckPlaceholderExpr(LowerBound);
23260     if (Result.isInvalid())
23261       return ExprError();
23262     Result = SemaRef.DefaultLvalueConversion(Result.get());
23263     if (Result.isInvalid())
23264       return ExprError();
23265     LowerBound = Result.get();
23266   }
23267   if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
23268     ExprResult Result = SemaRef.CheckPlaceholderExpr(Length);
23269     if (Result.isInvalid())
23270       return ExprError();
23271     Result = SemaRef.DefaultLvalueConversion(Result.get());
23272     if (Result.isInvalid())
23273       return ExprError();
23274     Length = Result.get();
23275   }
23276   if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
23277     ExprResult Result = SemaRef.CheckPlaceholderExpr(Stride);
23278     if (Result.isInvalid())
23279       return ExprError();
23280     Result = SemaRef.DefaultLvalueConversion(Result.get());
23281     if (Result.isInvalid())
23282       return ExprError();
23283     Stride = Result.get();
23284   }
23285 
23286   // Build an unanalyzed expression if either operand is type-dependent.
23287   if (Base->isTypeDependent() ||
23288       (LowerBound &&
23289        (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
23290       (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
23291       (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
23292     return new (Context) ArraySectionExpr(
23293         Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
23294         OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23295   }
23296 
23297   // Perform default conversions.
23298   QualType OriginalTy = ArraySectionExpr::getBaseOriginalType(Base);
23299   QualType ResultTy;
23300   if (OriginalTy->isAnyPointerType()) {
23301     ResultTy = OriginalTy->getPointeeType();
23302   } else if (OriginalTy->isArrayType()) {
23303     ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
23304   } else {
23305     return ExprError(
23306         Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
23307         << Base->getSourceRange());
23308   }
23309   // C99 6.5.2.1p1
23310   if (LowerBound) {
23311     auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
23312                                                       LowerBound);
23313     if (Res.isInvalid())
23314       return ExprError(Diag(LowerBound->getExprLoc(),
23315                             diag::err_omp_typecheck_section_not_integer)
23316                        << 0 << LowerBound->getSourceRange());
23317     LowerBound = Res.get();
23318 
23319     if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23320         LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23321       Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
23322           << 0 << LowerBound->getSourceRange();
23323   }
23324   if (Length) {
23325     auto Res =
23326         PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
23327     if (Res.isInvalid())
23328       return ExprError(Diag(Length->getExprLoc(),
23329                             diag::err_omp_typecheck_section_not_integer)
23330                        << 1 << Length->getSourceRange());
23331     Length = Res.get();
23332 
23333     if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23334         Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23335       Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
23336           << 1 << Length->getSourceRange();
23337   }
23338   if (Stride) {
23339     ExprResult Res =
23340         PerformOpenMPImplicitIntegerConversion(Stride->getExprLoc(), Stride);
23341     if (Res.isInvalid())
23342       return ExprError(Diag(Stride->getExprLoc(),
23343                             diag::err_omp_typecheck_section_not_integer)
23344                        << 1 << Stride->getSourceRange());
23345     Stride = Res.get();
23346 
23347     if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23348         Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23349       Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
23350           << 1 << Stride->getSourceRange();
23351   }
23352 
23353   // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
23354   // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
23355   // type. Note that functions are not objects, and that (in C99 parlance)
23356   // incomplete types are not object types.
23357   if (ResultTy->isFunctionType()) {
23358     Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
23359         << ResultTy << Base->getSourceRange();
23360     return ExprError();
23361   }
23362 
23363   if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
23364                                   diag::err_omp_section_incomplete_type, Base))
23365     return ExprError();
23366 
23367   if (LowerBound && !OriginalTy->isAnyPointerType()) {
23368     Expr::EvalResult Result;
23369     if (LowerBound->EvaluateAsInt(Result, Context)) {
23370       // OpenMP 5.0, [2.1.5 Array Sections]
23371       // The array section must be a subset of the original array.
23372       llvm::APSInt LowerBoundValue = Result.Val.getInt();
23373       if (LowerBoundValue.isNegative()) {
23374         Diag(LowerBound->getExprLoc(),
23375              diag::err_omp_section_not_subset_of_array)
23376             << LowerBound->getSourceRange();
23377         return ExprError();
23378       }
23379     }
23380   }
23381 
23382   if (Length) {
23383     Expr::EvalResult Result;
23384     if (Length->EvaluateAsInt(Result, Context)) {
23385       // OpenMP 5.0, [2.1.5 Array Sections]
23386       // The length must evaluate to non-negative integers.
23387       llvm::APSInt LengthValue = Result.Val.getInt();
23388       if (LengthValue.isNegative()) {
23389         Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
23390             << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
23391             << Length->getSourceRange();
23392         return ExprError();
23393       }
23394     }
23395   } else if (ColonLocFirst.isValid() &&
23396              (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
23397                                       !OriginalTy->isVariableArrayType()))) {
23398     // OpenMP 5.0, [2.1.5 Array Sections]
23399     // When the size of the array dimension is not known, the length must be
23400     // specified explicitly.
23401     Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
23402         << (!OriginalTy.isNull() && OriginalTy->isArrayType());
23403     return ExprError();
23404   }
23405 
23406   if (Stride) {
23407     Expr::EvalResult Result;
23408     if (Stride->EvaluateAsInt(Result, Context)) {
23409       // OpenMP 5.0, [2.1.5 Array Sections]
23410       // The stride must evaluate to a positive integer.
23411       llvm::APSInt StrideValue = Result.Val.getInt();
23412       if (!StrideValue.isStrictlyPositive()) {
23413         Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
23414             << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
23415             << Stride->getSourceRange();
23416         return ExprError();
23417       }
23418     }
23419   }
23420 
23421   if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23422     ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(Base);
23423     if (Result.isInvalid())
23424       return ExprError();
23425     Base = Result.get();
23426   }
23427   return new (Context) ArraySectionExpr(
23428       Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
23429       OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23430 }
23431 
ActOnOMPArrayShapingExpr(Expr * Base,SourceLocation LParenLoc,SourceLocation RParenLoc,ArrayRef<Expr * > Dims,ArrayRef<SourceRange> Brackets)23432 ExprResult SemaOpenMP::ActOnOMPArrayShapingExpr(
23433     Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
23434     ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
23435   ASTContext &Context = getASTContext();
23436   if (Base->hasPlaceholderType()) {
23437     ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
23438     if (Result.isInvalid())
23439       return ExprError();
23440     Result = SemaRef.DefaultLvalueConversion(Result.get());
23441     if (Result.isInvalid())
23442       return ExprError();
23443     Base = Result.get();
23444   }
23445   QualType BaseTy = Base->getType();
23446   // Delay analysis of the types/expressions if instantiation/specialization is
23447   // required.
23448   if (!BaseTy->isPointerType() && Base->isTypeDependent())
23449     return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
23450                                        LParenLoc, RParenLoc, Dims, Brackets);
23451   if (!BaseTy->isPointerType() ||
23452       (!Base->isTypeDependent() &&
23453        BaseTy->getPointeeType()->isIncompleteType()))
23454     return ExprError(Diag(Base->getExprLoc(),
23455                           diag::err_omp_non_pointer_type_array_shaping_base)
23456                      << Base->getSourceRange());
23457 
23458   SmallVector<Expr *, 4> NewDims;
23459   bool ErrorFound = false;
23460   for (Expr *Dim : Dims) {
23461     if (Dim->hasPlaceholderType()) {
23462       ExprResult Result = SemaRef.CheckPlaceholderExpr(Dim);
23463       if (Result.isInvalid()) {
23464         ErrorFound = true;
23465         continue;
23466       }
23467       Result = SemaRef.DefaultLvalueConversion(Result.get());
23468       if (Result.isInvalid()) {
23469         ErrorFound = true;
23470         continue;
23471       }
23472       Dim = Result.get();
23473     }
23474     if (!Dim->isTypeDependent()) {
23475       ExprResult Result =
23476           PerformOpenMPImplicitIntegerConversion(Dim->getExprLoc(), Dim);
23477       if (Result.isInvalid()) {
23478         ErrorFound = true;
23479         Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
23480             << Dim->getSourceRange();
23481         continue;
23482       }
23483       Dim = Result.get();
23484       Expr::EvalResult EvResult;
23485       if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
23486         // OpenMP 5.0, [2.1.4 Array Shaping]
23487         // Each si is an integral type expression that must evaluate to a
23488         // positive integer.
23489         llvm::APSInt Value = EvResult.Val.getInt();
23490         if (!Value.isStrictlyPositive()) {
23491           Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
23492               << toString(Value, /*Radix=*/10, /*Signed=*/true)
23493               << Dim->getSourceRange();
23494           ErrorFound = true;
23495           continue;
23496         }
23497       }
23498     }
23499     NewDims.push_back(Dim);
23500   }
23501   if (ErrorFound)
23502     return ExprError();
23503   return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
23504                                      LParenLoc, RParenLoc, NewDims, Brackets);
23505 }
23506 
ActOnOMPIteratorExpr(Scope * S,SourceLocation IteratorKwLoc,SourceLocation LLoc,SourceLocation RLoc,ArrayRef<OMPIteratorData> Data)23507 ExprResult SemaOpenMP::ActOnOMPIteratorExpr(Scope *S,
23508                                             SourceLocation IteratorKwLoc,
23509                                             SourceLocation LLoc,
23510                                             SourceLocation RLoc,
23511                                             ArrayRef<OMPIteratorData> Data) {
23512   ASTContext &Context = getASTContext();
23513   SmallVector<OMPIteratorExpr::IteratorDefinition, 4> ID;
23514   bool IsCorrect = true;
23515   for (const OMPIteratorData &D : Data) {
23516     TypeSourceInfo *TInfo = nullptr;
23517     SourceLocation StartLoc;
23518     QualType DeclTy;
23519     if (!D.Type.getAsOpaquePtr()) {
23520       // OpenMP 5.0, 2.1.6 Iterators
23521       // In an iterator-specifier, if the iterator-type is not specified then
23522       // the type of that iterator is of int type.
23523       DeclTy = Context.IntTy;
23524       StartLoc = D.DeclIdentLoc;
23525     } else {
23526       DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo);
23527       StartLoc = TInfo->getTypeLoc().getBeginLoc();
23528     }
23529 
23530     bool IsDeclTyDependent = DeclTy->isDependentType() ||
23531                              DeclTy->containsUnexpandedParameterPack() ||
23532                              DeclTy->isInstantiationDependentType();
23533     if (!IsDeclTyDependent) {
23534       if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
23535         // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
23536         // The iterator-type must be an integral or pointer type.
23537         Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
23538             << DeclTy;
23539         IsCorrect = false;
23540         continue;
23541       }
23542       if (DeclTy.isConstant(Context)) {
23543         // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
23544         // The iterator-type must not be const qualified.
23545         Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
23546             << DeclTy;
23547         IsCorrect = false;
23548         continue;
23549       }
23550     }
23551 
23552     // Iterator declaration.
23553     assert(D.DeclIdent && "Identifier expected.");
23554     // Always try to create iterator declarator to avoid extra error messages
23555     // about unknown declarations use.
23556     auto *VD =
23557         VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc,
23558                         D.DeclIdent, DeclTy, TInfo, SC_None);
23559     VD->setImplicit();
23560     if (S) {
23561       // Check for conflicting previous declaration.
23562       DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
23563       LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName,
23564                             RedeclarationKind::ForVisibleRedeclaration);
23565       Previous.suppressDiagnostics();
23566       SemaRef.LookupName(Previous, S);
23567 
23568       SemaRef.FilterLookupForScope(Previous, SemaRef.CurContext, S,
23569                                    /*ConsiderLinkage=*/false,
23570                                    /*AllowInlineNamespace=*/false);
23571       if (!Previous.empty()) {
23572         NamedDecl *Old = Previous.getRepresentativeDecl();
23573         Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
23574         Diag(Old->getLocation(), diag::note_previous_definition);
23575       } else {
23576         SemaRef.PushOnScopeChains(VD, S);
23577       }
23578     } else {
23579       SemaRef.CurContext->addDecl(VD);
23580     }
23581 
23582     /// Act on the iterator variable declaration.
23583     ActOnOpenMPIteratorVarDecl(VD);
23584 
23585     Expr *Begin = D.Range.Begin;
23586     if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
23587       ExprResult BeginRes =
23588           SemaRef.PerformImplicitConversion(Begin, DeclTy, Sema::AA_Converting);
23589       Begin = BeginRes.get();
23590     }
23591     Expr *End = D.Range.End;
23592     if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
23593       ExprResult EndRes =
23594           SemaRef.PerformImplicitConversion(End, DeclTy, Sema::AA_Converting);
23595       End = EndRes.get();
23596     }
23597     Expr *Step = D.Range.Step;
23598     if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
23599       if (!Step->getType()->isIntegralType(Context)) {
23600         Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
23601             << Step << Step->getSourceRange();
23602         IsCorrect = false;
23603         continue;
23604       }
23605       std::optional<llvm::APSInt> Result =
23606           Step->getIntegerConstantExpr(Context);
23607       // OpenMP 5.0, 2.1.6 Iterators, Restrictions
23608       // If the step expression of a range-specification equals zero, the
23609       // behavior is unspecified.
23610       if (Result && Result->isZero()) {
23611         Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
23612             << Step << Step->getSourceRange();
23613         IsCorrect = false;
23614         continue;
23615       }
23616     }
23617     if (!Begin || !End || !IsCorrect) {
23618       IsCorrect = false;
23619       continue;
23620     }
23621     OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
23622     IDElem.IteratorDecl = VD;
23623     IDElem.AssignmentLoc = D.AssignLoc;
23624     IDElem.Range.Begin = Begin;
23625     IDElem.Range.End = End;
23626     IDElem.Range.Step = Step;
23627     IDElem.ColonLoc = D.ColonLoc;
23628     IDElem.SecondColonLoc = D.SecColonLoc;
23629   }
23630   if (!IsCorrect) {
23631     // Invalidate all created iterator declarations if error is found.
23632     for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
23633       if (Decl *ID = D.IteratorDecl)
23634         ID->setInvalidDecl();
23635     }
23636     return ExprError();
23637   }
23638   SmallVector<OMPIteratorHelperData, 4> Helpers;
23639   if (!SemaRef.CurContext->isDependentContext()) {
23640     // Build number of ityeration for each iteration range.
23641     // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
23642     // ((Begini-Stepi-1-Endi) / -Stepi);
23643     for (OMPIteratorExpr::IteratorDefinition &D : ID) {
23644       // (Endi - Begini)
23645       ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub,
23646                                                   D.Range.End, D.Range.Begin);
23647       if (!Res.isUsable()) {
23648         IsCorrect = false;
23649         continue;
23650       }
23651       ExprResult St, St1;
23652       if (D.Range.Step) {
23653         St = D.Range.Step;
23654         // (Endi - Begini) + Stepi
23655         Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(),
23656                                          St.get());
23657         if (!Res.isUsable()) {
23658           IsCorrect = false;
23659           continue;
23660         }
23661         // (Endi - Begini) + Stepi - 1
23662         Res = SemaRef.CreateBuiltinBinOp(
23663             D.AssignmentLoc, BO_Sub, Res.get(),
23664             SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
23665         if (!Res.isUsable()) {
23666           IsCorrect = false;
23667           continue;
23668         }
23669         // ((Endi - Begini) + Stepi - 1) / Stepi
23670         Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(),
23671                                          St.get());
23672         if (!Res.isUsable()) {
23673           IsCorrect = false;
23674           continue;
23675         }
23676         St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
23677                                            D.Range.Step);
23678         // (Begini - Endi)
23679         ExprResult Res1 = SemaRef.CreateBuiltinBinOp(
23680             D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
23681         if (!Res1.isUsable()) {
23682           IsCorrect = false;
23683           continue;
23684         }
23685         // (Begini - Endi) - Stepi
23686         Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(),
23687                                           St1.get());
23688         if (!Res1.isUsable()) {
23689           IsCorrect = false;
23690           continue;
23691         }
23692         // (Begini - Endi) - Stepi - 1
23693         Res1 = SemaRef.CreateBuiltinBinOp(
23694             D.AssignmentLoc, BO_Sub, Res1.get(),
23695             SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
23696         if (!Res1.isUsable()) {
23697           IsCorrect = false;
23698           continue;
23699         }
23700         // ((Begini - Endi) - Stepi - 1) / (-Stepi)
23701         Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(),
23702                                           St1.get());
23703         if (!Res1.isUsable()) {
23704           IsCorrect = false;
23705           continue;
23706         }
23707         // Stepi > 0.
23708         ExprResult CmpRes = SemaRef.CreateBuiltinBinOp(
23709             D.AssignmentLoc, BO_GT, D.Range.Step,
23710             SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
23711         if (!CmpRes.isUsable()) {
23712           IsCorrect = false;
23713           continue;
23714         }
23715         Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
23716                                          CmpRes.get(), Res.get(), Res1.get());
23717         if (!Res.isUsable()) {
23718           IsCorrect = false;
23719           continue;
23720         }
23721       }
23722       Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false);
23723       if (!Res.isUsable()) {
23724         IsCorrect = false;
23725         continue;
23726       }
23727 
23728       // Build counter update.
23729       // Build counter.
23730       auto *CounterVD = VarDecl::Create(Context, SemaRef.CurContext,
23731                                         D.IteratorDecl->getBeginLoc(),
23732                                         D.IteratorDecl->getBeginLoc(), nullptr,
23733                                         Res.get()->getType(), nullptr, SC_None);
23734       CounterVD->setImplicit();
23735       ExprResult RefRes =
23736           SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue,
23737                                    D.IteratorDecl->getBeginLoc());
23738       // Build counter update.
23739       // I = Begini + counter * Stepi;
23740       ExprResult UpdateRes;
23741       if (D.Range.Step) {
23742         UpdateRes = SemaRef.CreateBuiltinBinOp(
23743             D.AssignmentLoc, BO_Mul,
23744             SemaRef.DefaultLvalueConversion(RefRes.get()).get(), St.get());
23745       } else {
23746         UpdateRes = SemaRef.DefaultLvalueConversion(RefRes.get());
23747       }
23748       if (!UpdateRes.isUsable()) {
23749         IsCorrect = false;
23750         continue;
23751       }
23752       UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
23753                                              D.Range.Begin, UpdateRes.get());
23754       if (!UpdateRes.isUsable()) {
23755         IsCorrect = false;
23756         continue;
23757       }
23758       ExprResult VDRes =
23759           SemaRef.BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl),
23760                                    cast<VarDecl>(D.IteratorDecl)->getType(),
23761                                    VK_LValue, D.IteratorDecl->getBeginLoc());
23762       UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
23763                                              VDRes.get(), UpdateRes.get());
23764       if (!UpdateRes.isUsable()) {
23765         IsCorrect = false;
23766         continue;
23767       }
23768       UpdateRes =
23769           SemaRef.ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true);
23770       if (!UpdateRes.isUsable()) {
23771         IsCorrect = false;
23772         continue;
23773       }
23774       ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
23775           D.AssignmentLoc, UO_PreInc, RefRes.get());
23776       if (!CounterUpdateRes.isUsable()) {
23777         IsCorrect = false;
23778         continue;
23779       }
23780       CounterUpdateRes = SemaRef.ActOnFinishFullExpr(CounterUpdateRes.get(),
23781                                                      /*DiscardedValue=*/true);
23782       if (!CounterUpdateRes.isUsable()) {
23783         IsCorrect = false;
23784         continue;
23785       }
23786       OMPIteratorHelperData &HD = Helpers.emplace_back();
23787       HD.CounterVD = CounterVD;
23788       HD.Upper = Res.get();
23789       HD.Update = UpdateRes.get();
23790       HD.CounterUpdate = CounterUpdateRes.get();
23791     }
23792   } else {
23793     Helpers.assign(ID.size(), {});
23794   }
23795   if (!IsCorrect) {
23796     // Invalidate all created iterator declarations if error is found.
23797     for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
23798       if (Decl *ID = D.IteratorDecl)
23799         ID->setInvalidDecl();
23800     }
23801     return ExprError();
23802   }
23803   return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc,
23804                                  LLoc, RLoc, ID, Helpers);
23805 }
23806 
23807 /// Check if \p AssumptionStr is a known assumption and warn if not.
checkOMPAssumeAttr(Sema & S,SourceLocation Loc,StringRef AssumptionStr)23808 static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc,
23809                                StringRef AssumptionStr) {
23810   if (llvm::KnownAssumptionStrings.count(AssumptionStr))
23811     return;
23812 
23813   unsigned BestEditDistance = 3;
23814   StringRef Suggestion;
23815   for (const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) {
23816     unsigned EditDistance =
23817         AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
23818     if (EditDistance < BestEditDistance) {
23819       Suggestion = KnownAssumptionIt.getKey();
23820       BestEditDistance = EditDistance;
23821     }
23822   }
23823 
23824   if (!Suggestion.empty())
23825     S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
23826         << AssumptionStr << Suggestion;
23827   else
23828     S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
23829         << AssumptionStr;
23830 }
23831 
handleOMPAssumeAttr(Decl * D,const ParsedAttr & AL)23832 void SemaOpenMP::handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL) {
23833   // Handle the case where the attribute has a text message.
23834   StringRef Str;
23835   SourceLocation AttrStrLoc;
23836   if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
23837     return;
23838 
23839   checkOMPAssumeAttr(SemaRef, AttrStrLoc, Str);
23840 
23841   D->addAttr(::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
23842 }
23843 
SemaOpenMP(Sema & S)23844 SemaOpenMP::SemaOpenMP(Sema &S)
23845     : SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
23846