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 "TreeTransform.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/ASTMutationListener.h"
17 #include "clang/AST/CXXInheritance.h"
18 #include "clang/AST/Decl.h"
19 #include "clang/AST/DeclCXX.h"
20 #include "clang/AST/DeclOpenMP.h"
21 #include "clang/AST/OpenMPClause.h"
22 #include "clang/AST/StmtCXX.h"
23 #include "clang/AST/StmtOpenMP.h"
24 #include "clang/AST/StmtVisitor.h"
25 #include "clang/AST/TypeOrdering.h"
26 #include "clang/Basic/DiagnosticSema.h"
27 #include "clang/Basic/OpenMPKinds.h"
28 #include "clang/Basic/PartialDiagnostic.h"
29 #include "clang/Basic/TargetInfo.h"
30 #include "clang/Sema/Initialization.h"
31 #include "clang/Sema/Lookup.h"
32 #include "clang/Sema/Scope.h"
33 #include "clang/Sema/ScopeInfo.h"
34 #include "clang/Sema/SemaInternal.h"
35 #include "llvm/ADT/IndexedMap.h"
36 #include "llvm/ADT/PointerEmbeddedInt.h"
37 #include "llvm/ADT/STLExtras.h"
38 #include "llvm/ADT/SmallSet.h"
39 #include "llvm/ADT/StringExtras.h"
40 #include "llvm/Frontend/OpenMP/OMPAssume.h"
41 #include "llvm/Frontend/OpenMP/OMPConstants.h"
42 #include <optional>
43 #include <set>
44
45 using namespace clang;
46 using namespace llvm::omp;
47
48 //===----------------------------------------------------------------------===//
49 // Stack of data-sharing attributes for variables
50 //===----------------------------------------------------------------------===//
51
52 static const Expr *checkMapClauseExpressionBase(
53 Sema &SemaRef, Expr *E,
54 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
55 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
56
57 namespace {
58 /// Default data sharing attributes, which can be applied to directive.
59 enum DefaultDataSharingAttributes {
60 DSA_unspecified = 0, /// Data sharing attribute not specified.
61 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
62 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
63 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
64 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
65 };
66
67 /// Stack for tracking declarations used in OpenMP directives and
68 /// clauses and their data-sharing attributes.
69 class DSAStackTy {
70 public:
71 struct DSAVarData {
72 OpenMPDirectiveKind DKind = OMPD_unknown;
73 OpenMPClauseKind CKind = OMPC_unknown;
74 unsigned Modifier = 0;
75 const Expr *RefExpr = nullptr;
76 DeclRefExpr *PrivateCopy = nullptr;
77 SourceLocation ImplicitDSALoc;
78 bool AppliedToPointee = false;
79 DSAVarData() = default;
DSAVarData__anon7e4ded5b0111::DSAStackTy::DSAVarData80 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
81 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
82 SourceLocation ImplicitDSALoc, unsigned Modifier,
83 bool AppliedToPointee)
84 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
85 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
86 AppliedToPointee(AppliedToPointee) {}
87 };
88 using OperatorOffsetTy =
89 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
90 using DoacrossDependMapTy =
91 llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>;
92 /// Kind of the declaration used in the uses_allocators clauses.
93 enum class UsesAllocatorsDeclKind {
94 /// Predefined allocator
95 PredefinedAllocator,
96 /// User-defined allocator
97 UserDefinedAllocator,
98 /// The declaration that represent allocator trait
99 AllocatorTrait,
100 };
101
102 private:
103 struct DSAInfo {
104 OpenMPClauseKind Attributes = OMPC_unknown;
105 unsigned Modifier = 0;
106 /// Pointer to a reference expression and a flag which shows that the
107 /// variable is marked as lastprivate(true) or not (false).
108 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
109 DeclRefExpr *PrivateCopy = nullptr;
110 /// true if the attribute is applied to the pointee, not the variable
111 /// itself.
112 bool AppliedToPointee = false;
113 };
114 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
115 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
116 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
117 using LoopControlVariablesMapTy =
118 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
119 /// Struct that associates a component with the clause kind where they are
120 /// found.
121 struct MappedExprComponentTy {
122 OMPClauseMappableExprCommon::MappableExprComponentLists Components;
123 OpenMPClauseKind Kind = OMPC_unknown;
124 };
125 using MappedExprComponentsTy =
126 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
127 using CriticalsWithHintsTy =
128 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
129 struct ReductionData {
130 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
131 SourceRange ReductionRange;
132 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
133 ReductionData() = default;
set__anon7e4ded5b0111::DSAStackTy::ReductionData134 void set(BinaryOperatorKind BO, SourceRange RR) {
135 ReductionRange = RR;
136 ReductionOp = BO;
137 }
set__anon7e4ded5b0111::DSAStackTy::ReductionData138 void set(const Expr *RefExpr, SourceRange RR) {
139 ReductionRange = RR;
140 ReductionOp = RefExpr;
141 }
142 };
143 using DeclReductionMapTy =
144 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
145 struct DefaultmapInfo {
146 OpenMPDefaultmapClauseModifier ImplicitBehavior =
147 OMPC_DEFAULTMAP_MODIFIER_unknown;
148 SourceLocation SLoc;
149 DefaultmapInfo() = default;
DefaultmapInfo__anon7e4ded5b0111::DSAStackTy::DefaultmapInfo150 DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc)
151 : ImplicitBehavior(M), SLoc(Loc) {}
152 };
153
154 struct SharingMapTy {
155 DeclSAMapTy SharingMap;
156 DeclReductionMapTy ReductionMap;
157 UsedRefMapTy AlignedMap;
158 UsedRefMapTy NontemporalMap;
159 MappedExprComponentsTy MappedExprComponents;
160 LoopControlVariablesMapTy LCVMap;
161 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
162 SourceLocation DefaultAttrLoc;
163 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown];
164 OpenMPDirectiveKind Directive = OMPD_unknown;
165 DeclarationNameInfo DirectiveName;
166 Scope *CurScope = nullptr;
167 DeclContext *Context = nullptr;
168 SourceLocation ConstructLoc;
169 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
170 /// get the data (loop counters etc.) about enclosing loop-based construct.
171 /// This data is required during codegen.
172 DoacrossDependMapTy DoacrossDepends;
173 /// First argument (Expr *) contains optional argument of the
174 /// 'ordered' clause, the second one is true if the regions has 'ordered'
175 /// clause, false otherwise.
176 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
177 bool RegionHasOrderConcurrent = false;
178 unsigned AssociatedLoops = 1;
179 bool HasMutipleLoops = false;
180 const Decl *PossiblyLoopCounter = nullptr;
181 bool NowaitRegion = false;
182 bool UntiedRegion = false;
183 bool CancelRegion = false;
184 bool LoopStart = false;
185 bool BodyComplete = false;
186 SourceLocation PrevScanLocation;
187 SourceLocation PrevOrderedLocation;
188 SourceLocation InnerTeamsRegionLoc;
189 /// Reference to the taskgroup task_reduction reference expression.
190 Expr *TaskgroupReductionRef = nullptr;
191 llvm::DenseSet<QualType> MappedClassesQualTypes;
192 SmallVector<Expr *, 4> InnerUsedAllocators;
193 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
194 /// List of globals marked as declare target link in this target region
195 /// (isOpenMPTargetExecutionDirective(Directive) == true).
196 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
197 /// List of decls used in inclusive/exclusive clauses of the scan directive.
198 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
199 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
200 UsesAllocatorsDecls;
201 /// Data is required on creating capture fields for implicit
202 /// default first|private clause.
203 struct ImplicitDefaultFDInfoTy {
204 /// Field decl.
205 const FieldDecl *FD = nullptr;
206 /// Nesting stack level
207 size_t StackLevel = 0;
208 /// Capture variable decl.
209 VarDecl *VD = nullptr;
ImplicitDefaultFDInfoTy__anon7e4ded5b0111::DSAStackTy::SharingMapTy::ImplicitDefaultFDInfoTy210 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
211 VarDecl *VD)
212 : FD(FD), StackLevel(StackLevel), VD(VD) {}
213 };
214 /// List of captured fields
215 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
216 ImplicitDefaultFirstprivateFDs;
217 Expr *DeclareMapperVar = nullptr;
218 SmallVector<VarDecl *, 16> IteratorVarDecls;
SharingMapTy__anon7e4ded5b0111::DSAStackTy::SharingMapTy219 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
220 Scope *CurScope, SourceLocation Loc)
221 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
222 ConstructLoc(Loc) {}
223 SharingMapTy() = default;
224 };
225
226 using StackTy = SmallVector<SharingMapTy, 4>;
227
228 /// Stack of used declaration and their data-sharing attributes.
229 DeclSAMapTy Threadprivates;
230 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
231 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
232 /// true, if check for DSA must be from parent directive, false, if
233 /// from current directive.
234 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
235 Sema &SemaRef;
236 bool ForceCapturing = false;
237 /// true if all the variables in the target executable directives must be
238 /// captured by reference.
239 bool ForceCaptureByReferenceInTargetExecutable = false;
240 CriticalsWithHintsTy Criticals;
241 unsigned IgnoredStackElements = 0;
242
243 /// Iterators over the stack iterate in order from innermost to outermost
244 /// directive.
245 using const_iterator = StackTy::const_reverse_iterator;
begin() const246 const_iterator begin() const {
247 return Stack.empty() ? const_iterator()
248 : Stack.back().first.rbegin() + IgnoredStackElements;
249 }
end() const250 const_iterator end() const {
251 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
252 }
253 using iterator = StackTy::reverse_iterator;
begin()254 iterator begin() {
255 return Stack.empty() ? iterator()
256 : Stack.back().first.rbegin() + IgnoredStackElements;
257 }
end()258 iterator end() {
259 return Stack.empty() ? iterator() : Stack.back().first.rend();
260 }
261
262 // Convenience operations to get at the elements of the stack.
263
isStackEmpty() const264 bool isStackEmpty() const {
265 return Stack.empty() ||
266 Stack.back().second != CurrentNonCapturingFunctionScope ||
267 Stack.back().first.size() <= IgnoredStackElements;
268 }
getStackSize() const269 size_t getStackSize() const {
270 return isStackEmpty() ? 0
271 : Stack.back().first.size() - IgnoredStackElements;
272 }
273
getTopOfStackOrNull()274 SharingMapTy *getTopOfStackOrNull() {
275 size_t Size = getStackSize();
276 if (Size == 0)
277 return nullptr;
278 return &Stack.back().first[Size - 1];
279 }
getTopOfStackOrNull() const280 const SharingMapTy *getTopOfStackOrNull() const {
281 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
282 }
getTopOfStack()283 SharingMapTy &getTopOfStack() {
284 assert(!isStackEmpty() && "no current directive");
285 return *getTopOfStackOrNull();
286 }
getTopOfStack() const287 const SharingMapTy &getTopOfStack() const {
288 return const_cast<DSAStackTy &>(*this).getTopOfStack();
289 }
290
getSecondOnStackOrNull()291 SharingMapTy *getSecondOnStackOrNull() {
292 size_t Size = getStackSize();
293 if (Size <= 1)
294 return nullptr;
295 return &Stack.back().first[Size - 2];
296 }
getSecondOnStackOrNull() const297 const SharingMapTy *getSecondOnStackOrNull() const {
298 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
299 }
300
301 /// Get the stack element at a certain level (previously returned by
302 /// \c getNestingLevel).
303 ///
304 /// Note that nesting levels count from outermost to innermost, and this is
305 /// the reverse of our iteration order where new inner levels are pushed at
306 /// the front of the stack.
getStackElemAtLevel(unsigned Level)307 SharingMapTy &getStackElemAtLevel(unsigned Level) {
308 assert(Level < getStackSize() && "no such stack element");
309 return Stack.back().first[Level];
310 }
getStackElemAtLevel(unsigned Level) const311 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
312 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
313 }
314
315 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
316
317 /// Checks if the variable is a local for OpenMP region.
318 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
319
320 /// Vector of previously declared requires directives
321 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
322 /// omp_allocator_handle_t type.
323 QualType OMPAllocatorHandleT;
324 /// omp_depend_t type.
325 QualType OMPDependT;
326 /// omp_event_handle_t type.
327 QualType OMPEventHandleT;
328 /// omp_alloctrait_t type.
329 QualType OMPAlloctraitT;
330 /// Expression for the predefined allocators.
331 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
332 nullptr};
333 /// Vector of previously encountered target directives
334 SmallVector<SourceLocation, 2> TargetLocations;
335 SourceLocation AtomicLocation;
336 /// Vector of declare variant construct traits.
337 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
338
339 public:
DSAStackTy(Sema & S)340 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
341
342 /// Sets omp_allocator_handle_t type.
setOMPAllocatorHandleT(QualType Ty)343 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
344 /// Gets omp_allocator_handle_t type.
getOMPAllocatorHandleT() const345 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
346 /// Sets omp_alloctrait_t type.
setOMPAlloctraitT(QualType Ty)347 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
348 /// Gets omp_alloctrait_t type.
getOMPAlloctraitT() const349 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
350 /// Sets the given default allocator.
setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,Expr * Allocator)351 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
352 Expr *Allocator) {
353 OMPPredefinedAllocators[AllocatorKind] = Allocator;
354 }
355 /// Returns the specified default allocator.
getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const356 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
357 return OMPPredefinedAllocators[AllocatorKind];
358 }
359 /// Sets omp_depend_t type.
setOMPDependT(QualType Ty)360 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
361 /// Gets omp_depend_t type.
getOMPDependT() const362 QualType getOMPDependT() const { return OMPDependT; }
363
364 /// Sets omp_event_handle_t type.
setOMPEventHandleT(QualType Ty)365 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
366 /// Gets omp_event_handle_t type.
getOMPEventHandleT() const367 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
368
isClauseParsingMode() const369 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
getClauseParsingMode() const370 OpenMPClauseKind getClauseParsingMode() const {
371 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
372 return ClauseKindMode;
373 }
setClauseParsingMode(OpenMPClauseKind K)374 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
375
isBodyComplete() const376 bool isBodyComplete() const {
377 const SharingMapTy *Top = getTopOfStackOrNull();
378 return Top && Top->BodyComplete;
379 }
setBodyComplete()380 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
381
isForceVarCapturing() const382 bool isForceVarCapturing() const { return ForceCapturing; }
setForceVarCapturing(bool V)383 void setForceVarCapturing(bool V) { ForceCapturing = V; }
384
setForceCaptureByReferenceInTargetExecutable(bool V)385 void setForceCaptureByReferenceInTargetExecutable(bool V) {
386 ForceCaptureByReferenceInTargetExecutable = V;
387 }
isForceCaptureByReferenceInTargetExecutable() const388 bool isForceCaptureByReferenceInTargetExecutable() const {
389 return ForceCaptureByReferenceInTargetExecutable;
390 }
391
push(OpenMPDirectiveKind DKind,const DeclarationNameInfo & DirName,Scope * CurScope,SourceLocation Loc)392 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
393 Scope *CurScope, SourceLocation Loc) {
394 assert(!IgnoredStackElements &&
395 "cannot change stack while ignoring elements");
396 if (Stack.empty() ||
397 Stack.back().second != CurrentNonCapturingFunctionScope)
398 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
399 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
400 Stack.back().first.back().DefaultAttrLoc = Loc;
401 }
402
pop()403 void pop() {
404 assert(!IgnoredStackElements &&
405 "cannot change stack while ignoring elements");
406 assert(!Stack.back().first.empty() &&
407 "Data-sharing attributes stack is empty!");
408 Stack.back().first.pop_back();
409 }
410
411 /// RAII object to temporarily leave the scope of a directive when we want to
412 /// logically operate in its parent.
413 class ParentDirectiveScope {
414 DSAStackTy &Self;
415 bool Active;
416
417 public:
ParentDirectiveScope(DSAStackTy & Self,bool Activate)418 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
419 : Self(Self), Active(false) {
420 if (Activate)
421 enable();
422 }
~ParentDirectiveScope()423 ~ParentDirectiveScope() { disable(); }
disable()424 void disable() {
425 if (Active) {
426 --Self.IgnoredStackElements;
427 Active = false;
428 }
429 }
enable()430 void enable() {
431 if (!Active) {
432 ++Self.IgnoredStackElements;
433 Active = true;
434 }
435 }
436 };
437
438 /// Marks that we're started loop parsing.
loopInit()439 void loopInit() {
440 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
441 "Expected loop-based directive.");
442 getTopOfStack().LoopStart = true;
443 }
444 /// Start capturing of the variables in the loop context.
loopStart()445 void loopStart() {
446 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
447 "Expected loop-based directive.");
448 getTopOfStack().LoopStart = false;
449 }
450 /// true, if variables are captured, false otherwise.
isLoopStarted() const451 bool isLoopStarted() const {
452 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
453 "Expected loop-based directive.");
454 return !getTopOfStack().LoopStart;
455 }
456 /// Marks (or clears) declaration as possibly loop counter.
resetPossibleLoopCounter(const Decl * D=nullptr)457 void resetPossibleLoopCounter(const Decl *D = nullptr) {
458 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
459 }
460 /// Gets the possible loop counter decl.
getPossiblyLoopCunter() const461 const Decl *getPossiblyLoopCunter() const {
462 return getTopOfStack().PossiblyLoopCounter;
463 }
464 /// Start new OpenMP region stack in new non-capturing function.
pushFunction()465 void pushFunction() {
466 assert(!IgnoredStackElements &&
467 "cannot change stack while ignoring elements");
468 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
469 assert(!isa<CapturingScopeInfo>(CurFnScope));
470 CurrentNonCapturingFunctionScope = CurFnScope;
471 }
472 /// Pop region stack for non-capturing function.
popFunction(const FunctionScopeInfo * OldFSI)473 void popFunction(const FunctionScopeInfo *OldFSI) {
474 assert(!IgnoredStackElements &&
475 "cannot change stack while ignoring elements");
476 if (!Stack.empty() && Stack.back().second == OldFSI) {
477 assert(Stack.back().first.empty());
478 Stack.pop_back();
479 }
480 CurrentNonCapturingFunctionScope = nullptr;
481 for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
482 if (!isa<CapturingScopeInfo>(FSI)) {
483 CurrentNonCapturingFunctionScope = FSI;
484 break;
485 }
486 }
487 }
488
addCriticalWithHint(const OMPCriticalDirective * D,llvm::APSInt Hint)489 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
490 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
491 }
492 const std::pair<const OMPCriticalDirective *, llvm::APSInt>
getCriticalWithHint(const DeclarationNameInfo & Name) const493 getCriticalWithHint(const DeclarationNameInfo &Name) const {
494 auto I = Criticals.find(Name.getAsString());
495 if (I != Criticals.end())
496 return I->second;
497 return std::make_pair(nullptr, llvm::APSInt());
498 }
499 /// If 'aligned' declaration for given variable \a D was not seen yet,
500 /// add it and return NULL; otherwise return previous occurrence's expression
501 /// for diagnostics.
502 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
503 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
504 /// add it and return NULL; otherwise return previous occurrence's expression
505 /// for diagnostics.
506 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
507
508 /// Register specified variable as loop control variable.
509 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
510 /// Check if the specified variable is a loop control variable for
511 /// current region.
512 /// \return The index of the loop control variable in the list of associated
513 /// for-loops (from outer to inner).
514 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
515 /// Check if the specified variable is a loop control variable for
516 /// parent region.
517 /// \return The index of the loop control variable in the list of associated
518 /// for-loops (from outer to inner).
519 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
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,
525 unsigned Level) const;
526 /// Get the loop control variable for the I-th loop (or nullptr) in
527 /// parent directive.
528 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
529
530 /// Marks the specified decl \p D as used in scan directive.
markDeclAsUsedInScanDirective(ValueDecl * D)531 void markDeclAsUsedInScanDirective(ValueDecl *D) {
532 if (SharingMapTy *Stack = getSecondOnStackOrNull())
533 Stack->UsedInScanDirective.insert(D);
534 }
535
536 /// Checks if the specified declaration was used in the inner scan directive.
isUsedInScanDirective(ValueDecl * D) const537 bool isUsedInScanDirective(ValueDecl *D) const {
538 if (const SharingMapTy *Stack = getTopOfStackOrNull())
539 return Stack->UsedInScanDirective.contains(D);
540 return false;
541 }
542
543 /// Adds explicit data sharing attribute to the specified declaration.
544 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
545 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
546 bool AppliedToPointee = false);
547
548 /// Adds additional information for the reduction items with the reduction id
549 /// represented as an operator.
550 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
551 BinaryOperatorKind BOK);
552 /// Adds additional information for the reduction items with the reduction id
553 /// represented as reduction identifier.
554 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
555 const Expr *ReductionRef);
556 /// Returns the location and reduction operation from the innermost parent
557 /// region for the given \p D.
558 const DSAVarData
559 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
560 BinaryOperatorKind &BOK,
561 Expr *&TaskgroupDescriptor) const;
562 /// Returns the location and reduction operation from the innermost parent
563 /// region for the given \p D.
564 const DSAVarData
565 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
566 const Expr *&ReductionRef,
567 Expr *&TaskgroupDescriptor) const;
568 /// Return reduction reference expression for the current taskgroup or
569 /// parallel/worksharing directives with task reductions.
getTaskgroupReductionRef() const570 Expr *getTaskgroupReductionRef() const {
571 assert((getTopOfStack().Directive == OMPD_taskgroup ||
572 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
573 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
574 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
575 "taskgroup reference expression requested for non taskgroup or "
576 "parallel/worksharing directive.");
577 return getTopOfStack().TaskgroupReductionRef;
578 }
579 /// Checks if the given \p VD declaration is actually a taskgroup reduction
580 /// descriptor variable at the \p Level of OpenMP regions.
isTaskgroupReductionRef(const ValueDecl * VD,unsigned Level) const581 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
582 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
583 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
584 ->getDecl() == VD;
585 }
586
587 /// Returns data sharing attributes from top of the stack for the
588 /// specified declaration.
589 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
590 /// Returns data-sharing attributes for the specified declaration.
591 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
592 /// Returns data-sharing attributes for the specified declaration.
593 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
594 /// Checks if the specified variables has data-sharing attributes which
595 /// match specified \a CPred predicate in any directive which matches \a DPred
596 /// predicate.
597 const DSAVarData
598 hasDSA(ValueDecl *D,
599 const llvm::function_ref<bool(OpenMPClauseKind, bool,
600 DefaultDataSharingAttributes)>
601 CPred,
602 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
603 bool FromParent) const;
604 /// Checks if the specified variables has data-sharing attributes which
605 /// match specified \a CPred predicate in any innermost directive which
606 /// matches \a DPred predicate.
607 const DSAVarData
608 hasInnermostDSA(ValueDecl *D,
609 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
610 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
611 bool FromParent) const;
612 /// Checks if the specified variables has explicit data-sharing
613 /// attributes which match specified \a CPred predicate at the specified
614 /// OpenMP region.
615 bool
616 hasExplicitDSA(const ValueDecl *D,
617 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
618 unsigned Level, bool NotLastprivate = false) const;
619
620 /// Returns true if the directive at level \Level matches in the
621 /// specified \a DPred predicate.
622 bool hasExplicitDirective(
623 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
624 unsigned Level) const;
625
626 /// Finds a directive which matches specified \a DPred predicate.
627 bool hasDirective(
628 const llvm::function_ref<bool(
629 OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)>
630 DPred,
631 bool FromParent) const;
632
633 /// Returns currently analyzed directive.
getCurrentDirective() const634 OpenMPDirectiveKind getCurrentDirective() const {
635 const SharingMapTy *Top = getTopOfStackOrNull();
636 return Top ? Top->Directive : OMPD_unknown;
637 }
638 /// Returns directive kind at specified level.
getDirective(unsigned Level) const639 OpenMPDirectiveKind getDirective(unsigned Level) const {
640 assert(!isStackEmpty() && "No directive at specified level.");
641 return getStackElemAtLevel(Level).Directive;
642 }
643 /// Returns the capture region at the specified level.
getCaptureRegion(unsigned Level,unsigned OpenMPCaptureLevel) const644 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
645 unsigned OpenMPCaptureLevel) const {
646 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
647 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
648 return CaptureRegions[OpenMPCaptureLevel];
649 }
650 /// Returns parent directive.
getParentDirective() const651 OpenMPDirectiveKind getParentDirective() const {
652 const SharingMapTy *Parent = getSecondOnStackOrNull();
653 return Parent ? Parent->Directive : OMPD_unknown;
654 }
655
656 /// Add requires decl to internal vector
addRequiresDecl(OMPRequiresDecl * RD)657 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
658
659 /// Checks if the defined 'requires' directive has specified type of clause.
hasRequiresDeclWithClause() const660 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
661 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
662 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
663 return isa<ClauseType>(C);
664 });
665 });
666 }
667
668 /// Checks for a duplicate clause amongst previously declared requires
669 /// directives
hasDuplicateRequiresClause(ArrayRef<OMPClause * > ClauseList) const670 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
671 bool IsDuplicate = false;
672 for (OMPClause *CNew : ClauseList) {
673 for (const OMPRequiresDecl *D : RequiresDecls) {
674 for (const OMPClause *CPrev : D->clauselists()) {
675 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
676 SemaRef.Diag(CNew->getBeginLoc(),
677 diag::err_omp_requires_clause_redeclaration)
678 << getOpenMPClauseName(CNew->getClauseKind());
679 SemaRef.Diag(CPrev->getBeginLoc(),
680 diag::note_omp_requires_previous_clause)
681 << getOpenMPClauseName(CPrev->getClauseKind());
682 IsDuplicate = true;
683 }
684 }
685 }
686 }
687 return IsDuplicate;
688 }
689
690 /// Add location of previously encountered target to internal vector
addTargetDirLocation(SourceLocation LocStart)691 void addTargetDirLocation(SourceLocation LocStart) {
692 TargetLocations.push_back(LocStart);
693 }
694
695 /// Add location for the first encountered atomicc directive.
addAtomicDirectiveLoc(SourceLocation Loc)696 void addAtomicDirectiveLoc(SourceLocation Loc) {
697 if (AtomicLocation.isInvalid())
698 AtomicLocation = Loc;
699 }
700
701 /// Returns the location of the first encountered atomic directive in the
702 /// module.
getAtomicDirectiveLoc() const703 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
704
705 // Return previously encountered target region locations.
getEncounteredTargetLocs() const706 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
707 return TargetLocations;
708 }
709
710 /// Set default data sharing attribute to none.
setDefaultDSANone(SourceLocation Loc)711 void setDefaultDSANone(SourceLocation Loc) {
712 getTopOfStack().DefaultAttr = DSA_none;
713 getTopOfStack().DefaultAttrLoc = Loc;
714 }
715 /// Set default data sharing attribute to shared.
setDefaultDSAShared(SourceLocation Loc)716 void setDefaultDSAShared(SourceLocation Loc) {
717 getTopOfStack().DefaultAttr = DSA_shared;
718 getTopOfStack().DefaultAttrLoc = Loc;
719 }
720 /// Set default data sharing attribute to private.
setDefaultDSAPrivate(SourceLocation Loc)721 void setDefaultDSAPrivate(SourceLocation Loc) {
722 getTopOfStack().DefaultAttr = DSA_private;
723 getTopOfStack().DefaultAttrLoc = Loc;
724 }
725 /// Set default data sharing attribute to firstprivate.
setDefaultDSAFirstPrivate(SourceLocation Loc)726 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
727 getTopOfStack().DefaultAttr = DSA_firstprivate;
728 getTopOfStack().DefaultAttrLoc = Loc;
729 }
730 /// Set default data mapping attribute to Modifier:Kind
setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,OpenMPDefaultmapClauseKind Kind,SourceLocation Loc)731 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
732 OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) {
733 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
734 DMI.ImplicitBehavior = M;
735 DMI.SLoc = Loc;
736 }
737 /// Check whether the implicit-behavior has been set in defaultmap
checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory)738 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
739 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
740 return getTopOfStack()
741 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
742 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
743 getTopOfStack()
744 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
745 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
746 getTopOfStack()
747 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
748 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
749 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
750 OMPC_DEFAULTMAP_MODIFIER_unknown;
751 }
752
getConstructTraits()753 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
754 return ConstructTraits;
755 }
handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,bool ScopeEntry)756 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
757 bool ScopeEntry) {
758 if (ScopeEntry)
759 ConstructTraits.append(Traits.begin(), Traits.end());
760 else
761 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
762 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
763 assert(Top == Trait && "Something left a trait on the stack!");
764 (void)Trait;
765 (void)Top;
766 }
767 }
768
getDefaultDSA(unsigned Level) const769 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
770 return getStackSize() <= Level ? DSA_unspecified
771 : getStackElemAtLevel(Level).DefaultAttr;
772 }
getDefaultDSA() const773 DefaultDataSharingAttributes getDefaultDSA() const {
774 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
775 }
getDefaultDSALocation() const776 SourceLocation getDefaultDSALocation() const {
777 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
778 }
779 OpenMPDefaultmapClauseModifier
getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const780 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
781 return isStackEmpty()
782 ? OMPC_DEFAULTMAP_MODIFIER_unknown
783 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
784 }
785 OpenMPDefaultmapClauseModifier
getDefaultmapModifierAtLevel(unsigned Level,OpenMPDefaultmapClauseKind Kind) const786 getDefaultmapModifierAtLevel(unsigned Level,
787 OpenMPDefaultmapClauseKind Kind) const {
788 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
789 }
isDefaultmapCapturedByRef(unsigned Level,OpenMPDefaultmapClauseKind Kind) const790 bool isDefaultmapCapturedByRef(unsigned Level,
791 OpenMPDefaultmapClauseKind Kind) const {
792 OpenMPDefaultmapClauseModifier M =
793 getDefaultmapModifierAtLevel(Level, Kind);
794 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
795 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
796 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
797 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
798 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom);
799 }
800 return true;
801 }
mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,OpenMPDefaultmapClauseKind Kind)802 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
803 OpenMPDefaultmapClauseKind Kind) {
804 switch (Kind) {
805 case OMPC_DEFAULTMAP_scalar:
806 case OMPC_DEFAULTMAP_pointer:
807 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
808 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
809 (M == OMPC_DEFAULTMAP_MODIFIER_default);
810 case OMPC_DEFAULTMAP_aggregate:
811 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
812 default:
813 break;
814 }
815 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
816 }
mustBeFirstprivateAtLevel(unsigned Level,OpenMPDefaultmapClauseKind Kind) const817 bool mustBeFirstprivateAtLevel(unsigned Level,
818 OpenMPDefaultmapClauseKind Kind) const {
819 OpenMPDefaultmapClauseModifier M =
820 getDefaultmapModifierAtLevel(Level, Kind);
821 return mustBeFirstprivateBase(M, Kind);
822 }
mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const823 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
824 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
825 return mustBeFirstprivateBase(M, Kind);
826 }
827
828 /// Checks if the specified variable is a threadprivate.
isThreadPrivate(VarDecl * D)829 bool isThreadPrivate(VarDecl *D) {
830 const DSAVarData DVar = getTopDSA(D, false);
831 return isOpenMPThreadPrivate(DVar.CKind);
832 }
833
834 /// Marks current region as ordered (it has an 'ordered' clause).
setOrderedRegion(bool IsOrdered,const Expr * Param,OMPOrderedClause * Clause)835 void setOrderedRegion(bool IsOrdered, const Expr *Param,
836 OMPOrderedClause *Clause) {
837 if (IsOrdered)
838 getTopOfStack().OrderedRegion.emplace(Param, Clause);
839 else
840 getTopOfStack().OrderedRegion.reset();
841 }
842 /// Returns true, if region is ordered (has associated 'ordered' clause),
843 /// false - otherwise.
isOrderedRegion() const844 bool isOrderedRegion() const {
845 if (const SharingMapTy *Top = getTopOfStackOrNull())
846 return Top->OrderedRegion.has_value();
847 return false;
848 }
849 /// Returns optional parameter for the ordered region.
getOrderedRegionParam() const850 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
851 if (const SharingMapTy *Top = getTopOfStackOrNull())
852 if (Top->OrderedRegion)
853 return *Top->OrderedRegion;
854 return std::make_pair(nullptr, nullptr);
855 }
856 /// Returns true, if parent region is ordered (has associated
857 /// 'ordered' clause), false - otherwise.
isParentOrderedRegion() const858 bool isParentOrderedRegion() const {
859 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
860 return Parent->OrderedRegion.has_value();
861 return false;
862 }
863 /// Returns optional parameter for the ordered region.
864 std::pair<const Expr *, OMPOrderedClause *>
getParentOrderedRegionParam() const865 getParentOrderedRegionParam() const {
866 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
867 if (Parent->OrderedRegion)
868 return *Parent->OrderedRegion;
869 return std::make_pair(nullptr, nullptr);
870 }
871 /// Marks current region as having an 'order' clause.
setRegionHasOrderConcurrent(bool HasOrderConcurrent)872 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
873 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
874 }
875 /// Returns true, if parent region is order (has associated
876 /// 'order' clause), false - otherwise.
isParentOrderConcurrent() const877 bool isParentOrderConcurrent() const {
878 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
879 return Parent->RegionHasOrderConcurrent;
880 return false;
881 }
882 /// Marks current region as nowait (it has a 'nowait' clause).
setNowaitRegion(bool IsNowait=true)883 void setNowaitRegion(bool IsNowait = true) {
884 getTopOfStack().NowaitRegion = IsNowait;
885 }
886 /// Returns true, if parent region is nowait (has associated
887 /// 'nowait' clause), false - otherwise.
isParentNowaitRegion() const888 bool isParentNowaitRegion() const {
889 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
890 return Parent->NowaitRegion;
891 return false;
892 }
893 /// Marks current region as untied (it has a 'untied' clause).
setUntiedRegion(bool IsUntied=true)894 void setUntiedRegion(bool IsUntied = true) {
895 getTopOfStack().UntiedRegion = IsUntied;
896 }
897 /// Return true if current region is untied.
isUntiedRegion() const898 bool isUntiedRegion() const {
899 const SharingMapTy *Top = getTopOfStackOrNull();
900 return Top ? Top->UntiedRegion : false;
901 }
902 /// Marks parent region as cancel region.
setParentCancelRegion(bool Cancel=true)903 void setParentCancelRegion(bool Cancel = true) {
904 if (SharingMapTy *Parent = getSecondOnStackOrNull())
905 Parent->CancelRegion |= Cancel;
906 }
907 /// Return true if current region has inner cancel construct.
isCancelRegion() const908 bool isCancelRegion() const {
909 const SharingMapTy *Top = getTopOfStackOrNull();
910 return Top ? Top->CancelRegion : false;
911 }
912
913 /// Mark that parent region already has scan directive.
setParentHasScanDirective(SourceLocation Loc)914 void setParentHasScanDirective(SourceLocation Loc) {
915 if (SharingMapTy *Parent = getSecondOnStackOrNull())
916 Parent->PrevScanLocation = Loc;
917 }
918 /// Return true if current region has inner cancel construct.
doesParentHasScanDirective() const919 bool doesParentHasScanDirective() const {
920 const SharingMapTy *Top = getSecondOnStackOrNull();
921 return Top ? Top->PrevScanLocation.isValid() : false;
922 }
923 /// Return true if current region has inner cancel construct.
getParentScanDirectiveLoc() const924 SourceLocation getParentScanDirectiveLoc() const {
925 const SharingMapTy *Top = getSecondOnStackOrNull();
926 return Top ? Top->PrevScanLocation : SourceLocation();
927 }
928 /// Mark that parent region already has ordered directive.
setParentHasOrderedDirective(SourceLocation Loc)929 void setParentHasOrderedDirective(SourceLocation Loc) {
930 if (SharingMapTy *Parent = getSecondOnStackOrNull())
931 Parent->PrevOrderedLocation = Loc;
932 }
933 /// Return true if current region has inner ordered construct.
doesParentHasOrderedDirective() const934 bool doesParentHasOrderedDirective() const {
935 const SharingMapTy *Top = getSecondOnStackOrNull();
936 return Top ? Top->PrevOrderedLocation.isValid() : false;
937 }
938 /// Returns the location of the previously specified ordered directive.
getParentOrderedDirectiveLoc() const939 SourceLocation getParentOrderedDirectiveLoc() const {
940 const SharingMapTy *Top = getSecondOnStackOrNull();
941 return Top ? Top->PrevOrderedLocation : SourceLocation();
942 }
943
944 /// Set collapse value for the region.
setAssociatedLoops(unsigned Val)945 void setAssociatedLoops(unsigned Val) {
946 getTopOfStack().AssociatedLoops = Val;
947 if (Val > 1)
948 getTopOfStack().HasMutipleLoops = true;
949 }
950 /// Return collapse value for region.
getAssociatedLoops() const951 unsigned getAssociatedLoops() const {
952 const SharingMapTy *Top = getTopOfStackOrNull();
953 return Top ? Top->AssociatedLoops : 0;
954 }
955 /// Returns true if the construct is associated with multiple loops.
hasMutipleLoops() const956 bool hasMutipleLoops() const {
957 const SharingMapTy *Top = getTopOfStackOrNull();
958 return Top ? Top->HasMutipleLoops : false;
959 }
960
961 /// Marks current target region as one with closely nested teams
962 /// region.
setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc)963 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
964 if (SharingMapTy *Parent = getSecondOnStackOrNull())
965 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
966 }
967 /// Returns true, if current region has closely nested teams region.
hasInnerTeamsRegion() const968 bool hasInnerTeamsRegion() const {
969 return getInnerTeamsRegionLoc().isValid();
970 }
971 /// Returns location of the nested teams region (if any).
getInnerTeamsRegionLoc() const972 SourceLocation getInnerTeamsRegionLoc() const {
973 const SharingMapTy *Top = getTopOfStackOrNull();
974 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
975 }
976
getCurScope() const977 Scope *getCurScope() const {
978 const SharingMapTy *Top = getTopOfStackOrNull();
979 return Top ? Top->CurScope : nullptr;
980 }
setContext(DeclContext * DC)981 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
getConstructLoc() const982 SourceLocation getConstructLoc() const {
983 const SharingMapTy *Top = getTopOfStackOrNull();
984 return Top ? Top->ConstructLoc : SourceLocation();
985 }
986
987 /// Do the check specified in \a Check to all component lists and return true
988 /// if any issue is found.
checkMappableExprComponentListsForDecl(const ValueDecl * VD,bool CurrentRegionOnly,const llvm::function_ref<bool (OMPClauseMappableExprCommon::MappableExprComponentListRef,OpenMPClauseKind)> Check) const989 bool checkMappableExprComponentListsForDecl(
990 const ValueDecl *VD, bool CurrentRegionOnly,
991 const llvm::function_ref<
992 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
993 OpenMPClauseKind)>
994 Check) const {
995 if (isStackEmpty())
996 return false;
997 auto SI = begin();
998 auto SE = end();
999
1000 if (SI == SE)
1001 return false;
1002
1003 if (CurrentRegionOnly)
1004 SE = std::next(SI);
1005 else
1006 std::advance(SI, 1);
1007
1008 for (; SI != SE; ++SI) {
1009 auto MI = SI->MappedExprComponents.find(VD);
1010 if (MI != SI->MappedExprComponents.end())
1011 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1012 MI->second.Components)
1013 if (Check(L, MI->second.Kind))
1014 return true;
1015 }
1016 return false;
1017 }
1018
1019 /// Do the check specified in \a Check to all component lists at a given level
1020 /// and return true if any issue is found.
checkMappableExprComponentListsForDeclAtLevel(const ValueDecl * VD,unsigned Level,const llvm::function_ref<bool (OMPClauseMappableExprCommon::MappableExprComponentListRef,OpenMPClauseKind)> Check) const1021 bool checkMappableExprComponentListsForDeclAtLevel(
1022 const ValueDecl *VD, unsigned Level,
1023 const llvm::function_ref<
1024 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1025 OpenMPClauseKind)>
1026 Check) const {
1027 if (getStackSize() <= Level)
1028 return false;
1029
1030 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1031 auto MI = StackElem.MappedExprComponents.find(VD);
1032 if (MI != StackElem.MappedExprComponents.end())
1033 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1034 MI->second.Components)
1035 if (Check(L, MI->second.Kind))
1036 return true;
1037 return false;
1038 }
1039
1040 /// Create a new mappable expression component list associated with a given
1041 /// declaration and initialize it with the provided list of components.
addMappableExpressionComponents(const ValueDecl * VD,OMPClauseMappableExprCommon::MappableExprComponentListRef Components,OpenMPClauseKind WhereFoundClauseKind)1042 void addMappableExpressionComponents(
1043 const ValueDecl *VD,
1044 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
1045 OpenMPClauseKind WhereFoundClauseKind) {
1046 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1047 // Create new entry and append the new components there.
1048 MEC.Components.resize(MEC.Components.size() + 1);
1049 MEC.Components.back().append(Components.begin(), Components.end());
1050 MEC.Kind = WhereFoundClauseKind;
1051 }
1052
getNestingLevel() const1053 unsigned getNestingLevel() const {
1054 assert(!isStackEmpty());
1055 return getStackSize() - 1;
1056 }
addDoacrossDependClause(OMPDependClause * C,const OperatorOffsetTy & OpsOffs)1057 void addDoacrossDependClause(OMPDependClause *C,
1058 const OperatorOffsetTy &OpsOffs) {
1059 SharingMapTy *Parent = getSecondOnStackOrNull();
1060 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1061 Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1062 }
1063 llvm::iterator_range<DoacrossDependMapTy::const_iterator>
getDoacrossDependClauses() const1064 getDoacrossDependClauses() const {
1065 const SharingMapTy &StackElem = getTopOfStack();
1066 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1067 const DoacrossDependMapTy &Ref = StackElem.DoacrossDepends;
1068 return llvm::make_range(Ref.begin(), Ref.end());
1069 }
1070 return llvm::make_range(StackElem.DoacrossDepends.end(),
1071 StackElem.DoacrossDepends.end());
1072 }
1073
1074 // Store types of classes which have been explicitly mapped
addMappedClassesQualTypes(QualType QT)1075 void addMappedClassesQualTypes(QualType QT) {
1076 SharingMapTy &StackElem = getTopOfStack();
1077 StackElem.MappedClassesQualTypes.insert(QT);
1078 }
1079
1080 // Return set of mapped classes types
isClassPreviouslyMapped(QualType QT) const1081 bool isClassPreviouslyMapped(QualType QT) const {
1082 const SharingMapTy &StackElem = getTopOfStack();
1083 return StackElem.MappedClassesQualTypes.contains(QT);
1084 }
1085
1086 /// Adds global declare target to the parent target region.
addToParentTargetRegionLinkGlobals(DeclRefExpr * E)1087 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1088 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1089 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1090 "Expected declare target link global.");
1091 for (auto &Elem : *this) {
1092 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1093 Elem.DeclareTargetLinkVarDecls.push_back(E);
1094 return;
1095 }
1096 }
1097 }
1098
1099 /// Returns the list of globals with declare target link if current directive
1100 /// is target.
getLinkGlobals() const1101 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1102 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1103 "Expected target executable directive.");
1104 return getTopOfStack().DeclareTargetLinkVarDecls;
1105 }
1106
1107 /// Adds list of allocators expressions.
addInnerAllocatorExpr(Expr * E)1108 void addInnerAllocatorExpr(Expr *E) {
1109 getTopOfStack().InnerUsedAllocators.push_back(E);
1110 }
1111 /// Return list of used allocators.
getInnerAllocators() const1112 ArrayRef<Expr *> getInnerAllocators() const {
1113 return getTopOfStack().InnerUsedAllocators;
1114 }
1115 /// Marks the declaration as implicitly firstprivate nin the task-based
1116 /// regions.
addImplicitTaskFirstprivate(unsigned Level,Decl * D)1117 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1118 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1119 }
1120 /// Checks if the decl is implicitly firstprivate in the task-based region.
isImplicitTaskFirstprivate(Decl * D) const1121 bool isImplicitTaskFirstprivate(Decl *D) const {
1122 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1123 }
1124
1125 /// Marks decl as used in uses_allocators clause as the allocator.
addUsesAllocatorsDecl(const Decl * D,UsesAllocatorsDeclKind Kind)1126 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1127 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1128 }
1129 /// Checks if specified decl is used in uses allocator clause as the
1130 /// allocator.
1131 std::optional<UsesAllocatorsDeclKind>
isUsesAllocatorsDecl(unsigned Level,const Decl * D) const1132 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1133 const SharingMapTy &StackElem = getTopOfStack();
1134 auto I = StackElem.UsesAllocatorsDecls.find(D);
1135 if (I == StackElem.UsesAllocatorsDecls.end())
1136 return std::nullopt;
1137 return I->getSecond();
1138 }
1139 std::optional<UsesAllocatorsDeclKind>
isUsesAllocatorsDecl(const Decl * D) const1140 isUsesAllocatorsDecl(const Decl *D) const {
1141 const SharingMapTy &StackElem = getTopOfStack();
1142 auto I = StackElem.UsesAllocatorsDecls.find(D);
1143 if (I == StackElem.UsesAllocatorsDecls.end())
1144 return std::nullopt;
1145 return I->getSecond();
1146 }
1147
addDeclareMapperVarRef(Expr * Ref)1148 void addDeclareMapperVarRef(Expr *Ref) {
1149 SharingMapTy &StackElem = getTopOfStack();
1150 StackElem.DeclareMapperVar = Ref;
1151 }
getDeclareMapperVarRef() const1152 const Expr *getDeclareMapperVarRef() const {
1153 const SharingMapTy *Top = getTopOfStackOrNull();
1154 return Top ? Top->DeclareMapperVar : nullptr;
1155 }
1156
1157 /// Add a new iterator variable.
addIteratorVarDecl(VarDecl * VD)1158 void addIteratorVarDecl(VarDecl *VD) {
1159 SharingMapTy &StackElem = getTopOfStack();
1160 StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl());
1161 }
1162 /// Check if variable declaration is an iterator VarDecl.
isIteratorVarDecl(const VarDecl * VD) const1163 bool isIteratorVarDecl(const VarDecl *VD) const {
1164 const SharingMapTy *Top = getTopOfStackOrNull();
1165 if (!Top)
1166 return false;
1167
1168 return llvm::any_of(Top->IteratorVarDecls, [VD](const VarDecl *IteratorVD) {
1169 return IteratorVD == VD->getCanonicalDecl();
1170 });
1171 }
1172 /// get captured field from ImplicitDefaultFirstprivateFDs
getImplicitFDCapExprDecl(const FieldDecl * FD) const1173 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1174 const_iterator I = begin();
1175 const_iterator EndI = end();
1176 size_t StackLevel = getStackSize();
1177 for (; I != EndI; ++I) {
1178 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1179 break;
1180 StackLevel--;
1181 }
1182 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1183 if (I == EndI)
1184 return nullptr;
1185 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1186 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1187 return IFD.VD;
1188 return nullptr;
1189 }
1190 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
isImplicitDefaultFirstprivateFD(VarDecl * VD) const1191 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1192 const_iterator I = begin();
1193 const_iterator EndI = end();
1194 for (; I != EndI; ++I)
1195 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1196 break;
1197 if (I == EndI)
1198 return false;
1199 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1200 if (IFD.VD == VD)
1201 return true;
1202 return false;
1203 }
1204 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
addImplicitDefaultFirstprivateFD(const FieldDecl * FD,VarDecl * VD)1205 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1206 iterator I = begin();
1207 const_iterator EndI = end();
1208 size_t StackLevel = getStackSize();
1209 for (; I != EndI; ++I) {
1210 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1211 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1212 break;
1213 }
1214 StackLevel--;
1215 }
1216 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1217 }
1218 };
1219
isImplicitTaskingRegion(OpenMPDirectiveKind DKind)1220 bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1221 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1222 }
1223
isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind)1224 bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1225 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1226 DKind == OMPD_unknown;
1227 }
1228
1229 } // namespace
1230
getExprAsWritten(const Expr * E)1231 static const Expr *getExprAsWritten(const Expr *E) {
1232 if (const auto *FE = dyn_cast<FullExpr>(E))
1233 E = FE->getSubExpr();
1234
1235 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1236 E = MTE->getSubExpr();
1237
1238 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1239 E = Binder->getSubExpr();
1240
1241 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1242 E = ICE->getSubExprAsWritten();
1243 return E->IgnoreParens();
1244 }
1245
getExprAsWritten(Expr * E)1246 static Expr *getExprAsWritten(Expr *E) {
1247 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1248 }
1249
getCanonicalDecl(const ValueDecl * D)1250 static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1251 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1252 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1253 D = ME->getMemberDecl();
1254 const auto *VD = dyn_cast<VarDecl>(D);
1255 const auto *FD = dyn_cast<FieldDecl>(D);
1256 if (VD != nullptr) {
1257 VD = VD->getCanonicalDecl();
1258 D = VD;
1259 } else {
1260 assert(FD);
1261 FD = FD->getCanonicalDecl();
1262 D = FD;
1263 }
1264 return D;
1265 }
1266
getCanonicalDecl(ValueDecl * D)1267 static ValueDecl *getCanonicalDecl(ValueDecl *D) {
1268 return const_cast<ValueDecl *>(
1269 getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1270 }
1271
getDSA(const_iterator & Iter,ValueDecl * D) const1272 DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1273 ValueDecl *D) const {
1274 D = getCanonicalDecl(D);
1275 auto *VD = dyn_cast<VarDecl>(D);
1276 const auto *FD = dyn_cast<FieldDecl>(D);
1277 DSAVarData DVar;
1278 if (Iter == end()) {
1279 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1280 // in a region but not in construct]
1281 // File-scope or namespace-scope variables referenced in called routines
1282 // in the region are shared unless they appear in a threadprivate
1283 // directive.
1284 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1285 DVar.CKind = OMPC_shared;
1286
1287 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1288 // in a region but not in construct]
1289 // Variables with static storage duration that are declared in called
1290 // routines in the region are shared.
1291 if (VD && VD->hasGlobalStorage())
1292 DVar.CKind = OMPC_shared;
1293
1294 // Non-static data members are shared by default.
1295 if (FD)
1296 DVar.CKind = OMPC_shared;
1297
1298 return DVar;
1299 }
1300
1301 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1302 // in a Construct, C/C++, predetermined, p.1]
1303 // Variables with automatic storage duration that are declared in a scope
1304 // inside the construct are private.
1305 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1306 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1307 DVar.CKind = OMPC_private;
1308 return DVar;
1309 }
1310
1311 DVar.DKind = Iter->Directive;
1312 // Explicitly specified attributes and local variables with predetermined
1313 // attributes.
1314 if (Iter->SharingMap.count(D)) {
1315 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1316 DVar.RefExpr = Data.RefExpr.getPointer();
1317 DVar.PrivateCopy = Data.PrivateCopy;
1318 DVar.CKind = Data.Attributes;
1319 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1320 DVar.Modifier = Data.Modifier;
1321 DVar.AppliedToPointee = Data.AppliedToPointee;
1322 return DVar;
1323 }
1324
1325 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1326 // in a Construct, C/C++, implicitly determined, p.1]
1327 // In a parallel or task construct, the data-sharing attributes of these
1328 // variables are determined by the default clause, if present.
1329 switch (Iter->DefaultAttr) {
1330 case DSA_shared:
1331 DVar.CKind = OMPC_shared;
1332 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1333 return DVar;
1334 case DSA_none:
1335 return DVar;
1336 case DSA_firstprivate:
1337 if (VD && VD->getStorageDuration() == SD_Static &&
1338 VD->getDeclContext()->isFileContext()) {
1339 DVar.CKind = OMPC_unknown;
1340 } else {
1341 DVar.CKind = OMPC_firstprivate;
1342 }
1343 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1344 return DVar;
1345 case DSA_private:
1346 // each variable with static storage duration that is declared
1347 // in a namespace or global scope and referenced in the construct,
1348 // and that does not have a predetermined data-sharing attribute
1349 if (VD && VD->getStorageDuration() == SD_Static &&
1350 VD->getDeclContext()->isFileContext()) {
1351 DVar.CKind = OMPC_unknown;
1352 } else {
1353 DVar.CKind = OMPC_private;
1354 }
1355 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1356 return DVar;
1357 case DSA_unspecified:
1358 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1359 // in a Construct, implicitly determined, p.2]
1360 // In a parallel construct, if no default clause is present, these
1361 // variables are shared.
1362 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1363 if ((isOpenMPParallelDirective(DVar.DKind) &&
1364 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1365 isOpenMPTeamsDirective(DVar.DKind)) {
1366 DVar.CKind = OMPC_shared;
1367 return DVar;
1368 }
1369
1370 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1371 // in a Construct, implicitly determined, p.4]
1372 // In a task construct, if no default clause is present, a variable that in
1373 // the enclosing context is determined to be shared by all implicit tasks
1374 // bound to the current team is shared.
1375 if (isOpenMPTaskingDirective(DVar.DKind)) {
1376 DSAVarData DVarTemp;
1377 const_iterator I = Iter, E = end();
1378 do {
1379 ++I;
1380 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1381 // Referenced in a Construct, implicitly determined, p.6]
1382 // In a task construct, if no default clause is present, a variable
1383 // whose data-sharing attribute is not determined by the rules above is
1384 // firstprivate.
1385 DVarTemp = getDSA(I, D);
1386 if (DVarTemp.CKind != OMPC_shared) {
1387 DVar.RefExpr = nullptr;
1388 DVar.CKind = OMPC_firstprivate;
1389 return DVar;
1390 }
1391 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1392 DVar.CKind =
1393 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1394 return DVar;
1395 }
1396 }
1397 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1398 // in a Construct, implicitly determined, p.3]
1399 // For constructs other than task, if no default clause is present, these
1400 // variables inherit their data-sharing attributes from the enclosing
1401 // context.
1402 return getDSA(++Iter, D);
1403 }
1404
addUniqueAligned(const ValueDecl * D,const Expr * NewDE)1405 const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1406 const Expr *NewDE) {
1407 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1408 D = getCanonicalDecl(D);
1409 SharingMapTy &StackElem = getTopOfStack();
1410 auto It = StackElem.AlignedMap.find(D);
1411 if (It == StackElem.AlignedMap.end()) {
1412 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1413 StackElem.AlignedMap[D] = NewDE;
1414 return nullptr;
1415 }
1416 assert(It->second && "Unexpected nullptr expr in the aligned map");
1417 return It->second;
1418 }
1419
addUniqueNontemporal(const ValueDecl * D,const Expr * NewDE)1420 const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1421 const Expr *NewDE) {
1422 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1423 D = getCanonicalDecl(D);
1424 SharingMapTy &StackElem = getTopOfStack();
1425 auto It = StackElem.NontemporalMap.find(D);
1426 if (It == StackElem.NontemporalMap.end()) {
1427 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1428 StackElem.NontemporalMap[D] = NewDE;
1429 return nullptr;
1430 }
1431 assert(It->second && "Unexpected nullptr expr in the aligned map");
1432 return It->second;
1433 }
1434
addLoopControlVariable(const ValueDecl * D,VarDecl * Capture)1435 void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1436 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1437 D = getCanonicalDecl(D);
1438 SharingMapTy &StackElem = getTopOfStack();
1439 StackElem.LCVMap.try_emplace(
1440 D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1441 }
1442
1443 const DSAStackTy::LCDeclInfo
isLoopControlVariable(const ValueDecl * D) const1444 DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1445 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1446 D = getCanonicalDecl(D);
1447 const SharingMapTy &StackElem = getTopOfStack();
1448 auto It = StackElem.LCVMap.find(D);
1449 if (It != StackElem.LCVMap.end())
1450 return It->second;
1451 return {0, nullptr};
1452 }
1453
1454 const DSAStackTy::LCDeclInfo
isLoopControlVariable(const ValueDecl * D,unsigned Level) const1455 DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1456 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1457 D = getCanonicalDecl(D);
1458 for (unsigned I = Level + 1; I > 0; --I) {
1459 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1460 auto It = StackElem.LCVMap.find(D);
1461 if (It != StackElem.LCVMap.end())
1462 return It->second;
1463 }
1464 return {0, nullptr};
1465 }
1466
1467 const DSAStackTy::LCDeclInfo
isParentLoopControlVariable(const ValueDecl * D) const1468 DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1469 const SharingMapTy *Parent = getSecondOnStackOrNull();
1470 assert(Parent && "Data-sharing attributes stack is empty");
1471 D = getCanonicalDecl(D);
1472 auto It = Parent->LCVMap.find(D);
1473 if (It != Parent->LCVMap.end())
1474 return It->second;
1475 return {0, nullptr};
1476 }
1477
getParentLoopControlVariable(unsigned I) const1478 const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1479 const SharingMapTy *Parent = getSecondOnStackOrNull();
1480 assert(Parent && "Data-sharing attributes stack is empty");
1481 if (Parent->LCVMap.size() < I)
1482 return nullptr;
1483 for (const auto &Pair : Parent->LCVMap)
1484 if (Pair.second.first == I)
1485 return Pair.first;
1486 return nullptr;
1487 }
1488
addDSA(const ValueDecl * D,const Expr * E,OpenMPClauseKind A,DeclRefExpr * PrivateCopy,unsigned Modifier,bool AppliedToPointee)1489 void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1490 DeclRefExpr *PrivateCopy, unsigned Modifier,
1491 bool AppliedToPointee) {
1492 D = getCanonicalDecl(D);
1493 if (A == OMPC_threadprivate) {
1494 DSAInfo &Data = Threadprivates[D];
1495 Data.Attributes = A;
1496 Data.RefExpr.setPointer(E);
1497 Data.PrivateCopy = nullptr;
1498 Data.Modifier = Modifier;
1499 } else {
1500 DSAInfo &Data = getTopOfStack().SharingMap[D];
1501 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1502 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1503 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1504 (isLoopControlVariable(D).first && A == OMPC_private));
1505 Data.Modifier = Modifier;
1506 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1507 Data.RefExpr.setInt(/*IntVal=*/true);
1508 return;
1509 }
1510 const bool IsLastprivate =
1511 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1512 Data.Attributes = A;
1513 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1514 Data.PrivateCopy = PrivateCopy;
1515 Data.AppliedToPointee = AppliedToPointee;
1516 if (PrivateCopy) {
1517 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1518 Data.Modifier = Modifier;
1519 Data.Attributes = A;
1520 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1521 Data.PrivateCopy = nullptr;
1522 Data.AppliedToPointee = AppliedToPointee;
1523 }
1524 }
1525 }
1526
1527 /// 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)1528 static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
1529 StringRef Name, const AttrVec *Attrs = nullptr,
1530 DeclRefExpr *OrigRef = nullptr) {
1531 DeclContext *DC = SemaRef.CurContext;
1532 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1533 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
1534 auto *Decl =
1535 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
1536 if (Attrs) {
1537 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1538 I != E; ++I)
1539 Decl->addAttr(*I);
1540 }
1541 Decl->setImplicit();
1542 if (OrigRef) {
1543 Decl->addAttr(
1544 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1545 }
1546 return Decl;
1547 }
1548
buildDeclRefExpr(Sema & S,VarDecl * D,QualType Ty,SourceLocation Loc,bool RefersToCapture=false)1549 static DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty,
1550 SourceLocation Loc,
1551 bool RefersToCapture = false) {
1552 D->setReferenced();
1553 D->markUsed(S.Context);
1554 return DeclRefExpr::Create(S.getASTContext(), NestedNameSpecifierLoc(),
1555 SourceLocation(), D, RefersToCapture, Loc, Ty,
1556 VK_LValue);
1557 }
1558
addTaskgroupReductionData(const ValueDecl * D,SourceRange SR,BinaryOperatorKind BOK)1559 void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1560 BinaryOperatorKind BOK) {
1561 D = getCanonicalDecl(D);
1562 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1563 assert(
1564 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1565 "Additional reduction info may be specified only for reduction items.");
1566 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1567 assert(ReductionData.ReductionRange.isInvalid() &&
1568 (getTopOfStack().Directive == OMPD_taskgroup ||
1569 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1570 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1571 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1572 "Additional reduction info may be specified only once for reduction "
1573 "items.");
1574 ReductionData.set(BOK, SR);
1575 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1576 if (!TaskgroupReductionRef) {
1577 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1578 SemaRef.Context.VoidPtrTy, ".task_red.");
1579 TaskgroupReductionRef =
1580 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1581 }
1582 }
1583
addTaskgroupReductionData(const ValueDecl * D,SourceRange SR,const Expr * ReductionRef)1584 void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1585 const Expr *ReductionRef) {
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(ReductionRef, 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
getTopMostTaskgroupReductionData(const ValueDecl * D,SourceRange & SR,BinaryOperatorKind & BOK,Expr * & TaskgroupDescriptor) const1609 const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1610 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1611 Expr *&TaskgroupDescriptor) const {
1612 D = getCanonicalDecl(D);
1613 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1614 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1615 const DSAInfo &Data = I->SharingMap.lookup(D);
1616 if (Data.Attributes != OMPC_reduction ||
1617 Data.Modifier != OMPC_REDUCTION_task)
1618 continue;
1619 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1620 if (!ReductionData.ReductionOp ||
1621 ReductionData.ReductionOp.is<const Expr *>())
1622 return DSAVarData();
1623 SR = ReductionData.ReductionRange;
1624 BOK = ReductionData.ReductionOp.get<ReductionData::BOKPtrType>();
1625 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1626 "expression for the descriptor is not "
1627 "set.");
1628 TaskgroupDescriptor = I->TaskgroupReductionRef;
1629 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1630 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1631 /*AppliedToPointee=*/false);
1632 }
1633 return DSAVarData();
1634 }
1635
getTopMostTaskgroupReductionData(const ValueDecl * D,SourceRange & SR,const Expr * & ReductionRef,Expr * & TaskgroupDescriptor) const1636 const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1637 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1638 Expr *&TaskgroupDescriptor) const {
1639 D = getCanonicalDecl(D);
1640 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1641 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1642 const DSAInfo &Data = I->SharingMap.lookup(D);
1643 if (Data.Attributes != OMPC_reduction ||
1644 Data.Modifier != OMPC_REDUCTION_task)
1645 continue;
1646 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1647 if (!ReductionData.ReductionOp ||
1648 !ReductionData.ReductionOp.is<const Expr *>())
1649 return DSAVarData();
1650 SR = ReductionData.ReductionRange;
1651 ReductionRef = ReductionData.ReductionOp.get<const Expr *>();
1652 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1653 "expression for the descriptor is not "
1654 "set.");
1655 TaskgroupDescriptor = I->TaskgroupReductionRef;
1656 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1657 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1658 /*AppliedToPointee=*/false);
1659 }
1660 return DSAVarData();
1661 }
1662
isOpenMPLocal(VarDecl * D,const_iterator I) const1663 bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1664 D = D->getCanonicalDecl();
1665 for (const_iterator E = end(); I != E; ++I) {
1666 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1667 isOpenMPTargetExecutionDirective(I->Directive)) {
1668 if (I->CurScope) {
1669 Scope *TopScope = I->CurScope->getParent();
1670 Scope *CurScope = getCurScope();
1671 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1672 CurScope = CurScope->getParent();
1673 return CurScope != TopScope;
1674 }
1675 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1676 if (I->Context == DC)
1677 return true;
1678 return false;
1679 }
1680 }
1681 return false;
1682 }
1683
isConstNotMutableType(Sema & SemaRef,QualType Type,bool AcceptIfMutable=true,bool * IsClassType=nullptr)1684 static bool isConstNotMutableType(Sema &SemaRef, QualType Type,
1685 bool AcceptIfMutable = true,
1686 bool *IsClassType = nullptr) {
1687 ASTContext &Context = SemaRef.getASTContext();
1688 Type = Type.getNonReferenceType().getCanonicalType();
1689 bool IsConstant = Type.isConstant(Context);
1690 Type = Context.getBaseElementType(Type);
1691 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1692 ? Type->getAsCXXRecordDecl()
1693 : nullptr;
1694 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1695 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1696 RD = CTD->getTemplatedDecl();
1697 if (IsClassType)
1698 *IsClassType = RD;
1699 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1700 RD->hasDefinition() && RD->hasMutableFields());
1701 }
1702
rejectConstNotMutableType(Sema & SemaRef,const ValueDecl * D,QualType Type,OpenMPClauseKind CKind,SourceLocation ELoc,bool AcceptIfMutable=true,bool ListItemNotVar=false)1703 static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1704 QualType Type, OpenMPClauseKind CKind,
1705 SourceLocation ELoc,
1706 bool AcceptIfMutable = true,
1707 bool ListItemNotVar = false) {
1708 ASTContext &Context = SemaRef.getASTContext();
1709 bool IsClassType;
1710 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
1711 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1712 : IsClassType ? diag::err_omp_const_not_mutable_variable
1713 : diag::err_omp_const_variable;
1714 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseName(CKind);
1715 if (!ListItemNotVar && D) {
1716 const VarDecl *VD = dyn_cast<VarDecl>(D);
1717 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1718 VarDecl::DeclarationOnly;
1719 SemaRef.Diag(D->getLocation(),
1720 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1721 << D;
1722 }
1723 return true;
1724 }
1725 return false;
1726 }
1727
getTopDSA(ValueDecl * D,bool FromParent)1728 const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1729 bool FromParent) {
1730 D = getCanonicalDecl(D);
1731 DSAVarData DVar;
1732
1733 auto *VD = dyn_cast<VarDecl>(D);
1734 auto TI = Threadprivates.find(D);
1735 if (TI != Threadprivates.end()) {
1736 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1737 DVar.CKind = OMPC_threadprivate;
1738 DVar.Modifier = TI->getSecond().Modifier;
1739 return DVar;
1740 }
1741 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1742 DVar.RefExpr = buildDeclRefExpr(
1743 SemaRef, VD, D->getType().getNonReferenceType(),
1744 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1745 DVar.CKind = OMPC_threadprivate;
1746 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1747 return DVar;
1748 }
1749 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1750 // in a Construct, C/C++, predetermined, p.1]
1751 // Variables appearing in threadprivate directives are threadprivate.
1752 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1753 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1754 SemaRef.getLangOpts().OpenMPUseTLS &&
1755 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1756 (VD && VD->getStorageClass() == SC_Register &&
1757 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1758 DVar.RefExpr = buildDeclRefExpr(
1759 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1760 DVar.CKind = OMPC_threadprivate;
1761 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1762 return DVar;
1763 }
1764 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1765 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1766 !isLoopControlVariable(D).first) {
1767 const_iterator IterTarget =
1768 std::find_if(begin(), end(), [](const SharingMapTy &Data) {
1769 return isOpenMPTargetExecutionDirective(Data.Directive);
1770 });
1771 if (IterTarget != end()) {
1772 const_iterator ParentIterTarget = IterTarget + 1;
1773 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1774 if (isOpenMPLocal(VD, Iter)) {
1775 DVar.RefExpr =
1776 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1777 D->getLocation());
1778 DVar.CKind = OMPC_threadprivate;
1779 return DVar;
1780 }
1781 }
1782 if (!isClauseParsingMode() || IterTarget != begin()) {
1783 auto DSAIter = IterTarget->SharingMap.find(D);
1784 if (DSAIter != IterTarget->SharingMap.end() &&
1785 isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1786 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1787 DVar.CKind = OMPC_threadprivate;
1788 return DVar;
1789 }
1790 const_iterator End = end();
1791 if (!SemaRef.isOpenMPCapturedByRef(D,
1792 std::distance(ParentIterTarget, End),
1793 /*OpenMPCaptureLevel=*/0)) {
1794 DVar.RefExpr =
1795 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1796 IterTarget->ConstructLoc);
1797 DVar.CKind = OMPC_threadprivate;
1798 return DVar;
1799 }
1800 }
1801 }
1802 }
1803
1804 if (isStackEmpty())
1805 // Not in OpenMP execution region and top scope was already checked.
1806 return DVar;
1807
1808 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1809 // in a Construct, C/C++, predetermined, p.4]
1810 // Static data members are shared.
1811 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1812 // in a Construct, C/C++, predetermined, p.7]
1813 // Variables with static storage duration that are declared in a scope
1814 // inside the construct are shared.
1815 if (VD && VD->isStaticDataMember()) {
1816 // Check for explicitly specified attributes.
1817 const_iterator I = begin();
1818 const_iterator EndI = end();
1819 if (FromParent && I != EndI)
1820 ++I;
1821 if (I != EndI) {
1822 auto It = I->SharingMap.find(D);
1823 if (It != I->SharingMap.end()) {
1824 const DSAInfo &Data = It->getSecond();
1825 DVar.RefExpr = Data.RefExpr.getPointer();
1826 DVar.PrivateCopy = Data.PrivateCopy;
1827 DVar.CKind = Data.Attributes;
1828 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1829 DVar.DKind = I->Directive;
1830 DVar.Modifier = Data.Modifier;
1831 DVar.AppliedToPointee = Data.AppliedToPointee;
1832 return DVar;
1833 }
1834 }
1835
1836 DVar.CKind = OMPC_shared;
1837 return DVar;
1838 }
1839
1840 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1841 // The predetermined shared attribute for const-qualified types having no
1842 // mutable members was removed after OpenMP 3.1.
1843 if (SemaRef.LangOpts.OpenMP <= 31) {
1844 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1845 // in a Construct, C/C++, predetermined, p.6]
1846 // Variables with const qualified type having no mutable member are
1847 // shared.
1848 if (isConstNotMutableType(SemaRef, D->getType())) {
1849 // Variables with const-qualified type having no mutable member may be
1850 // listed in a firstprivate clause, even if they are static data members.
1851 DSAVarData DVarTemp = hasInnermostDSA(
1852 D,
1853 [](OpenMPClauseKind C, bool) {
1854 return C == OMPC_firstprivate || C == OMPC_shared;
1855 },
1856 MatchesAlways, FromParent);
1857 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1858 return DVarTemp;
1859
1860 DVar.CKind = OMPC_shared;
1861 return DVar;
1862 }
1863 }
1864
1865 // Explicitly specified attributes and local variables with predetermined
1866 // attributes.
1867 const_iterator I = begin();
1868 const_iterator EndI = end();
1869 if (FromParent && I != EndI)
1870 ++I;
1871 if (I == EndI)
1872 return DVar;
1873 auto It = I->SharingMap.find(D);
1874 if (It != I->SharingMap.end()) {
1875 const DSAInfo &Data = It->getSecond();
1876 DVar.RefExpr = Data.RefExpr.getPointer();
1877 DVar.PrivateCopy = Data.PrivateCopy;
1878 DVar.CKind = Data.Attributes;
1879 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1880 DVar.DKind = I->Directive;
1881 DVar.Modifier = Data.Modifier;
1882 DVar.AppliedToPointee = Data.AppliedToPointee;
1883 }
1884
1885 return DVar;
1886 }
1887
getImplicitDSA(ValueDecl * D,bool FromParent) const1888 const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1889 bool FromParent) const {
1890 if (isStackEmpty()) {
1891 const_iterator I;
1892 return getDSA(I, D);
1893 }
1894 D = getCanonicalDecl(D);
1895 const_iterator StartI = begin();
1896 const_iterator EndI = end();
1897 if (FromParent && StartI != EndI)
1898 ++StartI;
1899 return getDSA(StartI, D);
1900 }
1901
getImplicitDSA(ValueDecl * D,unsigned Level) const1902 const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1903 unsigned Level) const {
1904 if (getStackSize() <= Level)
1905 return DSAVarData();
1906 D = getCanonicalDecl(D);
1907 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1908 return getDSA(StartI, D);
1909 }
1910
1911 const DSAStackTy::DSAVarData
hasDSA(ValueDecl * D,const llvm::function_ref<bool (OpenMPClauseKind,bool,DefaultDataSharingAttributes)> CPred,const llvm::function_ref<bool (OpenMPDirectiveKind)> DPred,bool FromParent) const1912 DSAStackTy::hasDSA(ValueDecl *D,
1913 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1914 DefaultDataSharingAttributes)>
1915 CPred,
1916 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1917 bool FromParent) const {
1918 if (isStackEmpty())
1919 return {};
1920 D = getCanonicalDecl(D);
1921 const_iterator I = begin();
1922 const_iterator EndI = end();
1923 if (FromParent && I != EndI)
1924 ++I;
1925 for (; I != EndI; ++I) {
1926 if (!DPred(I->Directive) &&
1927 !isImplicitOrExplicitTaskingRegion(I->Directive))
1928 continue;
1929 const_iterator NewI = I;
1930 DSAVarData DVar = getDSA(NewI, D);
1931 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1932 return DVar;
1933 }
1934 return {};
1935 }
1936
hasInnermostDSA(ValueDecl * D,const llvm::function_ref<bool (OpenMPClauseKind,bool)> CPred,const llvm::function_ref<bool (OpenMPDirectiveKind)> DPred,bool FromParent) const1937 const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1938 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1939 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1940 bool FromParent) const {
1941 if (isStackEmpty())
1942 return {};
1943 D = getCanonicalDecl(D);
1944 const_iterator StartI = begin();
1945 const_iterator EndI = end();
1946 if (FromParent && StartI != EndI)
1947 ++StartI;
1948 if (StartI == EndI || !DPred(StartI->Directive))
1949 return {};
1950 const_iterator NewI = StartI;
1951 DSAVarData DVar = getDSA(NewI, D);
1952 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1953 ? DVar
1954 : DSAVarData();
1955 }
1956
hasExplicitDSA(const ValueDecl * D,const llvm::function_ref<bool (OpenMPClauseKind,bool)> CPred,unsigned Level,bool NotLastprivate) const1957 bool DSAStackTy::hasExplicitDSA(
1958 const ValueDecl *D,
1959 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1960 unsigned Level, bool NotLastprivate) const {
1961 if (getStackSize() <= Level)
1962 return false;
1963 D = getCanonicalDecl(D);
1964 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1965 auto I = StackElem.SharingMap.find(D);
1966 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1967 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1968 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1969 return true;
1970 // Check predetermined rules for the loop control variables.
1971 auto LI = StackElem.LCVMap.find(D);
1972 if (LI != StackElem.LCVMap.end())
1973 return CPred(OMPC_private, /*AppliedToPointee=*/false);
1974 return false;
1975 }
1976
hasExplicitDirective(const llvm::function_ref<bool (OpenMPDirectiveKind)> DPred,unsigned Level) const1977 bool DSAStackTy::hasExplicitDirective(
1978 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1979 unsigned Level) const {
1980 if (getStackSize() <= Level)
1981 return false;
1982 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1983 return DPred(StackElem.Directive);
1984 }
1985
hasDirective(const llvm::function_ref<bool (OpenMPDirectiveKind,const DeclarationNameInfo &,SourceLocation)> DPred,bool FromParent) const1986 bool DSAStackTy::hasDirective(
1987 const llvm::function_ref<bool(OpenMPDirectiveKind,
1988 const DeclarationNameInfo &, SourceLocation)>
1989 DPred,
1990 bool FromParent) const {
1991 // We look only in the enclosing region.
1992 size_t Skip = FromParent ? 2 : 1;
1993 for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
1994 I != E; ++I) {
1995 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
1996 return true;
1997 }
1998 return false;
1999 }
2000
InitDataSharingAttributesStack()2001 void Sema::InitDataSharingAttributesStack() {
2002 VarDataSharingAttributesStack = new DSAStackTy(*this);
2003 }
2004
2005 #define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2006
pushOpenMPFunctionRegion()2007 void Sema::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2008
popOpenMPFunctionRegion(const FunctionScopeInfo * OldFSI)2009 void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2010 DSAStack->popFunction(OldFSI);
2011 }
2012
isOpenMPDeviceDelayedContext(Sema & S)2013 static bool isOpenMPDeviceDelayedContext(Sema &S) {
2014 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsDevice &&
2015 "Expected OpenMP device compilation.");
2016 return !S.isInOpenMPTargetExecutionDirective();
2017 }
2018
2019 namespace {
2020 /// Status of the function emission on the host/device.
2021 enum class FunctionEmissionStatus {
2022 Emitted,
2023 Discarded,
2024 Unknown,
2025 };
2026 } // anonymous namespace
2027
diagIfOpenMPDeviceCode(SourceLocation Loc,unsigned DiagID,FunctionDecl * FD)2028 Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPDeviceCode(SourceLocation Loc,
2029 unsigned DiagID,
2030 FunctionDecl *FD) {
2031 assert(LangOpts.OpenMP && LangOpts.OpenMPIsDevice &&
2032 "Expected OpenMP device compilation.");
2033
2034 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2035 if (FD) {
2036 FunctionEmissionStatus FES = getEmissionStatus(FD);
2037 switch (FES) {
2038 case FunctionEmissionStatus::Emitted:
2039 Kind = SemaDiagnosticBuilder::K_Immediate;
2040 break;
2041 case FunctionEmissionStatus::Unknown:
2042 // TODO: We should always delay diagnostics here in case a target
2043 // region is in a function we do not emit. However, as the
2044 // current diagnostics are associated with the function containing
2045 // the target region and we do not emit that one, we would miss out
2046 // on diagnostics for the target region itself. We need to anchor
2047 // the diagnostics with the new generated function *or* ensure we
2048 // emit diagnostics associated with the surrounding function.
2049 Kind = isOpenMPDeviceDelayedContext(*this)
2050 ? SemaDiagnosticBuilder::K_Deferred
2051 : SemaDiagnosticBuilder::K_Immediate;
2052 break;
2053 case FunctionEmissionStatus::TemplateDiscarded:
2054 case FunctionEmissionStatus::OMPDiscarded:
2055 Kind = SemaDiagnosticBuilder::K_Nop;
2056 break;
2057 case FunctionEmissionStatus::CUDADiscarded:
2058 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2059 break;
2060 }
2061 }
2062
2063 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this);
2064 }
2065
diagIfOpenMPHostCode(SourceLocation Loc,unsigned DiagID,FunctionDecl * FD)2066 Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPHostCode(SourceLocation Loc,
2067 unsigned DiagID,
2068 FunctionDecl *FD) {
2069 assert(LangOpts.OpenMP && !LangOpts.OpenMPIsDevice &&
2070 "Expected OpenMP host compilation.");
2071
2072 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2073 if (FD) {
2074 FunctionEmissionStatus FES = getEmissionStatus(FD);
2075 switch (FES) {
2076 case FunctionEmissionStatus::Emitted:
2077 Kind = SemaDiagnosticBuilder::K_Immediate;
2078 break;
2079 case FunctionEmissionStatus::Unknown:
2080 Kind = SemaDiagnosticBuilder::K_Deferred;
2081 break;
2082 case FunctionEmissionStatus::TemplateDiscarded:
2083 case FunctionEmissionStatus::OMPDiscarded:
2084 case FunctionEmissionStatus::CUDADiscarded:
2085 Kind = SemaDiagnosticBuilder::K_Nop;
2086 break;
2087 }
2088 }
2089
2090 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this);
2091 }
2092
2093 static OpenMPDefaultmapClauseKind
getVariableCategoryFromDecl(const LangOptions & LO,const ValueDecl * VD)2094 getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD) {
2095 if (LO.OpenMP <= 45) {
2096 if (VD->getType().getNonReferenceType()->isScalarType())
2097 return OMPC_DEFAULTMAP_scalar;
2098 return OMPC_DEFAULTMAP_aggregate;
2099 }
2100 if (VD->getType().getNonReferenceType()->isAnyPointerType())
2101 return OMPC_DEFAULTMAP_pointer;
2102 if (VD->getType().getNonReferenceType()->isScalarType())
2103 return OMPC_DEFAULTMAP_scalar;
2104 return OMPC_DEFAULTMAP_aggregate;
2105 }
2106
isOpenMPCapturedByRef(const ValueDecl * D,unsigned Level,unsigned OpenMPCaptureLevel) const2107 bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2108 unsigned OpenMPCaptureLevel) const {
2109 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2110
2111 ASTContext &Ctx = getASTContext();
2112 bool IsByRef = true;
2113
2114 // Find the directive that is associated with the provided scope.
2115 D = cast<ValueDecl>(D->getCanonicalDecl());
2116 QualType Ty = D->getType();
2117
2118 bool IsVariableUsedInMapClause = false;
2119 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2120 // This table summarizes how a given variable should be passed to the device
2121 // given its type and the clauses where it appears. This table is based on
2122 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2123 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2124 //
2125 // =========================================================================
2126 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2127 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2128 // =========================================================================
2129 // | scl | | | | - | | bycopy|
2130 // | scl | | - | x | - | - | bycopy|
2131 // | scl | | x | - | - | - | null |
2132 // | scl | x | | | - | | byref |
2133 // | scl | x | - | x | - | - | bycopy|
2134 // | scl | x | x | - | - | - | null |
2135 // | scl | | - | - | - | x | byref |
2136 // | scl | x | - | - | - | x | byref |
2137 //
2138 // | agg | n.a. | | | - | | byref |
2139 // | agg | n.a. | - | x | - | - | byref |
2140 // | agg | n.a. | x | - | - | - | null |
2141 // | agg | n.a. | - | - | - | x | byref |
2142 // | agg | n.a. | - | - | - | x[] | byref |
2143 //
2144 // | ptr | n.a. | | | - | | bycopy|
2145 // | ptr | n.a. | - | x | - | - | bycopy|
2146 // | ptr | n.a. | x | - | - | - | null |
2147 // | ptr | n.a. | - | - | - | x | byref |
2148 // | ptr | n.a. | - | - | - | x[] | bycopy|
2149 // | ptr | n.a. | - | - | x | | bycopy|
2150 // | ptr | n.a. | - | - | x | x | bycopy|
2151 // | ptr | n.a. | - | - | x | x[] | bycopy|
2152 // =========================================================================
2153 // Legend:
2154 // scl - scalar
2155 // ptr - pointer
2156 // agg - aggregate
2157 // x - applies
2158 // - - invalid in this combination
2159 // [] - mapped with an array section
2160 // byref - should be mapped by reference
2161 // byval - should be mapped by value
2162 // null - initialize a local variable to null on the device
2163 //
2164 // Observations:
2165 // - All scalar declarations that show up in a map clause have to be passed
2166 // by reference, because they may have been mapped in the enclosing data
2167 // environment.
2168 // - If the scalar value does not fit the size of uintptr, it has to be
2169 // passed by reference, regardless the result in the table above.
2170 // - For pointers mapped by value that have either an implicit map or an
2171 // array section, the runtime library may pass the NULL value to the
2172 // device instead of the value passed to it by the compiler.
2173
2174 if (Ty->isReferenceType())
2175 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2176
2177 // Locate map clauses and see if the variable being captured is referred to
2178 // in any of those clauses. Here we only care about variables, not fields,
2179 // because fields are part of aggregates.
2180 bool IsVariableAssociatedWithSection = false;
2181
2182 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2183 D, Level,
2184 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2185 D](OMPClauseMappableExprCommon::MappableExprComponentListRef
2186 MapExprComponents,
2187 OpenMPClauseKind WhereFoundClauseKind) {
2188 // Both map and has_device_addr clauses information influences how a
2189 // variable is captured. E.g. is_device_ptr does not require changing
2190 // the default behavior.
2191 if (WhereFoundClauseKind != OMPC_map &&
2192 WhereFoundClauseKind != OMPC_has_device_addr)
2193 return false;
2194
2195 auto EI = MapExprComponents.rbegin();
2196 auto EE = MapExprComponents.rend();
2197
2198 assert(EI != EE && "Invalid map expression!");
2199
2200 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2201 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2202
2203 ++EI;
2204 if (EI == EE)
2205 return false;
2206
2207 if (isa<ArraySubscriptExpr>(EI->getAssociatedExpression()) ||
2208 isa<OMPArraySectionExpr>(EI->getAssociatedExpression()) ||
2209 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2210 isa<OMPArrayShapingExpr>(EI->getAssociatedExpression())) {
2211 IsVariableAssociatedWithSection = true;
2212 // There is nothing more we need to know about this variable.
2213 return true;
2214 }
2215
2216 // Keep looking for more map info.
2217 return false;
2218 });
2219
2220 if (IsVariableUsedInMapClause) {
2221 // If variable is identified in a map clause it is always captured by
2222 // reference except if it is a pointer that is dereferenced somehow.
2223 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2224 } else {
2225 // By default, all the data that has a scalar type is mapped by copy
2226 // (except for reduction variables).
2227 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2228 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2229 !Ty->isAnyPointerType()) ||
2230 !Ty->isScalarType() ||
2231 DSAStack->isDefaultmapCapturedByRef(
2232 Level, getVariableCategoryFromDecl(LangOpts, D)) ||
2233 DSAStack->hasExplicitDSA(
2234 D,
2235 [](OpenMPClauseKind K, bool AppliedToPointee) {
2236 return K == OMPC_reduction && !AppliedToPointee;
2237 },
2238 Level);
2239 }
2240 }
2241
2242 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2243 IsByRef =
2244 ((IsVariableUsedInMapClause &&
2245 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2246 OMPD_target) ||
2247 !(DSAStack->hasExplicitDSA(
2248 D,
2249 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2250 return K == OMPC_firstprivate ||
2251 (K == OMPC_reduction && AppliedToPointee);
2252 },
2253 Level, /*NotLastprivate=*/true) ||
2254 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2255 // If the variable is artificial and must be captured by value - try to
2256 // capture by value.
2257 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2258 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2259 // If the variable is implicitly firstprivate and scalar - capture by
2260 // copy
2261 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2262 DSAStack->getDefaultDSA() == DSA_private) &&
2263 !DSAStack->hasExplicitDSA(
2264 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2265 Level) &&
2266 !DSAStack->isLoopControlVariable(D, Level).first);
2267 }
2268
2269 // When passing data by copy, we need to make sure it fits the uintptr size
2270 // and alignment, because the runtime library only deals with uintptr types.
2271 // If it does not fit the uintptr size, we need to pass the data by reference
2272 // instead.
2273 if (!IsByRef &&
2274 (Ctx.getTypeSizeInChars(Ty) >
2275 Ctx.getTypeSizeInChars(Ctx.getUIntPtrType()) ||
2276 Ctx.getDeclAlign(D) > Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2277 IsByRef = true;
2278 }
2279
2280 return IsByRef;
2281 }
2282
getOpenMPNestingLevel() const2283 unsigned Sema::getOpenMPNestingLevel() const {
2284 assert(getLangOpts().OpenMP);
2285 return DSAStack->getNestingLevel();
2286 }
2287
isInOpenMPTaskUntiedContext() const2288 bool Sema::isInOpenMPTaskUntiedContext() const {
2289 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2290 DSAStack->isUntiedRegion();
2291 }
2292
isInOpenMPTargetExecutionDirective() const2293 bool Sema::isInOpenMPTargetExecutionDirective() const {
2294 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2295 !DSAStack->isClauseParsingMode()) ||
2296 DSAStack->hasDirective(
2297 [](OpenMPDirectiveKind K, const DeclarationNameInfo &,
2298 SourceLocation) -> bool {
2299 return isOpenMPTargetExecutionDirective(K);
2300 },
2301 false);
2302 }
2303
isOpenMPRebuildMemberExpr(ValueDecl * D)2304 bool Sema::isOpenMPRebuildMemberExpr(ValueDecl *D) {
2305 // Only rebuild for Field.
2306 if (!dyn_cast<FieldDecl>(D))
2307 return false;
2308 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2309 D,
2310 [](OpenMPClauseKind C, bool AppliedToPointee,
2311 DefaultDataSharingAttributes DefaultAttr) {
2312 return isOpenMPPrivate(C) && !AppliedToPointee &&
2313 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2314 },
2315 [](OpenMPDirectiveKind) { return true; },
2316 DSAStack->isClauseParsingMode());
2317 if (DVarPrivate.CKind != OMPC_unknown)
2318 return true;
2319 return false;
2320 }
2321
2322 static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
2323 Expr *CaptureExpr, bool WithInit,
2324 DeclContext *CurContext,
2325 bool AsExpression);
2326
isOpenMPCapturedDecl(ValueDecl * D,bool CheckScopeInfo,unsigned StopAt)2327 VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
2328 unsigned StopAt) {
2329 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2330 D = getCanonicalDecl(D);
2331
2332 auto *VD = dyn_cast<VarDecl>(D);
2333 // Do not capture constexpr variables.
2334 if (VD && VD->isConstexpr())
2335 return nullptr;
2336
2337 // If we want to determine whether the variable should be captured from the
2338 // perspective of the current capturing scope, and we've already left all the
2339 // capturing scopes of the top directive on the stack, check from the
2340 // perspective of its parent directive (if any) instead.
2341 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2342 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2343
2344 // If we are attempting to capture a global variable in a directive with
2345 // 'target' we return true so that this global is also mapped to the device.
2346 //
2347 if (VD && !VD->hasLocalStorage() &&
2348 (getCurCapturedRegion() || getCurBlock() || getCurLambda())) {
2349 if (isInOpenMPTargetExecutionDirective()) {
2350 DSAStackTy::DSAVarData DVarTop =
2351 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2352 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2353 return VD;
2354 // If the declaration is enclosed in a 'declare target' directive,
2355 // then it should not be captured.
2356 //
2357 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2358 return nullptr;
2359 CapturedRegionScopeInfo *CSI = nullptr;
2360 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2361 llvm::reverse(FunctionScopes),
2362 CheckScopeInfo ? (FunctionScopes.size() - (StopAt + 1)) : 0)) {
2363 if (!isa<CapturingScopeInfo>(FSI))
2364 return nullptr;
2365 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2366 if (RSI->CapRegionKind == CR_OpenMP) {
2367 CSI = RSI;
2368 break;
2369 }
2370 }
2371 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2372 SmallVector<OpenMPDirectiveKind, 4> Regions;
2373 getOpenMPCaptureRegions(Regions,
2374 DSAStack->getDirective(CSI->OpenMPLevel));
2375 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2376 return VD;
2377 }
2378 if (isInOpenMPDeclareTargetContext()) {
2379 // Try to mark variable as declare target if it is used in capturing
2380 // regions.
2381 if (LangOpts.OpenMP <= 45 &&
2382 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2383 checkDeclIsAllowedInOpenMPTarget(nullptr, VD);
2384 return nullptr;
2385 }
2386 }
2387
2388 if (CheckScopeInfo) {
2389 bool OpenMPFound = false;
2390 for (unsigned I = StopAt + 1; I > 0; --I) {
2391 FunctionScopeInfo *FSI = FunctionScopes[I - 1];
2392 if (!isa<CapturingScopeInfo>(FSI))
2393 return nullptr;
2394 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2395 if (RSI->CapRegionKind == CR_OpenMP) {
2396 OpenMPFound = true;
2397 break;
2398 }
2399 }
2400 if (!OpenMPFound)
2401 return nullptr;
2402 }
2403
2404 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2405 (!DSAStack->isClauseParsingMode() ||
2406 DSAStack->getParentDirective() != OMPD_unknown)) {
2407 auto &&Info = DSAStack->isLoopControlVariable(D);
2408 if (Info.first ||
2409 (VD && VD->hasLocalStorage() &&
2410 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2411 (VD && DSAStack->isForceVarCapturing()))
2412 return VD ? VD : Info.second;
2413 DSAStackTy::DSAVarData DVarTop =
2414 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2415 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2416 (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee))
2417 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2418 // Threadprivate variables must not be captured.
2419 if (isOpenMPThreadPrivate(DVarTop.CKind))
2420 return nullptr;
2421 // The variable is not private or it is the variable in the directive with
2422 // default(none) clause and not used in any clause.
2423 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2424 D,
2425 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2426 return isOpenMPPrivate(C) && !AppliedToPointee;
2427 },
2428 [](OpenMPDirectiveKind) { return true; },
2429 DSAStack->isClauseParsingMode());
2430 // Global shared must not be captured.
2431 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2432 ((DSAStack->getDefaultDSA() != DSA_none &&
2433 DSAStack->getDefaultDSA() != DSA_private &&
2434 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2435 DVarTop.CKind == OMPC_shared))
2436 return nullptr;
2437 auto *FD = dyn_cast<FieldDecl>(D);
2438 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2439 !DVarPrivate.PrivateCopy) {
2440 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2441 D,
2442 [](OpenMPClauseKind C, bool AppliedToPointee,
2443 DefaultDataSharingAttributes DefaultAttr) {
2444 return isOpenMPPrivate(C) && !AppliedToPointee &&
2445 (DefaultAttr == DSA_firstprivate ||
2446 DefaultAttr == DSA_private);
2447 },
2448 [](OpenMPDirectiveKind) { return true; },
2449 DSAStack->isClauseParsingMode());
2450 if (DVarPrivate.CKind == OMPC_unknown)
2451 return nullptr;
2452
2453 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2454 if (VD)
2455 return VD;
2456 if (getCurrentThisType().isNull())
2457 return nullptr;
2458 Expr *ThisExpr = BuildCXXThisExpr(SourceLocation(), getCurrentThisType(),
2459 /*IsImplicit=*/true);
2460 const CXXScopeSpec CS = CXXScopeSpec();
2461 Expr *ME = BuildMemberExpr(ThisExpr, /*IsArrow=*/true, SourceLocation(),
2462 NestedNameSpecifierLoc(), SourceLocation(), FD,
2463 DeclAccessPair::make(FD, FD->getAccess()),
2464 /*HadMultipleCandidates=*/false,
2465 DeclarationNameInfo(), FD->getType(),
2466 VK_LValue, OK_Ordinary);
2467 OMPCapturedExprDecl *CD = buildCaptureDecl(
2468 *this, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2469 CurContext->getParent(), /*AsExpression=*/false);
2470 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2471 *this, CD, CD->getType().getNonReferenceType(), SourceLocation());
2472 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2473 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2474 return VD;
2475 }
2476 if (DVarPrivate.CKind != OMPC_unknown ||
2477 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2478 DSAStack->getDefaultDSA() == DSA_private ||
2479 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2480 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2481 }
2482 return nullptr;
2483 }
2484
adjustOpenMPTargetScopeIndex(unsigned & FunctionScopesIndex,unsigned Level) const2485 void Sema::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2486 unsigned Level) const {
2487 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2488 }
2489
startOpenMPLoop()2490 void Sema::startOpenMPLoop() {
2491 assert(LangOpts.OpenMP && "OpenMP must be enabled.");
2492 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2493 DSAStack->loopInit();
2494 }
2495
startOpenMPCXXRangeFor()2496 void Sema::startOpenMPCXXRangeFor() {
2497 assert(LangOpts.OpenMP && "OpenMP must be enabled.");
2498 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2499 DSAStack->resetPossibleLoopCounter();
2500 DSAStack->loopStart();
2501 }
2502 }
2503
isOpenMPPrivateDecl(ValueDecl * D,unsigned Level,unsigned CapLevel) const2504 OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
2505 unsigned CapLevel) const {
2506 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2507 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2508 (!DSAStack->isClauseParsingMode() ||
2509 DSAStack->getParentDirective() != OMPD_unknown)) {
2510 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2511 D,
2512 [](OpenMPClauseKind C, bool AppliedToPointee,
2513 DefaultDataSharingAttributes DefaultAttr) {
2514 return isOpenMPPrivate(C) && !AppliedToPointee &&
2515 DefaultAttr == DSA_private;
2516 },
2517 [](OpenMPDirectiveKind) { return true; },
2518 DSAStack->isClauseParsingMode());
2519 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2520 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2521 !DSAStack->isLoopControlVariable(D).first)
2522 return OMPC_private;
2523 }
2524 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2525 bool IsTriviallyCopyable =
2526 D->getType().getNonReferenceType().isTriviallyCopyableType(Context) &&
2527 !D->getType()
2528 .getNonReferenceType()
2529 .getCanonicalType()
2530 ->getAsCXXRecordDecl();
2531 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2532 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
2533 getOpenMPCaptureRegions(CaptureRegions, DKind);
2534 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2535 (IsTriviallyCopyable ||
2536 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2537 if (DSAStack->hasExplicitDSA(
2538 D,
2539 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2540 Level, /*NotLastprivate=*/true))
2541 return OMPC_firstprivate;
2542 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2543 if (DVar.CKind != OMPC_shared &&
2544 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2545 DSAStack->addImplicitTaskFirstprivate(Level, D);
2546 return OMPC_firstprivate;
2547 }
2548 }
2549 }
2550 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2551 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2552 DSAStack->resetPossibleLoopCounter(D);
2553 DSAStack->loopStart();
2554 return OMPC_private;
2555 }
2556 if ((DSAStack->getPossiblyLoopCunter() == D->getCanonicalDecl() ||
2557 DSAStack->isLoopControlVariable(D).first) &&
2558 !DSAStack->hasExplicitDSA(
2559 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2560 Level) &&
2561 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2562 return OMPC_private;
2563 }
2564 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2565 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2566 DSAStack->isForceVarCapturing() &&
2567 !DSAStack->hasExplicitDSA(
2568 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2569 Level))
2570 return OMPC_private;
2571 }
2572 // User-defined allocators are private since they must be defined in the
2573 // context of target region.
2574 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2575 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2576 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2577 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2578 return OMPC_private;
2579 return (DSAStack->hasExplicitDSA(
2580 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2581 Level) ||
2582 (DSAStack->isClauseParsingMode() &&
2583 DSAStack->getClauseParsingMode() == OMPC_private) ||
2584 // Consider taskgroup reduction descriptor variable a private
2585 // to avoid possible capture in the region.
2586 (DSAStack->hasExplicitDirective(
2587 [](OpenMPDirectiveKind K) {
2588 return K == OMPD_taskgroup ||
2589 ((isOpenMPParallelDirective(K) ||
2590 isOpenMPWorksharingDirective(K)) &&
2591 !isOpenMPSimdDirective(K));
2592 },
2593 Level) &&
2594 DSAStack->isTaskgroupReductionRef(D, Level)))
2595 ? OMPC_private
2596 : OMPC_unknown;
2597 }
2598
setOpenMPCaptureKind(FieldDecl * FD,const ValueDecl * D,unsigned Level)2599 void Sema::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D,
2600 unsigned Level) {
2601 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2602 D = getCanonicalDecl(D);
2603 OpenMPClauseKind OMPC = OMPC_unknown;
2604 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2605 const unsigned NewLevel = I - 1;
2606 if (DSAStack->hasExplicitDSA(
2607 D,
2608 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2609 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2610 OMPC = K;
2611 return true;
2612 }
2613 return false;
2614 },
2615 NewLevel))
2616 break;
2617 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2618 D, NewLevel,
2619 [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
2620 OpenMPClauseKind) { return true; })) {
2621 OMPC = OMPC_map;
2622 break;
2623 }
2624 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2625 NewLevel)) {
2626 OMPC = OMPC_map;
2627 if (DSAStack->mustBeFirstprivateAtLevel(
2628 NewLevel, getVariableCategoryFromDecl(LangOpts, D)))
2629 OMPC = OMPC_firstprivate;
2630 break;
2631 }
2632 }
2633 if (OMPC != OMPC_unknown)
2634 FD->addAttr(OMPCaptureKindAttr::CreateImplicit(Context, unsigned(OMPC)));
2635 }
2636
isOpenMPTargetCapturedDecl(const ValueDecl * D,unsigned Level,unsigned CaptureLevel) const2637 bool Sema::isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level,
2638 unsigned CaptureLevel) const {
2639 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2640 // Return true if the current level is no longer enclosed in a target region.
2641
2642 SmallVector<OpenMPDirectiveKind, 4> Regions;
2643 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2644 const auto *VD = dyn_cast<VarDecl>(D);
2645 return VD && !VD->hasLocalStorage() &&
2646 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2647 Level) &&
2648 Regions[CaptureLevel] != OMPD_task;
2649 }
2650
isOpenMPGlobalCapturedDecl(ValueDecl * D,unsigned Level,unsigned CaptureLevel) const2651 bool Sema::isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level,
2652 unsigned CaptureLevel) const {
2653 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2654 // Return true if the current level is no longer enclosed in a target region.
2655
2656 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2657 if (!VD->hasLocalStorage()) {
2658 if (isInOpenMPTargetExecutionDirective())
2659 return true;
2660 DSAStackTy::DSAVarData TopDVar =
2661 DSAStack->getTopDSA(D, /*FromParent=*/false);
2662 unsigned NumLevels =
2663 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2664 if (Level == 0)
2665 // non-file scope static variale with default(firstprivate)
2666 // should be gloabal captured.
2667 return (NumLevels == CaptureLevel + 1 &&
2668 (TopDVar.CKind != OMPC_shared ||
2669 DSAStack->getDefaultDSA() == DSA_firstprivate));
2670 do {
2671 --Level;
2672 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2673 if (DVar.CKind != OMPC_shared)
2674 return true;
2675 } while (Level > 0);
2676 }
2677 }
2678 return true;
2679 }
2680
DestroyDataSharingAttributesStack()2681 void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; }
2682
ActOnOpenMPBeginDeclareVariant(SourceLocation Loc,OMPTraitInfo & TI)2683 void Sema::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc,
2684 OMPTraitInfo &TI) {
2685 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2686 }
2687
ActOnOpenMPEndDeclareVariant()2688 void Sema::ActOnOpenMPEndDeclareVariant() {
2689 assert(isInOpenMPDeclareVariantScope() &&
2690 "Not in OpenMP declare variant scope!");
2691
2692 OMPDeclareVariantScopes.pop_back();
2693 }
2694
finalizeOpenMPDelayedAnalysis(const FunctionDecl * Caller,const FunctionDecl * Callee,SourceLocation Loc)2695 void Sema::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,
2696 const FunctionDecl *Callee,
2697 SourceLocation Loc) {
2698 assert(LangOpts.OpenMP && "Expected OpenMP compilation mode.");
2699 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2700 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2701 // Ignore host functions during device analyzis.
2702 if (LangOpts.OpenMPIsDevice &&
2703 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2704 return;
2705 // Ignore nohost functions during host analyzis.
2706 if (!LangOpts.OpenMPIsDevice && DevTy &&
2707 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2708 return;
2709 const FunctionDecl *FD = Callee->getMostRecentDecl();
2710 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2711 if (LangOpts.OpenMPIsDevice && DevTy &&
2712 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2713 // Diagnose host function called during device codegen.
2714 StringRef HostDevTy =
2715 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2716 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2717 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2718 diag::note_omp_marked_device_type_here)
2719 << HostDevTy;
2720 return;
2721 }
2722 if (!LangOpts.OpenMPIsDevice && !LangOpts.OpenMPOffloadMandatory && DevTy &&
2723 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2724 // In OpenMP 5.2 or later, if the function has a host variant then allow
2725 // that to be called instead
2726 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2727 for (OMPDeclareVariantAttr *A :
2728 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2729 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2730 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2731 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2732 OMPDeclareTargetDeclAttr::getDeviceType(
2733 VariantFD->getMostRecentDecl());
2734 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2735 return true;
2736 }
2737 return false;
2738 };
2739 if (getLangOpts().OpenMP >= 52 &&
2740 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2741 return;
2742 // Diagnose nohost function called during host codegen.
2743 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2744 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2745 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2746 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2747 diag::note_omp_marked_device_type_here)
2748 << NoHostDevTy;
2749 }
2750 }
2751
StartOpenMPDSABlock(OpenMPDirectiveKind DKind,const DeclarationNameInfo & DirName,Scope * CurScope,SourceLocation Loc)2752 void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
2753 const DeclarationNameInfo &DirName,
2754 Scope *CurScope, SourceLocation Loc) {
2755 DSAStack->push(DKind, DirName, CurScope, Loc);
2756 PushExpressionEvaluationContext(
2757 ExpressionEvaluationContext::PotentiallyEvaluated);
2758 }
2759
StartOpenMPClause(OpenMPClauseKind K)2760 void Sema::StartOpenMPClause(OpenMPClauseKind K) {
2761 DSAStack->setClauseParsingMode(K);
2762 }
2763
EndOpenMPClause()2764 void Sema::EndOpenMPClause() {
2765 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2766 CleanupVarDeclMarking();
2767 }
2768
2769 static std::pair<ValueDecl *, bool>
2770 getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2771 SourceRange &ERange, bool AllowArraySection = false,
2772 StringRef DiagType = "");
2773
2774 /// Check consistency of the reduction clauses.
checkReductionClauses(Sema & S,DSAStackTy * Stack,ArrayRef<OMPClause * > Clauses)2775 static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2776 ArrayRef<OMPClause *> Clauses) {
2777 bool InscanFound = false;
2778 SourceLocation InscanLoc;
2779 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2780 // A reduction clause without the inscan reduction-modifier may not appear on
2781 // a construct on which a reduction clause with the inscan reduction-modifier
2782 // appears.
2783 for (OMPClause *C : Clauses) {
2784 if (C->getClauseKind() != OMPC_reduction)
2785 continue;
2786 auto *RC = cast<OMPReductionClause>(C);
2787 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2788 InscanFound = true;
2789 InscanLoc = RC->getModifierLoc();
2790 continue;
2791 }
2792 if (RC->getModifier() == OMPC_REDUCTION_task) {
2793 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2794 // A reduction clause with the task reduction-modifier may only appear on
2795 // a parallel construct, a worksharing construct or a combined or
2796 // composite construct for which any of the aforementioned constructs is a
2797 // constituent construct and simd or loop are not constituent constructs.
2798 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2799 if (!(isOpenMPParallelDirective(CurDir) ||
2800 isOpenMPWorksharingDirective(CurDir)) ||
2801 isOpenMPSimdDirective(CurDir))
2802 S.Diag(RC->getModifierLoc(),
2803 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2804 continue;
2805 }
2806 }
2807 if (InscanFound) {
2808 for (OMPClause *C : Clauses) {
2809 if (C->getClauseKind() != OMPC_reduction)
2810 continue;
2811 auto *RC = cast<OMPReductionClause>(C);
2812 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2813 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2814 ? RC->getBeginLoc()
2815 : RC->getModifierLoc(),
2816 diag::err_omp_inscan_reduction_expected);
2817 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2818 continue;
2819 }
2820 for (Expr *Ref : RC->varlists()) {
2821 assert(Ref && "NULL expr in OpenMP nontemporal clause.");
2822 SourceLocation ELoc;
2823 SourceRange ERange;
2824 Expr *SimpleRefExpr = Ref;
2825 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2826 /*AllowArraySection=*/true);
2827 ValueDecl *D = Res.first;
2828 if (!D)
2829 continue;
2830 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2831 S.Diag(Ref->getExprLoc(),
2832 diag::err_omp_reduction_not_inclusive_exclusive)
2833 << Ref->getSourceRange();
2834 }
2835 }
2836 }
2837 }
2838 }
2839
2840 static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2841 ArrayRef<OMPClause *> Clauses);
2842 static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2843 bool WithInit);
2844
2845 static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2846 const ValueDecl *D,
2847 const DSAStackTy::DSAVarData &DVar,
2848 bool IsLoopIterVar = false);
2849
EndOpenMPDSABlock(Stmt * CurDirective)2850 void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
2851 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2852 // A variable of class type (or array thereof) that appears in a lastprivate
2853 // clause requires an accessible, unambiguous default constructor for the
2854 // class type, unless the list item is also specified in a firstprivate
2855 // clause.
2856 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2857 for (OMPClause *C : D->clauses()) {
2858 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
2859 SmallVector<Expr *, 8> PrivateCopies;
2860 for (Expr *DE : Clause->varlists()) {
2861 if (DE->isValueDependent() || DE->isTypeDependent()) {
2862 PrivateCopies.push_back(nullptr);
2863 continue;
2864 }
2865 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2866 auto *VD = cast<VarDecl>(DRE->getDecl());
2867 QualType Type = VD->getType().getNonReferenceType();
2868 const DSAStackTy::DSAVarData DVar =
2869 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2870 if (DVar.CKind == OMPC_lastprivate) {
2871 // Generate helper private variable and initialize it with the
2872 // default value. The address of the original variable is replaced
2873 // by the address of the new private variable in CodeGen. This new
2874 // variable is not added to IdResolver, so the code in the OpenMP
2875 // region uses original variable for proper diagnostics.
2876 VarDecl *VDPrivate = buildVarDecl(
2877 *this, DE->getExprLoc(), Type.getUnqualifiedType(),
2878 VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2879 ActOnUninitializedDecl(VDPrivate);
2880 if (VDPrivate->isInvalidDecl()) {
2881 PrivateCopies.push_back(nullptr);
2882 continue;
2883 }
2884 PrivateCopies.push_back(buildDeclRefExpr(
2885 *this, VDPrivate, DE->getType(), DE->getExprLoc()));
2886 } else {
2887 // The variable is also a firstprivate, so initialization sequence
2888 // for private copy is generated already.
2889 PrivateCopies.push_back(nullptr);
2890 }
2891 }
2892 Clause->setPrivateCopies(PrivateCopies);
2893 continue;
2894 }
2895 // Finalize nontemporal clause by handling private copies, if any.
2896 if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
2897 SmallVector<Expr *, 8> PrivateRefs;
2898 for (Expr *RefExpr : Clause->varlists()) {
2899 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2900 SourceLocation ELoc;
2901 SourceRange ERange;
2902 Expr *SimpleRefExpr = RefExpr;
2903 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
2904 if (Res.second)
2905 // It will be analyzed later.
2906 PrivateRefs.push_back(RefExpr);
2907 ValueDecl *D = Res.first;
2908 if (!D)
2909 continue;
2910
2911 const DSAStackTy::DSAVarData DVar =
2912 DSAStack->getTopDSA(D, /*FromParent=*/false);
2913 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2914 : SimpleRefExpr);
2915 }
2916 Clause->setPrivateRefs(PrivateRefs);
2917 continue;
2918 }
2919 if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
2920 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2921 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2922 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
2923 if (!DRE)
2924 continue;
2925 ValueDecl *VD = DRE->getDecl();
2926 if (!VD || !isa<VarDecl>(VD))
2927 continue;
2928 DSAStackTy::DSAVarData DVar =
2929 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2930 // OpenMP [2.12.5, target Construct]
2931 // Memory allocators that appear in a uses_allocators clause cannot
2932 // appear in other data-sharing attribute clauses or data-mapping
2933 // attribute clauses in the same construct.
2934 Expr *MapExpr = nullptr;
2935 if (DVar.RefExpr ||
2936 DSAStack->checkMappableExprComponentListsForDecl(
2937 VD, /*CurrentRegionOnly=*/true,
2938 [VD, &MapExpr](
2939 OMPClauseMappableExprCommon::MappableExprComponentListRef
2940 MapExprComponents,
2941 OpenMPClauseKind C) {
2942 auto MI = MapExprComponents.rbegin();
2943 auto ME = MapExprComponents.rend();
2944 if (MI != ME &&
2945 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2946 VD->getCanonicalDecl()) {
2947 MapExpr = MI->getAssociatedExpression();
2948 return true;
2949 }
2950 return false;
2951 })) {
2952 Diag(D.Allocator->getExprLoc(),
2953 diag::err_omp_allocator_used_in_clauses)
2954 << D.Allocator->getSourceRange();
2955 if (DVar.RefExpr)
2956 reportOriginalDsa(*this, DSAStack, VD, DVar);
2957 else
2958 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2959 << MapExpr->getSourceRange();
2960 }
2961 }
2962 continue;
2963 }
2964 }
2965 // Check allocate clauses.
2966 if (!CurContext->isDependentContext())
2967 checkAllocateClauses(*this, DSAStack, D->clauses());
2968 checkReductionClauses(*this, DSAStack, D->clauses());
2969 }
2970
2971 DSAStack->pop();
2972 DiscardCleanupsInEvaluationContext();
2973 PopExpressionEvaluationContext();
2974 }
2975
2976 static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
2977 Expr *NumIterations, Sema &SemaRef,
2978 Scope *S, DSAStackTy *Stack);
2979
2980 namespace {
2981
2982 class VarDeclFilterCCC final : public CorrectionCandidateCallback {
2983 private:
2984 Sema &SemaRef;
2985
2986 public:
VarDeclFilterCCC(Sema & S)2987 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
ValidateCandidate(const TypoCorrection & Candidate)2988 bool ValidateCandidate(const TypoCorrection &Candidate) override {
2989 NamedDecl *ND = Candidate.getCorrectionDecl();
2990 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
2991 return VD->hasGlobalStorage() &&
2992 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
2993 SemaRef.getCurScope());
2994 }
2995 return false;
2996 }
2997
clone()2998 std::unique_ptr<CorrectionCandidateCallback> clone() override {
2999 return std::make_unique<VarDeclFilterCCC>(*this);
3000 }
3001 };
3002
3003 class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3004 private:
3005 Sema &SemaRef;
3006
3007 public:
VarOrFuncDeclFilterCCC(Sema & S)3008 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
ValidateCandidate(const TypoCorrection & Candidate)3009 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3010 NamedDecl *ND = Candidate.getCorrectionDecl();
3011 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3012 isa<FunctionDecl>(ND))) {
3013 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3014 SemaRef.getCurScope());
3015 }
3016 return false;
3017 }
3018
clone()3019 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3020 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3021 }
3022 };
3023
3024 } // namespace
3025
ActOnOpenMPIdExpression(Scope * CurScope,CXXScopeSpec & ScopeSpec,const DeclarationNameInfo & Id,OpenMPDirectiveKind Kind)3026 ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
3027 CXXScopeSpec &ScopeSpec,
3028 const DeclarationNameInfo &Id,
3029 OpenMPDirectiveKind Kind) {
3030 LookupResult Lookup(*this, Id, LookupOrdinaryName);
3031 LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
3032
3033 if (Lookup.isAmbiguous())
3034 return ExprError();
3035
3036 VarDecl *VD;
3037 if (!Lookup.isSingleResult()) {
3038 VarDeclFilterCCC CCC(*this);
3039 if (TypoCorrection Corrected =
3040 CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, CCC,
3041 CTK_ErrorRecovery)) {
3042 diagnoseTypo(Corrected,
3043 PDiag(Lookup.empty()
3044 ? diag::err_undeclared_var_use_suggest
3045 : diag::err_omp_expected_var_arg_suggest)
3046 << Id.getName());
3047 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3048 } else {
3049 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3050 : diag::err_omp_expected_var_arg)
3051 << Id.getName();
3052 return ExprError();
3053 }
3054 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3055 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3056 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3057 return ExprError();
3058 }
3059 Lookup.suppressDiagnostics();
3060
3061 // OpenMP [2.9.2, Syntax, C/C++]
3062 // Variables must be file-scope, namespace-scope, or static block-scope.
3063 if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
3064 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3065 << getOpenMPDirectiveName(Kind) << !VD->isStaticLocal();
3066 bool IsDecl =
3067 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3068 Diag(VD->getLocation(),
3069 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3070 << VD;
3071 return ExprError();
3072 }
3073
3074 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3075 NamedDecl *ND = CanonicalVD;
3076 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3077 // A threadprivate directive for file-scope variables must appear outside
3078 // any definition or declaration.
3079 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3080 !getCurLexicalContext()->isTranslationUnit()) {
3081 Diag(Id.getLoc(), diag::err_omp_var_scope)
3082 << getOpenMPDirectiveName(Kind) << VD;
3083 bool IsDecl =
3084 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3085 Diag(VD->getLocation(),
3086 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3087 << VD;
3088 return ExprError();
3089 }
3090 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3091 // A threadprivate directive for static class member variables must appear
3092 // in the class definition, in the same scope in which the member
3093 // variables are declared.
3094 if (CanonicalVD->isStaticDataMember() &&
3095 !CanonicalVD->getDeclContext()->Equals(getCurLexicalContext())) {
3096 Diag(Id.getLoc(), diag::err_omp_var_scope)
3097 << getOpenMPDirectiveName(Kind) << VD;
3098 bool IsDecl =
3099 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3100 Diag(VD->getLocation(),
3101 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3102 << VD;
3103 return ExprError();
3104 }
3105 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3106 // A threadprivate directive for namespace-scope variables must appear
3107 // outside any definition or declaration other than the namespace
3108 // definition itself.
3109 if (CanonicalVD->getDeclContext()->isNamespace() &&
3110 (!getCurLexicalContext()->isFileContext() ||
3111 !getCurLexicalContext()->Encloses(CanonicalVD->getDeclContext()))) {
3112 Diag(Id.getLoc(), diag::err_omp_var_scope)
3113 << getOpenMPDirectiveName(Kind) << VD;
3114 bool IsDecl =
3115 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3116 Diag(VD->getLocation(),
3117 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3118 << VD;
3119 return ExprError();
3120 }
3121 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3122 // A threadprivate directive for static block-scope variables must appear
3123 // in the scope of the variable and not in a nested scope.
3124 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3125 !isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
3126 Diag(Id.getLoc(), diag::err_omp_var_scope)
3127 << getOpenMPDirectiveName(Kind) << VD;
3128 bool IsDecl =
3129 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3130 Diag(VD->getLocation(),
3131 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3132 << VD;
3133 return ExprError();
3134 }
3135
3136 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3137 // A threadprivate directive must lexically precede all references to any
3138 // of the variables in its list.
3139 if (Kind == OMPD_threadprivate && VD->isUsed() &&
3140 !DSAStack->isThreadPrivate(VD)) {
3141 Diag(Id.getLoc(), diag::err_omp_var_used)
3142 << getOpenMPDirectiveName(Kind) << VD;
3143 return ExprError();
3144 }
3145
3146 QualType ExprType = VD->getType().getNonReferenceType();
3147 return DeclRefExpr::Create(Context, NestedNameSpecifierLoc(),
3148 SourceLocation(), VD,
3149 /*RefersToEnclosingVariableOrCapture=*/false,
3150 Id.getLoc(), ExprType, VK_LValue);
3151 }
3152
3153 Sema::DeclGroupPtrTy
ActOnOpenMPThreadprivateDirective(SourceLocation Loc,ArrayRef<Expr * > VarList)3154 Sema::ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
3155 ArrayRef<Expr *> VarList) {
3156 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3157 CurContext->addDecl(D);
3158 return DeclGroupPtrTy::make(DeclGroupRef(D));
3159 }
3160 return nullptr;
3161 }
3162
3163 namespace {
3164 class LocalVarRefChecker final
3165 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3166 Sema &SemaRef;
3167
3168 public:
VisitDeclRefExpr(const DeclRefExpr * E)3169 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3170 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3171 if (VD->hasLocalStorage()) {
3172 SemaRef.Diag(E->getBeginLoc(),
3173 diag::err_omp_local_var_in_threadprivate_init)
3174 << E->getSourceRange();
3175 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3176 << VD << VD->getSourceRange();
3177 return true;
3178 }
3179 }
3180 return false;
3181 }
VisitStmt(const Stmt * S)3182 bool VisitStmt(const Stmt *S) {
3183 for (const Stmt *Child : S->children()) {
3184 if (Child && Visit(Child))
3185 return true;
3186 }
3187 return false;
3188 }
LocalVarRefChecker(Sema & SemaRef)3189 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3190 };
3191 } // namespace
3192
3193 OMPThreadPrivateDecl *
CheckOMPThreadPrivateDecl(SourceLocation Loc,ArrayRef<Expr * > VarList)3194 Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
3195 SmallVector<Expr *, 8> Vars;
3196 for (Expr *RefExpr : VarList) {
3197 auto *DE = cast<DeclRefExpr>(RefExpr);
3198 auto *VD = cast<VarDecl>(DE->getDecl());
3199 SourceLocation ILoc = DE->getExprLoc();
3200
3201 // Mark variable as used.
3202 VD->setReferenced();
3203 VD->markUsed(Context);
3204
3205 QualType QType = VD->getType();
3206 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3207 // It will be analyzed later.
3208 Vars.push_back(DE);
3209 continue;
3210 }
3211
3212 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3213 // A threadprivate variable must not have an incomplete type.
3214 if (RequireCompleteType(ILoc, VD->getType(),
3215 diag::err_omp_threadprivate_incomplete_type)) {
3216 continue;
3217 }
3218
3219 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3220 // A threadprivate variable must not have a reference type.
3221 if (VD->getType()->isReferenceType()) {
3222 Diag(ILoc, diag::err_omp_ref_type_arg)
3223 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
3224 bool IsDecl =
3225 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3226 Diag(VD->getLocation(),
3227 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3228 << VD;
3229 continue;
3230 }
3231
3232 // Check if this is a TLS variable. If TLS is not being supported, produce
3233 // the corresponding diagnostic.
3234 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3235 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3236 getLangOpts().OpenMPUseTLS &&
3237 getASTContext().getTargetInfo().isTLSSupported())) ||
3238 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3239 !VD->isLocalVarDecl())) {
3240 Diag(ILoc, diag::err_omp_var_thread_local)
3241 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3242 bool IsDecl =
3243 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3244 Diag(VD->getLocation(),
3245 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3246 << VD;
3247 continue;
3248 }
3249
3250 // Check if initial value of threadprivate variable reference variable with
3251 // local storage (it is not supported by runtime).
3252 if (const Expr *Init = VD->getAnyInitializer()) {
3253 LocalVarRefChecker Checker(*this);
3254 if (Checker.Visit(Init))
3255 continue;
3256 }
3257
3258 Vars.push_back(RefExpr);
3259 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3260 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3261 Context, SourceRange(Loc, Loc)));
3262 if (ASTMutationListener *ML = Context.getASTMutationListener())
3263 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3264 }
3265 OMPThreadPrivateDecl *D = nullptr;
3266 if (!Vars.empty()) {
3267 D = OMPThreadPrivateDecl::Create(Context, getCurLexicalContext(), Loc,
3268 Vars);
3269 D->setAccess(AS_public);
3270 }
3271 return D;
3272 }
3273
3274 static OMPAllocateDeclAttr::AllocatorTypeTy
getAllocatorKind(Sema & S,DSAStackTy * Stack,Expr * Allocator)3275 getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3276 if (!Allocator)
3277 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3278 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3279 Allocator->isInstantiationDependent() ||
3280 Allocator->containsUnexpandedParameterPack())
3281 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3282 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3283 llvm::FoldingSetNodeID AEId;
3284 const Expr *AE = Allocator->IgnoreParenImpCasts();
3285 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3286 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3287 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3288 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3289 llvm::FoldingSetNodeID DAEId;
3290 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3291 /*Canonical=*/true);
3292 if (AEId == DAEId) {
3293 AllocatorKindRes = AllocatorKind;
3294 break;
3295 }
3296 }
3297 return AllocatorKindRes;
3298 }
3299
checkPreviousOMPAllocateAttribute(Sema & S,DSAStackTy * Stack,Expr * RefExpr,VarDecl * VD,OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,Expr * Allocator)3300 static bool checkPreviousOMPAllocateAttribute(
3301 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3302 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3303 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3304 return false;
3305 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3306 Expr *PrevAllocator = A->getAllocator();
3307 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3308 getAllocatorKind(S, Stack, PrevAllocator);
3309 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3310 if (AllocatorsMatch &&
3311 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3312 Allocator && PrevAllocator) {
3313 const Expr *AE = Allocator->IgnoreParenImpCasts();
3314 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3315 llvm::FoldingSetNodeID AEId, PAEId;
3316 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3317 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3318 AllocatorsMatch = AEId == PAEId;
3319 }
3320 if (!AllocatorsMatch) {
3321 SmallString<256> AllocatorBuffer;
3322 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3323 if (Allocator)
3324 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3325 SmallString<256> PrevAllocatorBuffer;
3326 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3327 if (PrevAllocator)
3328 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3329 S.getPrintingPolicy());
3330
3331 SourceLocation AllocatorLoc =
3332 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3333 SourceRange AllocatorRange =
3334 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3335 SourceLocation PrevAllocatorLoc =
3336 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3337 SourceRange PrevAllocatorRange =
3338 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3339 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3340 << (Allocator ? 1 : 0) << AllocatorStream.str()
3341 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3342 << AllocatorRange;
3343 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3344 << PrevAllocatorRange;
3345 return true;
3346 }
3347 return false;
3348 }
3349
3350 static void
applyOMPAllocateAttribute(Sema & S,VarDecl * VD,OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,Expr * Allocator,Expr * Alignment,SourceRange SR)3351 applyOMPAllocateAttribute(Sema &S, VarDecl *VD,
3352 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3353 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3354 if (VD->hasAttr<OMPAllocateDeclAttr>())
3355 return;
3356 if (Alignment &&
3357 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3358 Alignment->isInstantiationDependent() ||
3359 Alignment->containsUnexpandedParameterPack()))
3360 // Apply later when we have a usable value.
3361 return;
3362 if (Allocator &&
3363 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3364 Allocator->isInstantiationDependent() ||
3365 Allocator->containsUnexpandedParameterPack()))
3366 return;
3367 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3368 Allocator, Alignment, SR);
3369 VD->addAttr(A);
3370 if (ASTMutationListener *ML = S.Context.getASTMutationListener())
3371 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3372 }
3373
3374 Sema::DeclGroupPtrTy
ActOnOpenMPAllocateDirective(SourceLocation Loc,ArrayRef<Expr * > VarList,ArrayRef<OMPClause * > Clauses,DeclContext * Owner)3375 Sema::ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef<Expr *> VarList,
3376 ArrayRef<OMPClause *> Clauses,
3377 DeclContext *Owner) {
3378 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3379 Expr *Alignment = nullptr;
3380 Expr *Allocator = nullptr;
3381 if (Clauses.empty()) {
3382 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3383 // allocate directives that appear in a target region must specify an
3384 // allocator clause unless a requires directive with the dynamic_allocators
3385 // clause is present in the same compilation unit.
3386 if (LangOpts.OpenMPIsDevice &&
3387 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3388 targetDiag(Loc, diag::err_expected_allocator_clause);
3389 } else {
3390 for (const OMPClause *C : Clauses)
3391 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3392 Allocator = AC->getAllocator();
3393 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3394 Alignment = AC->getAlignment();
3395 else
3396 llvm_unreachable("Unexpected clause on allocate directive");
3397 }
3398 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3399 getAllocatorKind(*this, DSAStack, Allocator);
3400 SmallVector<Expr *, 8> Vars;
3401 for (Expr *RefExpr : VarList) {
3402 auto *DE = cast<DeclRefExpr>(RefExpr);
3403 auto *VD = cast<VarDecl>(DE->getDecl());
3404
3405 // Check if this is a TLS variable or global register.
3406 if (VD->getTLSKind() != VarDecl::TLS_None ||
3407 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3408 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3409 !VD->isLocalVarDecl()))
3410 continue;
3411
3412 // If the used several times in the allocate directive, the same allocator
3413 // must be used.
3414 if (checkPreviousOMPAllocateAttribute(*this, DSAStack, RefExpr, VD,
3415 AllocatorKind, Allocator))
3416 continue;
3417
3418 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3419 // If a list item has a static storage type, the allocator expression in the
3420 // allocator clause must be a constant expression that evaluates to one of
3421 // the predefined memory allocator values.
3422 if (Allocator && VD->hasGlobalStorage()) {
3423 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3424 Diag(Allocator->getExprLoc(),
3425 diag::err_omp_expected_predefined_allocator)
3426 << Allocator->getSourceRange();
3427 bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
3428 VarDecl::DeclarationOnly;
3429 Diag(VD->getLocation(),
3430 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3431 << VD;
3432 continue;
3433 }
3434 }
3435
3436 Vars.push_back(RefExpr);
3437 applyOMPAllocateAttribute(*this, VD, AllocatorKind, Allocator, Alignment,
3438 DE->getSourceRange());
3439 }
3440 if (Vars.empty())
3441 return nullptr;
3442 if (!Owner)
3443 Owner = getCurLexicalContext();
3444 auto *D = OMPAllocateDecl::Create(Context, Owner, Loc, Vars, Clauses);
3445 D->setAccess(AS_public);
3446 Owner->addDecl(D);
3447 return DeclGroupPtrTy::make(DeclGroupRef(D));
3448 }
3449
3450 Sema::DeclGroupPtrTy
ActOnOpenMPRequiresDirective(SourceLocation Loc,ArrayRef<OMPClause * > ClauseList)3451 Sema::ActOnOpenMPRequiresDirective(SourceLocation Loc,
3452 ArrayRef<OMPClause *> ClauseList) {
3453 OMPRequiresDecl *D = nullptr;
3454 if (!CurContext->isFileContext()) {
3455 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3456 } else {
3457 D = CheckOMPRequiresDecl(Loc, ClauseList);
3458 if (D) {
3459 CurContext->addDecl(D);
3460 DSAStack->addRequiresDecl(D);
3461 }
3462 }
3463 return DeclGroupPtrTy::make(DeclGroupRef(D));
3464 }
3465
ActOnOpenMPAssumesDirective(SourceLocation Loc,OpenMPDirectiveKind DKind,ArrayRef<std::string> Assumptions,bool SkippedClauses)3466 void Sema::ActOnOpenMPAssumesDirective(SourceLocation Loc,
3467 OpenMPDirectiveKind DKind,
3468 ArrayRef<std::string> Assumptions,
3469 bool SkippedClauses) {
3470 if (!SkippedClauses && Assumptions.empty())
3471 Diag(Loc, diag::err_omp_no_clause_for_directive)
3472 << llvm::omp::getAllAssumeClauseOptions()
3473 << llvm::omp::getOpenMPDirectiveName(DKind);
3474
3475 auto *AA = AssumptionAttr::Create(Context, llvm::join(Assumptions, ","), Loc);
3476 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3477 OMPAssumeScoped.push_back(AA);
3478 return;
3479 }
3480
3481 // Global assumes without assumption clauses are ignored.
3482 if (Assumptions.empty())
3483 return;
3484
3485 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3486 "Unexpected omp assumption directive!");
3487 OMPAssumeGlobal.push_back(AA);
3488
3489 // The OMPAssumeGlobal scope above will take care of new declarations but
3490 // we also want to apply the assumption to existing ones, e.g., to
3491 // declarations in included headers. To this end, we traverse all existing
3492 // declaration contexts and annotate function declarations here.
3493 SmallVector<DeclContext *, 8> DeclContexts;
3494 auto *Ctx = CurContext;
3495 while (Ctx->getLexicalParent())
3496 Ctx = Ctx->getLexicalParent();
3497 DeclContexts.push_back(Ctx);
3498 while (!DeclContexts.empty()) {
3499 DeclContext *DC = DeclContexts.pop_back_val();
3500 for (auto *SubDC : DC->decls()) {
3501 if (SubDC->isInvalidDecl())
3502 continue;
3503 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3504 DeclContexts.push_back(CTD->getTemplatedDecl());
3505 llvm::append_range(DeclContexts, CTD->specializations());
3506 continue;
3507 }
3508 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3509 DeclContexts.push_back(DC);
3510 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3511 F->addAttr(AA);
3512 continue;
3513 }
3514 }
3515 }
3516 }
3517
ActOnOpenMPEndAssumesDirective()3518 void Sema::ActOnOpenMPEndAssumesDirective() {
3519 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3520 OMPAssumeScoped.pop_back();
3521 }
3522
CheckOMPRequiresDecl(SourceLocation Loc,ArrayRef<OMPClause * > ClauseList)3523 OMPRequiresDecl *Sema::CheckOMPRequiresDecl(SourceLocation Loc,
3524 ArrayRef<OMPClause *> ClauseList) {
3525 /// For target specific clauses, the requires directive cannot be
3526 /// specified after the handling of any of the target regions in the
3527 /// current compilation unit.
3528 ArrayRef<SourceLocation> TargetLocations =
3529 DSAStack->getEncounteredTargetLocs();
3530 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3531 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3532 for (const OMPClause *CNew : ClauseList) {
3533 // Check if any of the requires clauses affect target regions.
3534 if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3535 isa<OMPUnifiedAddressClause>(CNew) ||
3536 isa<OMPReverseOffloadClause>(CNew) ||
3537 isa<OMPDynamicAllocatorsClause>(CNew)) {
3538 Diag(Loc, diag::err_omp_directive_before_requires)
3539 << "target" << getOpenMPClauseName(CNew->getClauseKind());
3540 for (SourceLocation TargetLoc : TargetLocations) {
3541 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3542 << "target";
3543 }
3544 } else if (!AtomicLoc.isInvalid() &&
3545 isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3546 Diag(Loc, diag::err_omp_directive_before_requires)
3547 << "atomic" << getOpenMPClauseName(CNew->getClauseKind());
3548 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3549 << "atomic";
3550 }
3551 }
3552 }
3553
3554 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3555 return OMPRequiresDecl::Create(Context, getCurLexicalContext(), Loc,
3556 ClauseList);
3557 return nullptr;
3558 }
3559
reportOriginalDsa(Sema & SemaRef,const DSAStackTy * Stack,const ValueDecl * D,const DSAStackTy::DSAVarData & DVar,bool IsLoopIterVar)3560 static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3561 const ValueDecl *D,
3562 const DSAStackTy::DSAVarData &DVar,
3563 bool IsLoopIterVar) {
3564 if (DVar.RefExpr) {
3565 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3566 << getOpenMPClauseName(DVar.CKind);
3567 return;
3568 }
3569 enum {
3570 PDSA_StaticMemberShared,
3571 PDSA_StaticLocalVarShared,
3572 PDSA_LoopIterVarPrivate,
3573 PDSA_LoopIterVarLinear,
3574 PDSA_LoopIterVarLastprivate,
3575 PDSA_ConstVarShared,
3576 PDSA_GlobalVarShared,
3577 PDSA_TaskVarFirstprivate,
3578 PDSA_LocalVarPrivate,
3579 PDSA_Implicit
3580 } Reason = PDSA_Implicit;
3581 bool ReportHint = false;
3582 auto ReportLoc = D->getLocation();
3583 auto *VD = dyn_cast<VarDecl>(D);
3584 if (IsLoopIterVar) {
3585 if (DVar.CKind == OMPC_private)
3586 Reason = PDSA_LoopIterVarPrivate;
3587 else if (DVar.CKind == OMPC_lastprivate)
3588 Reason = PDSA_LoopIterVarLastprivate;
3589 else
3590 Reason = PDSA_LoopIterVarLinear;
3591 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3592 DVar.CKind == OMPC_firstprivate) {
3593 Reason = PDSA_TaskVarFirstprivate;
3594 ReportLoc = DVar.ImplicitDSALoc;
3595 } else if (VD && VD->isStaticLocal())
3596 Reason = PDSA_StaticLocalVarShared;
3597 else if (VD && VD->isStaticDataMember())
3598 Reason = PDSA_StaticMemberShared;
3599 else if (VD && VD->isFileVarDecl())
3600 Reason = PDSA_GlobalVarShared;
3601 else if (D->getType().isConstant(SemaRef.getASTContext()))
3602 Reason = PDSA_ConstVarShared;
3603 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3604 ReportHint = true;
3605 Reason = PDSA_LocalVarPrivate;
3606 }
3607 if (Reason != PDSA_Implicit) {
3608 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3609 << Reason << ReportHint
3610 << getOpenMPDirectiveName(Stack->getCurrentDirective());
3611 } else if (DVar.ImplicitDSALoc.isValid()) {
3612 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3613 << getOpenMPClauseName(DVar.CKind);
3614 }
3615 }
3616
3617 static OpenMPMapClauseKind
getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M,bool IsAggregateOrDeclareTarget)3618 getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M,
3619 bool IsAggregateOrDeclareTarget) {
3620 OpenMPMapClauseKind Kind = OMPC_MAP_unknown;
3621 switch (M) {
3622 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3623 Kind = OMPC_MAP_alloc;
3624 break;
3625 case OMPC_DEFAULTMAP_MODIFIER_to:
3626 Kind = OMPC_MAP_to;
3627 break;
3628 case OMPC_DEFAULTMAP_MODIFIER_from:
3629 Kind = OMPC_MAP_from;
3630 break;
3631 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3632 Kind = OMPC_MAP_tofrom;
3633 break;
3634 case OMPC_DEFAULTMAP_MODIFIER_present:
3635 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3636 // If implicit-behavior is present, each variable referenced in the
3637 // construct in the category specified by variable-category is treated as if
3638 // it had been listed in a map clause with the map-type of alloc and
3639 // map-type-modifier of present.
3640 Kind = OMPC_MAP_alloc;
3641 break;
3642 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3643 case OMPC_DEFAULTMAP_MODIFIER_last:
3644 llvm_unreachable("Unexpected defaultmap implicit behavior");
3645 case OMPC_DEFAULTMAP_MODIFIER_none:
3646 case OMPC_DEFAULTMAP_MODIFIER_default:
3647 case OMPC_DEFAULTMAP_MODIFIER_unknown:
3648 // IsAggregateOrDeclareTarget could be true if:
3649 // 1. the implicit behavior for aggregate is tofrom
3650 // 2. it's a declare target link
3651 if (IsAggregateOrDeclareTarget) {
3652 Kind = OMPC_MAP_tofrom;
3653 break;
3654 }
3655 llvm_unreachable("Unexpected defaultmap implicit behavior");
3656 }
3657 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3658 return Kind;
3659 }
3660
3661 namespace {
3662 class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3663 DSAStackTy *Stack;
3664 Sema &SemaRef;
3665 bool ErrorFound = false;
3666 bool TryCaptureCXXThisMembers = false;
3667 CapturedStmt *CS = nullptr;
3668 const static unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_pointer + 1;
3669 llvm::SmallVector<Expr *, 4> ImplicitFirstprivate;
3670 llvm::SmallVector<Expr *, 4> ImplicitPrivate;
3671 llvm::SmallVector<Expr *, 4> ImplicitMap[DefaultmapKindNum][OMPC_MAP_delete];
3672 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3673 ImplicitMapModifier[DefaultmapKindNum];
3674 Sema::VarsWithInheritedDSAType VarsWithInheritedDSA;
3675 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3676
VisitSubCaptures(OMPExecutableDirective * S)3677 void VisitSubCaptures(OMPExecutableDirective *S) {
3678 // Check implicitly captured variables.
3679 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3680 return;
3681 if (S->getDirectiveKind() == OMPD_atomic ||
3682 S->getDirectiveKind() == OMPD_critical ||
3683 S->getDirectiveKind() == OMPD_section ||
3684 S->getDirectiveKind() == OMPD_master ||
3685 S->getDirectiveKind() == OMPD_masked ||
3686 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3687 Visit(S->getAssociatedStmt());
3688 return;
3689 }
3690 visitSubCaptures(S->getInnermostCapturedStmt());
3691 // Try to capture inner this->member references to generate correct mappings
3692 // and diagnostics.
3693 if (TryCaptureCXXThisMembers ||
3694 (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
3695 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3696 [](const CapturedStmt::Capture &C) {
3697 return C.capturesThis();
3698 }))) {
3699 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3700 TryCaptureCXXThisMembers = true;
3701 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3702 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3703 }
3704 // In tasks firstprivates are not captured anymore, need to analyze them
3705 // explicitly.
3706 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3707 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3708 for (OMPClause *C : S->clauses())
3709 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3710 for (Expr *Ref : FC->varlists())
3711 Visit(Ref);
3712 }
3713 }
3714 }
3715
3716 public:
VisitDeclRefExpr(DeclRefExpr * E)3717 void VisitDeclRefExpr(DeclRefExpr *E) {
3718 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3719 E->isValueDependent() || E->containsUnexpandedParameterPack() ||
3720 E->isInstantiationDependent())
3721 return;
3722 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3723 // Check the datasharing rules for the expressions in the clauses.
3724 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3725 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3726 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3727 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3728 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3729 Visit(CED->getInit());
3730 return;
3731 }
3732 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3733 // Do not analyze internal variables and do not enclose them into
3734 // implicit clauses.
3735 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3736 return;
3737 VD = VD->getCanonicalDecl();
3738 // Skip internally declared variables.
3739 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3740 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3741 !Stack->isImplicitTaskFirstprivate(VD))
3742 return;
3743 // Skip allocators in uses_allocators clauses.
3744 if (Stack->isUsesAllocatorsDecl(VD))
3745 return;
3746
3747 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3748 // Check if the variable has explicit DSA set and stop analysis if it so.
3749 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3750 return;
3751
3752 // Skip internally declared static variables.
3753 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3754 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3755 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3756 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3757 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3758 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3759 !Stack->isImplicitTaskFirstprivate(VD))
3760 return;
3761
3762 SourceLocation ELoc = E->getExprLoc();
3763 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3764 // The default(none) clause requires that each variable that is referenced
3765 // in the construct, and does not have a predetermined data-sharing
3766 // attribute, must have its data-sharing attribute explicitly determined
3767 // by being listed in a data-sharing attribute clause.
3768 if (DVar.CKind == OMPC_unknown &&
3769 (Stack->getDefaultDSA() == DSA_none ||
3770 Stack->getDefaultDSA() == DSA_private ||
3771 Stack->getDefaultDSA() == DSA_firstprivate) &&
3772 isImplicitOrExplicitTaskingRegion(DKind) &&
3773 VarsWithInheritedDSA.count(VD) == 0) {
3774 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3775 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3776 Stack->getDefaultDSA() == DSA_private)) {
3777 DSAStackTy::DSAVarData DVar =
3778 Stack->getImplicitDSA(VD, /*FromParent=*/false);
3779 InheritedDSA = DVar.CKind == OMPC_unknown;
3780 }
3781 if (InheritedDSA)
3782 VarsWithInheritedDSA[VD] = E;
3783 if (Stack->getDefaultDSA() == DSA_none)
3784 return;
3785 }
3786
3787 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3788 // If implicit-behavior is none, each variable referenced in the
3789 // construct that does not have a predetermined data-sharing attribute
3790 // and does not appear in a to or link clause on a declare target
3791 // directive must be listed in a data-mapping attribute clause, a
3792 // data-sharing attribute clause (including a data-sharing attribute
3793 // clause on a combined construct where target. is one of the
3794 // constituent constructs), or an is_device_ptr clause.
3795 OpenMPDefaultmapClauseKind ClauseKind =
3796 getVariableCategoryFromDecl(SemaRef.getLangOpts(), VD);
3797 if (SemaRef.getLangOpts().OpenMP >= 50) {
3798 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3799 OMPC_DEFAULTMAP_MODIFIER_none;
3800 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3801 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3802 // Only check for data-mapping attribute and is_device_ptr here
3803 // since we have already make sure that the declaration does not
3804 // have a data-sharing attribute above
3805 if (!Stack->checkMappableExprComponentListsForDecl(
3806 VD, /*CurrentRegionOnly=*/true,
3807 [VD](OMPClauseMappableExprCommon::MappableExprComponentListRef
3808 MapExprComponents,
3809 OpenMPClauseKind) {
3810 auto MI = MapExprComponents.rbegin();
3811 auto ME = MapExprComponents.rend();
3812 return MI != ME && MI->getAssociatedDeclaration() == VD;
3813 })) {
3814 VarsWithInheritedDSA[VD] = E;
3815 return;
3816 }
3817 }
3818 }
3819 if (SemaRef.getLangOpts().OpenMP > 50) {
3820 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3821 OMPC_DEFAULTMAP_MODIFIER_present;
3822 if (IsModifierPresent) {
3823 if (!llvm::is_contained(ImplicitMapModifier[ClauseKind],
3824 OMPC_MAP_MODIFIER_present)) {
3825 ImplicitMapModifier[ClauseKind].push_back(
3826 OMPC_MAP_MODIFIER_present);
3827 }
3828 }
3829 }
3830
3831 if (isOpenMPTargetExecutionDirective(DKind) &&
3832 !Stack->isLoopControlVariable(VD).first) {
3833 if (!Stack->checkMappableExprComponentListsForDecl(
3834 VD, /*CurrentRegionOnly=*/true,
3835 [this](OMPClauseMappableExprCommon::MappableExprComponentListRef
3836 StackComponents,
3837 OpenMPClauseKind) {
3838 if (SemaRef.LangOpts.OpenMP >= 50)
3839 return !StackComponents.empty();
3840 // Variable is used if it has been marked as an array, array
3841 // section, array shaping or the variable iself.
3842 return StackComponents.size() == 1 ||
3843 llvm::all_of(
3844 llvm::drop_begin(llvm::reverse(StackComponents)),
3845 [](const OMPClauseMappableExprCommon::
3846 MappableComponent &MC) {
3847 return MC.getAssociatedDeclaration() ==
3848 nullptr &&
3849 (isa<OMPArraySectionExpr>(
3850 MC.getAssociatedExpression()) ||
3851 isa<OMPArrayShapingExpr>(
3852 MC.getAssociatedExpression()) ||
3853 isa<ArraySubscriptExpr>(
3854 MC.getAssociatedExpression()));
3855 });
3856 })) {
3857 bool IsFirstprivate = false;
3858 // By default lambdas are captured as firstprivates.
3859 if (const auto *RD =
3860 VD->getType().getNonReferenceType()->getAsCXXRecordDecl())
3861 IsFirstprivate = RD->isLambda();
3862 IsFirstprivate =
3863 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3864 if (IsFirstprivate) {
3865 ImplicitFirstprivate.emplace_back(E);
3866 } else {
3867 OpenMPDefaultmapClauseModifier M =
3868 Stack->getDefaultmapModifier(ClauseKind);
3869 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
3870 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3871 ImplicitMap[ClauseKind][Kind].emplace_back(E);
3872 }
3873 return;
3874 }
3875 }
3876
3877 // OpenMP [2.9.3.6, Restrictions, p.2]
3878 // A list item that appears in a reduction clause of the innermost
3879 // enclosing worksharing or parallel construct may not be accessed in an
3880 // explicit task.
3881 DVar = Stack->hasInnermostDSA(
3882 VD,
3883 [](OpenMPClauseKind C, bool AppliedToPointee) {
3884 return C == OMPC_reduction && !AppliedToPointee;
3885 },
3886 [](OpenMPDirectiveKind K) {
3887 return isOpenMPParallelDirective(K) ||
3888 isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
3889 },
3890 /*FromParent=*/true);
3891 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3892 ErrorFound = true;
3893 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3894 reportOriginalDsa(SemaRef, Stack, VD, DVar);
3895 return;
3896 }
3897
3898 // Define implicit data-sharing attributes for task.
3899 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
3900 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
3901 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3902 DVar.CKind == OMPC_firstprivate) ||
3903 (Stack->getDefaultDSA() == DSA_private &&
3904 DVar.CKind == OMPC_private)) &&
3905 !DVar.RefExpr)) &&
3906 !Stack->isLoopControlVariable(VD).first) {
3907 if (Stack->getDefaultDSA() == DSA_private)
3908 ImplicitPrivate.push_back(E);
3909 else
3910 ImplicitFirstprivate.push_back(E);
3911 return;
3912 }
3913
3914 // Store implicitly used globals with declare target link for parent
3915 // target.
3916 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
3917 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3918 Stack->addToParentTargetRegionLinkGlobals(E);
3919 return;
3920 }
3921 }
3922 }
VisitMemberExpr(MemberExpr * E)3923 void VisitMemberExpr(MemberExpr *E) {
3924 if (E->isTypeDependent() || E->isValueDependent() ||
3925 E->containsUnexpandedParameterPack() || E->isInstantiationDependent())
3926 return;
3927 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
3928 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3929 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
3930 if (!FD)
3931 return;
3932 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
3933 // Check if the variable has explicit DSA set and stop analysis if it
3934 // so.
3935 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
3936 return;
3937
3938 if (isOpenMPTargetExecutionDirective(DKind) &&
3939 !Stack->isLoopControlVariable(FD).first &&
3940 !Stack->checkMappableExprComponentListsForDecl(
3941 FD, /*CurrentRegionOnly=*/true,
3942 [](OMPClauseMappableExprCommon::MappableExprComponentListRef
3943 StackComponents,
3944 OpenMPClauseKind) {
3945 return isa<CXXThisExpr>(
3946 cast<MemberExpr>(
3947 StackComponents.back().getAssociatedExpression())
3948 ->getBase()
3949 ->IgnoreParens());
3950 })) {
3951 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
3952 // A bit-field cannot appear in a map clause.
3953 //
3954 if (FD->isBitField())
3955 return;
3956
3957 // Check to see if the member expression is referencing a class that
3958 // has already been explicitly mapped
3959 if (Stack->isClassPreviouslyMapped(TE->getType()))
3960 return;
3961
3962 OpenMPDefaultmapClauseModifier Modifier =
3963 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
3964 OpenMPDefaultmapClauseKind ClauseKind =
3965 getVariableCategoryFromDecl(SemaRef.getLangOpts(), FD);
3966 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
3967 Modifier, /*IsAggregateOrDeclareTarget*/ true);
3968 ImplicitMap[ClauseKind][Kind].emplace_back(E);
3969 return;
3970 }
3971
3972 SourceLocation ELoc = E->getExprLoc();
3973 // OpenMP [2.9.3.6, Restrictions, p.2]
3974 // A list item that appears in a reduction clause of the innermost
3975 // enclosing worksharing or parallel construct may not be accessed in
3976 // an explicit task.
3977 DVar = Stack->hasInnermostDSA(
3978 FD,
3979 [](OpenMPClauseKind C, bool AppliedToPointee) {
3980 return C == OMPC_reduction && !AppliedToPointee;
3981 },
3982 [](OpenMPDirectiveKind K) {
3983 return isOpenMPParallelDirective(K) ||
3984 isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
3985 },
3986 /*FromParent=*/true);
3987 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3988 ErrorFound = true;
3989 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3990 reportOriginalDsa(SemaRef, Stack, FD, DVar);
3991 return;
3992 }
3993
3994 // Define implicit data-sharing attributes for task.
3995 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
3996 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
3997 !Stack->isLoopControlVariable(FD).first) {
3998 // Check if there is a captured expression for the current field in the
3999 // region. Do not mark it as firstprivate unless there is no captured
4000 // expression.
4001 // TODO: try to make it firstprivate.
4002 if (DVar.CKind != OMPC_unknown)
4003 ImplicitFirstprivate.push_back(E);
4004 }
4005 return;
4006 }
4007 if (isOpenMPTargetExecutionDirective(DKind)) {
4008 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
4009 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4010 Stack->getCurrentDirective(),
4011 /*NoDiagnose=*/true))
4012 return;
4013 const auto *VD = cast<ValueDecl>(
4014 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4015 if (!Stack->checkMappableExprComponentListsForDecl(
4016 VD, /*CurrentRegionOnly=*/true,
4017 [&CurComponents](
4018 OMPClauseMappableExprCommon::MappableExprComponentListRef
4019 StackComponents,
4020 OpenMPClauseKind) {
4021 auto CCI = CurComponents.rbegin();
4022 auto CCE = CurComponents.rend();
4023 for (const auto &SC : llvm::reverse(StackComponents)) {
4024 // Do both expressions have the same kind?
4025 if (CCI->getAssociatedExpression()->getStmtClass() !=
4026 SC.getAssociatedExpression()->getStmtClass())
4027 if (!((isa<OMPArraySectionExpr>(
4028 SC.getAssociatedExpression()) ||
4029 isa<OMPArrayShapingExpr>(
4030 SC.getAssociatedExpression())) &&
4031 isa<ArraySubscriptExpr>(
4032 CCI->getAssociatedExpression())))
4033 return false;
4034
4035 const Decl *CCD = CCI->getAssociatedDeclaration();
4036 const Decl *SCD = SC.getAssociatedDeclaration();
4037 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4038 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4039 if (SCD != CCD)
4040 return false;
4041 std::advance(CCI, 1);
4042 if (CCI == CCE)
4043 break;
4044 }
4045 return true;
4046 })) {
4047 Visit(E->getBase());
4048 }
4049 } else if (!TryCaptureCXXThisMembers) {
4050 Visit(E->getBase());
4051 }
4052 }
VisitOMPExecutableDirective(OMPExecutableDirective * S)4053 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4054 for (OMPClause *C : S->clauses()) {
4055 // Skip analysis of arguments of private clauses for task|target
4056 // directives.
4057 if (isa_and_nonnull<OMPPrivateClause>(C))
4058 continue;
4059 // Skip analysis of arguments of implicitly defined firstprivate clause
4060 // for task|target directives.
4061 // Skip analysis of arguments of implicitly defined map clause for target
4062 // directives.
4063 if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
4064 C->isImplicit() &&
4065 !isOpenMPTaskingDirective(Stack->getCurrentDirective()))) {
4066 for (Stmt *CC : C->children()) {
4067 if (CC)
4068 Visit(CC);
4069 }
4070 }
4071 }
4072 // Check implicitly captured variables.
4073 VisitSubCaptures(S);
4074 }
4075
VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective * S)4076 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) {
4077 // Loop transformation directives do not introduce data sharing
4078 VisitStmt(S);
4079 }
4080
VisitCallExpr(CallExpr * S)4081 void VisitCallExpr(CallExpr *S) {
4082 for (Stmt *C : S->arguments()) {
4083 if (C) {
4084 // Check implicitly captured variables in the task-based directives to
4085 // check if they must be firstprivatized.
4086 Visit(C);
4087 }
4088 }
4089 if (Expr *Callee = S->getCallee()) {
4090 auto *CI = Callee->IgnoreParenImpCasts();
4091 if (auto *CE = dyn_cast<MemberExpr>(CI))
4092 Visit(CE->getBase());
4093 else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4094 Visit(CE);
4095 }
4096 }
VisitStmt(Stmt * S)4097 void VisitStmt(Stmt *S) {
4098 for (Stmt *C : S->children()) {
4099 if (C) {
4100 // Check implicitly captured variables in the task-based directives to
4101 // check if they must be firstprivatized.
4102 Visit(C);
4103 }
4104 }
4105 }
4106
visitSubCaptures(CapturedStmt * S)4107 void visitSubCaptures(CapturedStmt *S) {
4108 for (const CapturedStmt::Capture &Cap : S->captures()) {
4109 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4110 continue;
4111 VarDecl *VD = Cap.getCapturedVar();
4112 // Do not try to map the variable if it or its sub-component was mapped
4113 // already.
4114 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
4115 Stack->checkMappableExprComponentListsForDecl(
4116 VD, /*CurrentRegionOnly=*/true,
4117 [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
4118 OpenMPClauseKind) { return true; }))
4119 continue;
4120 DeclRefExpr *DRE = buildDeclRefExpr(
4121 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4122 Cap.getLocation(), /*RefersToCapture=*/true);
4123 Visit(DRE);
4124 }
4125 }
isErrorFound() const4126 bool isErrorFound() const { return ErrorFound; }
getImplicitFirstprivate() const4127 ArrayRef<Expr *> getImplicitFirstprivate() const {
4128 return ImplicitFirstprivate;
4129 }
getImplicitPrivate() const4130 ArrayRef<Expr *> getImplicitPrivate() const { return ImplicitPrivate; }
getImplicitMap(OpenMPDefaultmapClauseKind DK,OpenMPMapClauseKind MK) const4131 ArrayRef<Expr *> getImplicitMap(OpenMPDefaultmapClauseKind DK,
4132 OpenMPMapClauseKind MK) const {
4133 return ImplicitMap[DK][MK];
4134 }
4135 ArrayRef<OpenMPMapModifierKind>
getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind) const4136 getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind) const {
4137 return ImplicitMapModifier[Kind];
4138 }
getVarsWithInheritedDSA() const4139 const Sema::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4140 return VarsWithInheritedDSA;
4141 }
4142
DSAAttrChecker(DSAStackTy * S,Sema & SemaRef,CapturedStmt * CS)4143 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4144 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4145 // Process declare target link variables for the target directives.
4146 if (isOpenMPTargetExecutionDirective(S->getCurrentDirective())) {
4147 for (DeclRefExpr *E : Stack->getLinkGlobals())
4148 Visit(E);
4149 }
4150 }
4151 };
4152 } // namespace
4153
handleDeclareVariantConstructTrait(DSAStackTy * Stack,OpenMPDirectiveKind DKind,bool ScopeEntry)4154 static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4155 OpenMPDirectiveKind DKind,
4156 bool ScopeEntry) {
4157 SmallVector<llvm::omp::TraitProperty, 8> Traits;
4158 if (isOpenMPTargetExecutionDirective(DKind))
4159 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4160 if (isOpenMPTeamsDirective(DKind))
4161 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4162 if (isOpenMPParallelDirective(DKind))
4163 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4164 if (isOpenMPWorksharingDirective(DKind))
4165 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4166 if (isOpenMPSimdDirective(DKind))
4167 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4168 Stack->handleConstructTrait(Traits, ScopeEntry);
4169 }
4170
ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind,Scope * CurScope)4171 void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
4172 switch (DKind) {
4173 case OMPD_parallel:
4174 case OMPD_parallel_for:
4175 case OMPD_parallel_for_simd:
4176 case OMPD_parallel_sections:
4177 case OMPD_parallel_master:
4178 case OMPD_parallel_masked:
4179 case OMPD_parallel_loop:
4180 case OMPD_teams:
4181 case OMPD_teams_distribute:
4182 case OMPD_teams_distribute_simd: {
4183 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4184 QualType KmpInt32PtrTy =
4185 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4186 Sema::CapturedParamNameType Params[] = {
4187 std::make_pair(".global_tid.", KmpInt32PtrTy),
4188 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4189 std::make_pair(StringRef(), QualType()) // __context with shared vars
4190 };
4191 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4192 Params);
4193 break;
4194 }
4195 case OMPD_target_teams:
4196 case OMPD_target_parallel:
4197 case OMPD_target_parallel_for:
4198 case OMPD_target_parallel_for_simd:
4199 case OMPD_target_teams_loop:
4200 case OMPD_target_parallel_loop:
4201 case OMPD_target_teams_distribute:
4202 case OMPD_target_teams_distribute_simd: {
4203 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4204 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4205 QualType KmpInt32PtrTy =
4206 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4207 QualType Args[] = {VoidPtrTy};
4208 FunctionProtoType::ExtProtoInfo EPI;
4209 EPI.Variadic = true;
4210 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4211 Sema::CapturedParamNameType Params[] = {
4212 std::make_pair(".global_tid.", KmpInt32Ty),
4213 std::make_pair(".part_id.", KmpInt32PtrTy),
4214 std::make_pair(".privates.", VoidPtrTy),
4215 std::make_pair(
4216 ".copy_fn.",
4217 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4218 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4219 std::make_pair(StringRef(), QualType()) // __context with shared vars
4220 };
4221 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4222 Params, /*OpenMPCaptureLevel=*/0);
4223 // Mark this captured region as inlined, because we don't use outlined
4224 // function directly.
4225 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4226 AlwaysInlineAttr::CreateImplicit(
4227 Context, {}, AttributeCommonInfo::AS_Keyword,
4228 AlwaysInlineAttr::Keyword_forceinline));
4229 Sema::CapturedParamNameType ParamsTarget[] = {
4230 std::make_pair(StringRef(), QualType()) // __context with shared vars
4231 };
4232 // Start a captured region for 'target' with no implicit parameters.
4233 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4234 ParamsTarget, /*OpenMPCaptureLevel=*/1);
4235 Sema::CapturedParamNameType ParamsTeamsOrParallel[] = {
4236 std::make_pair(".global_tid.", KmpInt32PtrTy),
4237 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4238 std::make_pair(StringRef(), QualType()) // __context with shared vars
4239 };
4240 // Start a captured region for 'teams' or 'parallel'. Both regions have
4241 // the same implicit parameters.
4242 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4243 ParamsTeamsOrParallel, /*OpenMPCaptureLevel=*/2);
4244 break;
4245 }
4246 case OMPD_target:
4247 case OMPD_target_simd: {
4248 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4249 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4250 QualType KmpInt32PtrTy =
4251 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4252 QualType Args[] = {VoidPtrTy};
4253 FunctionProtoType::ExtProtoInfo EPI;
4254 EPI.Variadic = true;
4255 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4256 Sema::CapturedParamNameType Params[] = {
4257 std::make_pair(".global_tid.", KmpInt32Ty),
4258 std::make_pair(".part_id.", KmpInt32PtrTy),
4259 std::make_pair(".privates.", VoidPtrTy),
4260 std::make_pair(
4261 ".copy_fn.",
4262 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4263 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4264 std::make_pair(StringRef(), QualType()) // __context with shared vars
4265 };
4266 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4267 Params, /*OpenMPCaptureLevel=*/0);
4268 // Mark this captured region as inlined, because we don't use outlined
4269 // function directly.
4270 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4271 AlwaysInlineAttr::CreateImplicit(
4272 Context, {}, AttributeCommonInfo::AS_Keyword,
4273 AlwaysInlineAttr::Keyword_forceinline));
4274 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4275 std::make_pair(StringRef(), QualType()),
4276 /*OpenMPCaptureLevel=*/1);
4277 break;
4278 }
4279 case OMPD_atomic:
4280 case OMPD_critical:
4281 case OMPD_section:
4282 case OMPD_master:
4283 case OMPD_masked:
4284 case OMPD_tile:
4285 case OMPD_unroll:
4286 break;
4287 case OMPD_loop:
4288 // TODO: 'loop' may require additional parameters depending on the binding.
4289 // Treat similar to OMPD_simd/OMPD_for for now.
4290 case OMPD_simd:
4291 case OMPD_for:
4292 case OMPD_for_simd:
4293 case OMPD_sections:
4294 case OMPD_single:
4295 case OMPD_taskgroup:
4296 case OMPD_distribute:
4297 case OMPD_distribute_simd:
4298 case OMPD_ordered:
4299 case OMPD_target_data:
4300 case OMPD_dispatch: {
4301 Sema::CapturedParamNameType Params[] = {
4302 std::make_pair(StringRef(), QualType()) // __context with shared vars
4303 };
4304 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4305 Params);
4306 break;
4307 }
4308 case OMPD_task: {
4309 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4310 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4311 QualType KmpInt32PtrTy =
4312 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4313 QualType Args[] = {VoidPtrTy};
4314 FunctionProtoType::ExtProtoInfo EPI;
4315 EPI.Variadic = true;
4316 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4317 Sema::CapturedParamNameType Params[] = {
4318 std::make_pair(".global_tid.", KmpInt32Ty),
4319 std::make_pair(".part_id.", KmpInt32PtrTy),
4320 std::make_pair(".privates.", VoidPtrTy),
4321 std::make_pair(
4322 ".copy_fn.",
4323 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4324 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4325 std::make_pair(StringRef(), QualType()) // __context with shared vars
4326 };
4327 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4328 Params);
4329 // Mark this captured region as inlined, because we don't use outlined
4330 // function directly.
4331 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4332 AlwaysInlineAttr::CreateImplicit(
4333 Context, {}, AttributeCommonInfo::AS_Keyword,
4334 AlwaysInlineAttr::Keyword_forceinline));
4335 break;
4336 }
4337 case OMPD_taskloop:
4338 case OMPD_taskloop_simd:
4339 case OMPD_master_taskloop:
4340 case OMPD_masked_taskloop:
4341 case OMPD_masked_taskloop_simd:
4342 case OMPD_master_taskloop_simd: {
4343 QualType KmpInt32Ty =
4344 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4345 .withConst();
4346 QualType KmpUInt64Ty =
4347 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4348 .withConst();
4349 QualType KmpInt64Ty =
4350 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4351 .withConst();
4352 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4353 QualType KmpInt32PtrTy =
4354 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4355 QualType Args[] = {VoidPtrTy};
4356 FunctionProtoType::ExtProtoInfo EPI;
4357 EPI.Variadic = true;
4358 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4359 Sema::CapturedParamNameType Params[] = {
4360 std::make_pair(".global_tid.", KmpInt32Ty),
4361 std::make_pair(".part_id.", KmpInt32PtrTy),
4362 std::make_pair(".privates.", VoidPtrTy),
4363 std::make_pair(
4364 ".copy_fn.",
4365 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4366 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4367 std::make_pair(".lb.", KmpUInt64Ty),
4368 std::make_pair(".ub.", KmpUInt64Ty),
4369 std::make_pair(".st.", KmpInt64Ty),
4370 std::make_pair(".liter.", KmpInt32Ty),
4371 std::make_pair(".reductions.", VoidPtrTy),
4372 std::make_pair(StringRef(), QualType()) // __context with shared vars
4373 };
4374 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4375 Params);
4376 // Mark this captured region as inlined, because we don't use outlined
4377 // function directly.
4378 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4379 AlwaysInlineAttr::CreateImplicit(
4380 Context, {}, AttributeCommonInfo::AS_Keyword,
4381 AlwaysInlineAttr::Keyword_forceinline));
4382 break;
4383 }
4384 case OMPD_parallel_masked_taskloop:
4385 case OMPD_parallel_masked_taskloop_simd:
4386 case OMPD_parallel_master_taskloop:
4387 case OMPD_parallel_master_taskloop_simd: {
4388 QualType KmpInt32Ty =
4389 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4390 .withConst();
4391 QualType KmpUInt64Ty =
4392 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4393 .withConst();
4394 QualType KmpInt64Ty =
4395 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4396 .withConst();
4397 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4398 QualType KmpInt32PtrTy =
4399 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4400 Sema::CapturedParamNameType ParamsParallel[] = {
4401 std::make_pair(".global_tid.", KmpInt32PtrTy),
4402 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4403 std::make_pair(StringRef(), QualType()) // __context with shared vars
4404 };
4405 // Start a captured region for 'parallel'.
4406 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4407 ParamsParallel, /*OpenMPCaptureLevel=*/0);
4408 QualType Args[] = {VoidPtrTy};
4409 FunctionProtoType::ExtProtoInfo EPI;
4410 EPI.Variadic = true;
4411 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4412 Sema::CapturedParamNameType Params[] = {
4413 std::make_pair(".global_tid.", KmpInt32Ty),
4414 std::make_pair(".part_id.", KmpInt32PtrTy),
4415 std::make_pair(".privates.", VoidPtrTy),
4416 std::make_pair(
4417 ".copy_fn.",
4418 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4419 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4420 std::make_pair(".lb.", KmpUInt64Ty),
4421 std::make_pair(".ub.", KmpUInt64Ty),
4422 std::make_pair(".st.", KmpInt64Ty),
4423 std::make_pair(".liter.", KmpInt32Ty),
4424 std::make_pair(".reductions.", VoidPtrTy),
4425 std::make_pair(StringRef(), QualType()) // __context with shared vars
4426 };
4427 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4428 Params, /*OpenMPCaptureLevel=*/1);
4429 // Mark this captured region as inlined, because we don't use outlined
4430 // function directly.
4431 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4432 AlwaysInlineAttr::CreateImplicit(
4433 Context, {}, AttributeCommonInfo::AS_Keyword,
4434 AlwaysInlineAttr::Keyword_forceinline));
4435 break;
4436 }
4437 case OMPD_distribute_parallel_for_simd:
4438 case OMPD_distribute_parallel_for: {
4439 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4440 QualType KmpInt32PtrTy =
4441 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4442 Sema::CapturedParamNameType Params[] = {
4443 std::make_pair(".global_tid.", KmpInt32PtrTy),
4444 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4445 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4446 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4447 std::make_pair(StringRef(), QualType()) // __context with shared vars
4448 };
4449 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4450 Params);
4451 break;
4452 }
4453 case OMPD_target_teams_distribute_parallel_for:
4454 case OMPD_target_teams_distribute_parallel_for_simd: {
4455 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4456 QualType KmpInt32PtrTy =
4457 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4458 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4459
4460 QualType Args[] = {VoidPtrTy};
4461 FunctionProtoType::ExtProtoInfo EPI;
4462 EPI.Variadic = true;
4463 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4464 Sema::CapturedParamNameType Params[] = {
4465 std::make_pair(".global_tid.", KmpInt32Ty),
4466 std::make_pair(".part_id.", KmpInt32PtrTy),
4467 std::make_pair(".privates.", VoidPtrTy),
4468 std::make_pair(
4469 ".copy_fn.",
4470 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4471 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4472 std::make_pair(StringRef(), QualType()) // __context with shared vars
4473 };
4474 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4475 Params, /*OpenMPCaptureLevel=*/0);
4476 // Mark this captured region as inlined, because we don't use outlined
4477 // function directly.
4478 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4479 AlwaysInlineAttr::CreateImplicit(
4480 Context, {}, AttributeCommonInfo::AS_Keyword,
4481 AlwaysInlineAttr::Keyword_forceinline));
4482 Sema::CapturedParamNameType ParamsTarget[] = {
4483 std::make_pair(StringRef(), QualType()) // __context with shared vars
4484 };
4485 // Start a captured region for 'target' with no implicit parameters.
4486 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4487 ParamsTarget, /*OpenMPCaptureLevel=*/1);
4488
4489 Sema::CapturedParamNameType ParamsTeams[] = {
4490 std::make_pair(".global_tid.", KmpInt32PtrTy),
4491 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4492 std::make_pair(StringRef(), QualType()) // __context with shared vars
4493 };
4494 // Start a captured region for 'target' with no implicit parameters.
4495 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4496 ParamsTeams, /*OpenMPCaptureLevel=*/2);
4497
4498 Sema::CapturedParamNameType ParamsParallel[] = {
4499 std::make_pair(".global_tid.", KmpInt32PtrTy),
4500 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4501 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4502 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4503 std::make_pair(StringRef(), QualType()) // __context with shared vars
4504 };
4505 // Start a captured region for 'teams' or 'parallel'. Both regions have
4506 // the same implicit parameters.
4507 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4508 ParamsParallel, /*OpenMPCaptureLevel=*/3);
4509 break;
4510 }
4511
4512 case OMPD_teams_loop: {
4513 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4514 QualType KmpInt32PtrTy =
4515 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4516
4517 Sema::CapturedParamNameType ParamsTeams[] = {
4518 std::make_pair(".global_tid.", KmpInt32PtrTy),
4519 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4520 std::make_pair(StringRef(), QualType()) // __context with shared vars
4521 };
4522 // Start a captured region for 'teams'.
4523 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4524 ParamsTeams, /*OpenMPCaptureLevel=*/0);
4525 break;
4526 }
4527
4528 case OMPD_teams_distribute_parallel_for:
4529 case OMPD_teams_distribute_parallel_for_simd: {
4530 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4531 QualType KmpInt32PtrTy =
4532 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4533
4534 Sema::CapturedParamNameType ParamsTeams[] = {
4535 std::make_pair(".global_tid.", KmpInt32PtrTy),
4536 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4537 std::make_pair(StringRef(), QualType()) // __context with shared vars
4538 };
4539 // Start a captured region for 'target' with no implicit parameters.
4540 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4541 ParamsTeams, /*OpenMPCaptureLevel=*/0);
4542
4543 Sema::CapturedParamNameType ParamsParallel[] = {
4544 std::make_pair(".global_tid.", KmpInt32PtrTy),
4545 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4546 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4547 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4548 std::make_pair(StringRef(), QualType()) // __context with shared vars
4549 };
4550 // Start a captured region for 'teams' or 'parallel'. Both regions have
4551 // the same implicit parameters.
4552 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4553 ParamsParallel, /*OpenMPCaptureLevel=*/1);
4554 break;
4555 }
4556 case OMPD_target_update:
4557 case OMPD_target_enter_data:
4558 case OMPD_target_exit_data: {
4559 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4560 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4561 QualType KmpInt32PtrTy =
4562 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4563 QualType Args[] = {VoidPtrTy};
4564 FunctionProtoType::ExtProtoInfo EPI;
4565 EPI.Variadic = true;
4566 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4567 Sema::CapturedParamNameType Params[] = {
4568 std::make_pair(".global_tid.", KmpInt32Ty),
4569 std::make_pair(".part_id.", KmpInt32PtrTy),
4570 std::make_pair(".privates.", VoidPtrTy),
4571 std::make_pair(
4572 ".copy_fn.",
4573 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4574 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4575 std::make_pair(StringRef(), QualType()) // __context with shared vars
4576 };
4577 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4578 Params);
4579 // Mark this captured region as inlined, because we don't use outlined
4580 // function directly.
4581 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4582 AlwaysInlineAttr::CreateImplicit(
4583 Context, {}, AttributeCommonInfo::AS_Keyword,
4584 AlwaysInlineAttr::Keyword_forceinline));
4585 break;
4586 }
4587 case OMPD_threadprivate:
4588 case OMPD_allocate:
4589 case OMPD_taskyield:
4590 case OMPD_error:
4591 case OMPD_barrier:
4592 case OMPD_taskwait:
4593 case OMPD_cancellation_point:
4594 case OMPD_cancel:
4595 case OMPD_flush:
4596 case OMPD_depobj:
4597 case OMPD_scan:
4598 case OMPD_declare_reduction:
4599 case OMPD_declare_mapper:
4600 case OMPD_declare_simd:
4601 case OMPD_declare_target:
4602 case OMPD_end_declare_target:
4603 case OMPD_requires:
4604 case OMPD_declare_variant:
4605 case OMPD_begin_declare_variant:
4606 case OMPD_end_declare_variant:
4607 case OMPD_metadirective:
4608 llvm_unreachable("OpenMP Directive is not allowed");
4609 case OMPD_unknown:
4610 default:
4611 llvm_unreachable("Unknown OpenMP directive");
4612 }
4613 DSAStack->setContext(CurContext);
4614 handleDeclareVariantConstructTrait(DSAStack, DKind, /* ScopeEntry */ true);
4615 }
4616
getNumberOfConstructScopes(unsigned Level) const4617 int Sema::getNumberOfConstructScopes(unsigned Level) const {
4618 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4619 }
4620
getOpenMPCaptureLevels(OpenMPDirectiveKind DKind)4621 int Sema::getOpenMPCaptureLevels(OpenMPDirectiveKind DKind) {
4622 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4623 getOpenMPCaptureRegions(CaptureRegions, DKind);
4624 return CaptureRegions.size();
4625 }
4626
buildCaptureDecl(Sema & S,IdentifierInfo * Id,Expr * CaptureExpr,bool WithInit,DeclContext * CurContext,bool AsExpression)4627 static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
4628 Expr *CaptureExpr, bool WithInit,
4629 DeclContext *CurContext,
4630 bool AsExpression) {
4631 assert(CaptureExpr);
4632 ASTContext &C = S.getASTContext();
4633 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4634 QualType Ty = Init->getType();
4635 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4636 if (S.getLangOpts().CPlusPlus) {
4637 Ty = C.getLValueReferenceType(Ty);
4638 } else {
4639 Ty = C.getPointerType(Ty);
4640 ExprResult Res =
4641 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4642 if (!Res.isUsable())
4643 return nullptr;
4644 Init = Res.get();
4645 }
4646 WithInit = true;
4647 }
4648 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4649 CaptureExpr->getBeginLoc());
4650 if (!WithInit)
4651 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4652 CurContext->addHiddenDecl(CED);
4653 Sema::TentativeAnalysisScope Trap(S);
4654 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4655 return CED;
4656 }
4657
buildCapture(Sema & S,ValueDecl * D,Expr * CaptureExpr,bool WithInit)4658 static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4659 bool WithInit) {
4660 OMPCapturedExprDecl *CD;
4661 if (VarDecl *VD = S.isOpenMPCapturedDecl(D))
4662 CD = cast<OMPCapturedExprDecl>(VD);
4663 else
4664 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4665 S.CurContext,
4666 /*AsExpression=*/false);
4667 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4668 CaptureExpr->getExprLoc());
4669 }
4670
buildCapture(Sema & S,Expr * CaptureExpr,DeclRefExpr * & Ref)4671 static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref) {
4672 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4673 if (!Ref) {
4674 OMPCapturedExprDecl *CD = buildCaptureDecl(
4675 S, &S.getASTContext().Idents.get(".capture_expr."), CaptureExpr,
4676 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4677 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4678 CaptureExpr->getExprLoc());
4679 }
4680 ExprResult Res = Ref;
4681 if (!S.getLangOpts().CPlusPlus &&
4682 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4683 Ref->getType()->isPointerType()) {
4684 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4685 if (!Res.isUsable())
4686 return ExprError();
4687 }
4688 return S.DefaultLvalueConversion(Res.get());
4689 }
4690
4691 namespace {
4692 // OpenMP directives parsed in this section are represented as a
4693 // CapturedStatement with an associated statement. If a syntax error
4694 // is detected during the parsing of the associated statement, the
4695 // compiler must abort processing and close the CapturedStatement.
4696 //
4697 // Combined directives such as 'target parallel' have more than one
4698 // nested CapturedStatements. This RAII ensures that we unwind out
4699 // of all the nested CapturedStatements when an error is found.
4700 class CaptureRegionUnwinderRAII {
4701 private:
4702 Sema &S;
4703 bool &ErrorFound;
4704 OpenMPDirectiveKind DKind = OMPD_unknown;
4705
4706 public:
CaptureRegionUnwinderRAII(Sema & S,bool & ErrorFound,OpenMPDirectiveKind DKind)4707 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4708 OpenMPDirectiveKind DKind)
4709 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
~CaptureRegionUnwinderRAII()4710 ~CaptureRegionUnwinderRAII() {
4711 if (ErrorFound) {
4712 int ThisCaptureLevel = S.getOpenMPCaptureLevels(DKind);
4713 while (--ThisCaptureLevel >= 0)
4714 S.ActOnCapturedRegionError();
4715 }
4716 }
4717 };
4718 } // namespace
4719
tryCaptureOpenMPLambdas(ValueDecl * V)4720 void Sema::tryCaptureOpenMPLambdas(ValueDecl *V) {
4721 // Capture variables captured by reference in lambdas for target-based
4722 // directives.
4723 if (!CurContext->isDependentContext() &&
4724 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4725 isOpenMPTargetDataManagementDirective(
4726 DSAStack->getCurrentDirective()))) {
4727 QualType Type = V->getType();
4728 if (const auto *RD = Type.getCanonicalType()
4729 .getNonReferenceType()
4730 ->getAsCXXRecordDecl()) {
4731 bool SavedForceCaptureByReferenceInTargetExecutable =
4732 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4733 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4734 /*V=*/true);
4735 if (RD->isLambda()) {
4736 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4737 FieldDecl *ThisCapture;
4738 RD->getCaptureFields(Captures, ThisCapture);
4739 for (const LambdaCapture &LC : RD->captures()) {
4740 if (LC.getCaptureKind() == LCK_ByRef) {
4741 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4742 DeclContext *VDC = VD->getDeclContext();
4743 if (!VDC->Encloses(CurContext))
4744 continue;
4745 MarkVariableReferenced(LC.getLocation(), VD);
4746 } else if (LC.getCaptureKind() == LCK_This) {
4747 QualType ThisTy = getCurrentThisType();
4748 if (!ThisTy.isNull() &&
4749 Context.typesAreCompatible(ThisTy, ThisCapture->getType()))
4750 CheckCXXThisCapture(LC.getLocation());
4751 }
4752 }
4753 }
4754 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4755 SavedForceCaptureByReferenceInTargetExecutable);
4756 }
4757 }
4758 }
4759
checkOrderedOrderSpecified(Sema & S,const ArrayRef<OMPClause * > Clauses)4760 static bool checkOrderedOrderSpecified(Sema &S,
4761 const ArrayRef<OMPClause *> Clauses) {
4762 const OMPOrderedClause *Ordered = nullptr;
4763 const OMPOrderClause *Order = nullptr;
4764
4765 for (const OMPClause *Clause : Clauses) {
4766 if (Clause->getClauseKind() == OMPC_ordered)
4767 Ordered = cast<OMPOrderedClause>(Clause);
4768 else if (Clause->getClauseKind() == OMPC_order) {
4769 Order = cast<OMPOrderClause>(Clause);
4770 if (Order->getKind() != OMPC_ORDER_concurrent)
4771 Order = nullptr;
4772 }
4773 if (Ordered && Order)
4774 break;
4775 }
4776
4777 if (Ordered && Order) {
4778 S.Diag(Order->getKindKwLoc(),
4779 diag::err_omp_simple_clause_incompatible_with_ordered)
4780 << getOpenMPClauseName(OMPC_order)
4781 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4782 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4783 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4784 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4785 return true;
4786 }
4787 return false;
4788 }
4789
ActOnOpenMPRegionEnd(StmtResult S,ArrayRef<OMPClause * > Clauses)4790 StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
4791 ArrayRef<OMPClause *> Clauses) {
4792 handleDeclareVariantConstructTrait(DSAStack, DSAStack->getCurrentDirective(),
4793 /* ScopeEntry */ false);
4794 if (DSAStack->getCurrentDirective() == OMPD_atomic ||
4795 DSAStack->getCurrentDirective() == OMPD_critical ||
4796 DSAStack->getCurrentDirective() == OMPD_section ||
4797 DSAStack->getCurrentDirective() == OMPD_master ||
4798 DSAStack->getCurrentDirective() == OMPD_masked)
4799 return S;
4800
4801 bool ErrorFound = false;
4802 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4803 *this, ErrorFound, DSAStack->getCurrentDirective());
4804 if (!S.isUsable()) {
4805 ErrorFound = true;
4806 return StmtError();
4807 }
4808
4809 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4810 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4811 OMPOrderedClause *OC = nullptr;
4812 OMPScheduleClause *SC = nullptr;
4813 SmallVector<const OMPLinearClause *, 4> LCs;
4814 SmallVector<const OMPClauseWithPreInit *, 4> PICs;
4815 // This is required for proper codegen.
4816 for (OMPClause *Clause : Clauses) {
4817 if (!LangOpts.OpenMPSimd &&
4818 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4819 DSAStack->getCurrentDirective() == OMPD_target) &&
4820 Clause->getClauseKind() == OMPC_in_reduction) {
4821 // Capture taskgroup task_reduction descriptors inside the tasking regions
4822 // with the corresponding in_reduction items.
4823 auto *IRC = cast<OMPInReductionClause>(Clause);
4824 for (Expr *E : IRC->taskgroup_descriptors())
4825 if (E)
4826 MarkDeclarationsReferencedInExpr(E);
4827 }
4828 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4829 Clause->getClauseKind() == OMPC_copyprivate ||
4830 (getLangOpts().OpenMPUseTLS &&
4831 getASTContext().getTargetInfo().isTLSSupported() &&
4832 Clause->getClauseKind() == OMPC_copyin)) {
4833 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4834 // Mark all variables in private list clauses as used in inner region.
4835 for (Stmt *VarRef : Clause->children()) {
4836 if (auto *E = cast_or_null<Expr>(VarRef)) {
4837 MarkDeclarationsReferencedInExpr(E);
4838 }
4839 }
4840 DSAStack->setForceVarCapturing(/*V=*/false);
4841 } else if (isOpenMPLoopTransformationDirective(
4842 DSAStack->getCurrentDirective())) {
4843 assert(CaptureRegions.empty() &&
4844 "No captured regions in loop transformation directives.");
4845 } else if (CaptureRegions.size() > 1 ||
4846 CaptureRegions.back() != OMPD_unknown) {
4847 if (auto *C = OMPClauseWithPreInit::get(Clause))
4848 PICs.push_back(C);
4849 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4850 if (Expr *E = C->getPostUpdateExpr())
4851 MarkDeclarationsReferencedInExpr(E);
4852 }
4853 }
4854 if (Clause->getClauseKind() == OMPC_schedule)
4855 SC = cast<OMPScheduleClause>(Clause);
4856 else if (Clause->getClauseKind() == OMPC_ordered)
4857 OC = cast<OMPOrderedClause>(Clause);
4858 else if (Clause->getClauseKind() == OMPC_linear)
4859 LCs.push_back(cast<OMPLinearClause>(Clause));
4860 }
4861 // Capture allocator expressions if used.
4862 for (Expr *E : DSAStack->getInnerAllocators())
4863 MarkDeclarationsReferencedInExpr(E);
4864 // OpenMP, 2.7.1 Loop Construct, Restrictions
4865 // The nonmonotonic modifier cannot be specified if an ordered clause is
4866 // specified.
4867 if (SC &&
4868 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4869 SC->getSecondScheduleModifier() ==
4870 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4871 OC) {
4872 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4873 ? SC->getFirstScheduleModifierLoc()
4874 : SC->getSecondScheduleModifierLoc(),
4875 diag::err_omp_simple_clause_incompatible_with_ordered)
4876 << getOpenMPClauseName(OMPC_schedule)
4877 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4878 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4879 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4880 ErrorFound = true;
4881 }
4882 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4883 // If an order(concurrent) clause is present, an ordered clause may not appear
4884 // on the same directive.
4885 if (checkOrderedOrderSpecified(*this, Clauses))
4886 ErrorFound = true;
4887 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4888 for (const OMPLinearClause *C : LCs) {
4889 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4890 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4891 }
4892 ErrorFound = true;
4893 }
4894 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4895 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4896 OC->getNumForLoops()) {
4897 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4898 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
4899 ErrorFound = true;
4900 }
4901 if (ErrorFound) {
4902 return StmtError();
4903 }
4904 StmtResult SR = S;
4905 unsigned CompletedRegions = 0;
4906 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4907 // Mark all variables in private list clauses as used in inner region.
4908 // Required for proper codegen of combined directives.
4909 // TODO: add processing for other clauses.
4910 if (ThisCaptureRegion != OMPD_unknown) {
4911 for (const clang::OMPClauseWithPreInit *C : PICs) {
4912 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4913 // Find the particular capture region for the clause if the
4914 // directive is a combined one with multiple capture regions.
4915 // If the directive is not a combined one, the capture region
4916 // associated with the clause is OMPD_unknown and is generated
4917 // only once.
4918 if (CaptureRegion == ThisCaptureRegion ||
4919 CaptureRegion == OMPD_unknown) {
4920 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4921 for (Decl *D : DS->decls())
4922 MarkVariableReferenced(D->getLocation(), cast<VarDecl>(D));
4923 }
4924 }
4925 }
4926 }
4927 if (ThisCaptureRegion == OMPD_target) {
4928 // Capture allocator traits in the target region. They are used implicitly
4929 // and, thus, are not captured by default.
4930 for (OMPClause *C : Clauses) {
4931 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4932 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4933 ++I) {
4934 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4935 if (Expr *E = D.AllocatorTraits)
4936 MarkDeclarationsReferencedInExpr(E);
4937 }
4938 continue;
4939 }
4940 }
4941 }
4942 if (ThisCaptureRegion == OMPD_parallel) {
4943 // Capture temp arrays for inscan reductions and locals in aligned
4944 // clauses.
4945 for (OMPClause *C : Clauses) {
4946 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4947 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4948 continue;
4949 for (Expr *E : RC->copy_array_temps())
4950 MarkDeclarationsReferencedInExpr(E);
4951 }
4952 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4953 for (Expr *E : AC->varlists())
4954 MarkDeclarationsReferencedInExpr(E);
4955 }
4956 }
4957 }
4958 if (++CompletedRegions == CaptureRegions.size())
4959 DSAStack->setBodyComplete();
4960 SR = ActOnCapturedRegionEnd(SR.get());
4961 }
4962 return SR;
4963 }
4964
checkCancelRegion(Sema & SemaRef,OpenMPDirectiveKind CurrentRegion,OpenMPDirectiveKind CancelRegion,SourceLocation StartLoc)4965 static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4966 OpenMPDirectiveKind CancelRegion,
4967 SourceLocation StartLoc) {
4968 // CancelRegion is only needed for cancel and cancellation_point.
4969 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4970 return false;
4971
4972 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4973 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4974 return false;
4975
4976 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4977 << getOpenMPDirectiveName(CancelRegion);
4978 return true;
4979 }
4980
checkNestingOfRegions(Sema & SemaRef,const DSAStackTy * Stack,OpenMPDirectiveKind CurrentRegion,const DeclarationNameInfo & CurrentName,OpenMPDirectiveKind CancelRegion,OpenMPBindClauseKind BindKind,SourceLocation StartLoc)4981 static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4982 OpenMPDirectiveKind CurrentRegion,
4983 const DeclarationNameInfo &CurrentName,
4984 OpenMPDirectiveKind CancelRegion,
4985 OpenMPBindClauseKind BindKind,
4986 SourceLocation StartLoc) {
4987 if (Stack->getCurScope()) {
4988 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4989 OpenMPDirectiveKind OffendingRegion = ParentRegion;
4990 bool NestingProhibited = false;
4991 bool CloseNesting = true;
4992 bool OrphanSeen = false;
4993 enum {
4994 NoRecommend,
4995 ShouldBeInParallelRegion,
4996 ShouldBeInOrderedRegion,
4997 ShouldBeInTargetRegion,
4998 ShouldBeInTeamsRegion,
4999 ShouldBeInLoopSimdRegion,
5000 } Recommend = NoRecommend;
5001 if (SemaRef.LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() &&
5002 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop &&
5003 CurrentRegion != OMPD_parallel &&
5004 !isOpenMPCombinedParallelADirective(CurrentRegion)) {
5005 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
5006 << getOpenMPDirectiveName(CurrentRegion);
5007 return true;
5008 }
5009 if (isOpenMPSimdDirective(ParentRegion) &&
5010 ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
5011 (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
5012 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
5013 CurrentRegion != OMPD_scan))) {
5014 // OpenMP [2.16, Nesting of Regions]
5015 // OpenMP constructs may not be nested inside a simd region.
5016 // OpenMP [2.8.1,simd Construct, Restrictions]
5017 // An ordered construct with the simd clause is the only OpenMP
5018 // construct that can appear in the simd region.
5019 // Allowing a SIMD construct nested in another SIMD construct is an
5020 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
5021 // message.
5022 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
5023 // The only OpenMP constructs that can be encountered during execution of
5024 // a simd region are the atomic construct, the loop construct, the simd
5025 // construct and the ordered construct with the simd clause.
5026 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
5027 ? diag::err_omp_prohibited_region_simd
5028 : diag::warn_omp_nesting_simd)
5029 << (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0);
5030 return CurrentRegion != OMPD_simd;
5031 }
5032 if (ParentRegion == OMPD_atomic) {
5033 // OpenMP [2.16, Nesting of Regions]
5034 // OpenMP constructs may not be nested inside an atomic region.
5035 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
5036 return true;
5037 }
5038 if (CurrentRegion == OMPD_section) {
5039 // OpenMP [2.7.2, sections Construct, Restrictions]
5040 // Orphaned section directives are prohibited. That is, the section
5041 // directives must appear within the sections construct and must not be
5042 // encountered elsewhere in the sections region.
5043 if (ParentRegion != OMPD_sections &&
5044 ParentRegion != OMPD_parallel_sections) {
5045 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
5046 << (ParentRegion != OMPD_unknown)
5047 << getOpenMPDirectiveName(ParentRegion);
5048 return true;
5049 }
5050 return false;
5051 }
5052 // Allow some constructs (except teams and cancellation constructs) to be
5053 // orphaned (they could be used in functions, called from OpenMP regions
5054 // with the required preconditions).
5055 if (ParentRegion == OMPD_unknown &&
5056 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
5057 CurrentRegion != OMPD_cancellation_point &&
5058 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5059 return false;
5060 if (CurrentRegion == OMPD_cancellation_point ||
5061 CurrentRegion == OMPD_cancel) {
5062 // OpenMP [2.16, Nesting of Regions]
5063 // A cancellation point construct for which construct-type-clause is
5064 // taskgroup must be nested inside a task construct. A cancellation
5065 // point construct for which construct-type-clause is not taskgroup must
5066 // be closely nested inside an OpenMP construct that matches the type
5067 // specified in construct-type-clause.
5068 // A cancel construct for which construct-type-clause is taskgroup must be
5069 // nested inside a task construct. A cancel construct for which
5070 // construct-type-clause is not taskgroup must be closely nested inside an
5071 // OpenMP construct that matches the type specified in
5072 // construct-type-clause.
5073 NestingProhibited =
5074 !((CancelRegion == OMPD_parallel &&
5075 (ParentRegion == OMPD_parallel ||
5076 ParentRegion == OMPD_target_parallel)) ||
5077 (CancelRegion == OMPD_for &&
5078 (ParentRegion == OMPD_for || ParentRegion == OMPD_parallel_for ||
5079 ParentRegion == OMPD_target_parallel_for ||
5080 ParentRegion == OMPD_distribute_parallel_for ||
5081 ParentRegion == OMPD_teams_distribute_parallel_for ||
5082 ParentRegion == OMPD_target_teams_distribute_parallel_for)) ||
5083 (CancelRegion == OMPD_taskgroup &&
5084 (ParentRegion == OMPD_task ||
5085 (SemaRef.getLangOpts().OpenMP >= 50 &&
5086 (ParentRegion == OMPD_taskloop ||
5087 ParentRegion == OMPD_master_taskloop ||
5088 ParentRegion == OMPD_masked_taskloop ||
5089 ParentRegion == OMPD_parallel_masked_taskloop ||
5090 ParentRegion == OMPD_parallel_master_taskloop)))) ||
5091 (CancelRegion == OMPD_sections &&
5092 (ParentRegion == OMPD_section || ParentRegion == OMPD_sections ||
5093 ParentRegion == OMPD_parallel_sections)));
5094 OrphanSeen = ParentRegion == OMPD_unknown;
5095 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5096 // OpenMP 5.1 [2.22, Nesting of Regions]
5097 // A masked region may not be closely nested inside a worksharing, loop,
5098 // atomic, task, or taskloop region.
5099 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5100 isOpenMPGenericLoopDirective(ParentRegion) ||
5101 isOpenMPTaskingDirective(ParentRegion);
5102 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5103 // OpenMP [2.16, Nesting of Regions]
5104 // A critical region may not be nested (closely or otherwise) inside a
5105 // critical region with the same name. Note that this restriction is not
5106 // sufficient to prevent deadlock.
5107 SourceLocation PreviousCriticalLoc;
5108 bool DeadLock = Stack->hasDirective(
5109 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5110 const DeclarationNameInfo &DNI,
5111 SourceLocation Loc) {
5112 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5113 PreviousCriticalLoc = Loc;
5114 return true;
5115 }
5116 return false;
5117 },
5118 false /* skip top directive */);
5119 if (DeadLock) {
5120 SemaRef.Diag(StartLoc,
5121 diag::err_omp_prohibited_region_critical_same_name)
5122 << CurrentName.getName();
5123 if (PreviousCriticalLoc.isValid())
5124 SemaRef.Diag(PreviousCriticalLoc,
5125 diag::note_omp_previous_critical_region);
5126 return true;
5127 }
5128 } else if (CurrentRegion == OMPD_barrier) {
5129 // OpenMP 5.1 [2.22, Nesting of Regions]
5130 // A barrier region may not be closely nested inside a worksharing, loop,
5131 // task, taskloop, critical, ordered, atomic, or masked region.
5132 NestingProhibited =
5133 isOpenMPWorksharingDirective(ParentRegion) ||
5134 isOpenMPGenericLoopDirective(ParentRegion) ||
5135 isOpenMPTaskingDirective(ParentRegion) ||
5136 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5137 ParentRegion == OMPD_parallel_master ||
5138 ParentRegion == OMPD_parallel_masked ||
5139 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5140 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
5141 !isOpenMPParallelDirective(CurrentRegion) &&
5142 !isOpenMPTeamsDirective(CurrentRegion)) {
5143 // OpenMP 5.1 [2.22, Nesting of Regions]
5144 // A loop region that binds to a parallel region or a worksharing region
5145 // may not be closely nested inside a worksharing, loop, task, taskloop,
5146 // critical, ordered, atomic, or masked region.
5147 NestingProhibited =
5148 isOpenMPWorksharingDirective(ParentRegion) ||
5149 isOpenMPGenericLoopDirective(ParentRegion) ||
5150 isOpenMPTaskingDirective(ParentRegion) ||
5151 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5152 ParentRegion == OMPD_parallel_master ||
5153 ParentRegion == OMPD_parallel_masked ||
5154 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5155 Recommend = ShouldBeInParallelRegion;
5156 } else if (CurrentRegion == OMPD_ordered) {
5157 // OpenMP [2.16, Nesting of Regions]
5158 // An ordered region may not be closely nested inside a critical,
5159 // atomic, or explicit task region.
5160 // An ordered region must be closely nested inside a loop region (or
5161 // parallel loop region) with an ordered clause.
5162 // OpenMP [2.8.1,simd Construct, Restrictions]
5163 // An ordered construct with the simd clause is the only OpenMP construct
5164 // that can appear in the simd region.
5165 NestingProhibited = ParentRegion == OMPD_critical ||
5166 isOpenMPTaskingDirective(ParentRegion) ||
5167 !(isOpenMPSimdDirective(ParentRegion) ||
5168 Stack->isParentOrderedRegion());
5169 Recommend = ShouldBeInOrderedRegion;
5170 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
5171 // OpenMP [2.16, Nesting of Regions]
5172 // If specified, a teams construct must be contained within a target
5173 // construct.
5174 NestingProhibited =
5175 (SemaRef.LangOpts.OpenMP <= 45 && ParentRegion != OMPD_target) ||
5176 (SemaRef.LangOpts.OpenMP >= 50 && ParentRegion != OMPD_unknown &&
5177 ParentRegion != OMPD_target);
5178 OrphanSeen = ParentRegion == OMPD_unknown;
5179 Recommend = ShouldBeInTargetRegion;
5180 } else if (CurrentRegion == OMPD_scan) {
5181 // OpenMP [2.16, Nesting of Regions]
5182 // If specified, a teams construct must be contained within a target
5183 // construct.
5184 NestingProhibited =
5185 SemaRef.LangOpts.OpenMP < 50 ||
5186 (ParentRegion != OMPD_simd && ParentRegion != OMPD_for &&
5187 ParentRegion != OMPD_for_simd && ParentRegion != OMPD_parallel_for &&
5188 ParentRegion != OMPD_parallel_for_simd);
5189 OrphanSeen = ParentRegion == OMPD_unknown;
5190 Recommend = ShouldBeInLoopSimdRegion;
5191 }
5192 if (!NestingProhibited &&
5193 !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5194 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5195 (ParentRegion == OMPD_teams || ParentRegion == OMPD_target_teams)) {
5196 // OpenMP [5.1, 2.22, Nesting of Regions]
5197 // distribute, distribute simd, distribute parallel worksharing-loop,
5198 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5199 // including any parallel regions arising from combined constructs,
5200 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5201 // only OpenMP regions that may be strictly nested inside the teams
5202 // region.
5203 //
5204 // As an extension, we permit atomic within teams as well.
5205 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5206 !isOpenMPDistributeDirective(CurrentRegion) &&
5207 CurrentRegion != OMPD_loop &&
5208 !(SemaRef.getLangOpts().OpenMPExtensions &&
5209 CurrentRegion == OMPD_atomic);
5210 Recommend = ShouldBeInParallelRegion;
5211 }
5212 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5213 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5214 // If the bind clause is present on the loop construct and binding is
5215 // teams then the corresponding loop region must be strictly nested inside
5216 // a teams region.
5217 NestingProhibited = BindKind == OMPC_BIND_teams &&
5218 ParentRegion != OMPD_teams &&
5219 ParentRegion != OMPD_target_teams;
5220 Recommend = ShouldBeInTeamsRegion;
5221 }
5222 if (!NestingProhibited &&
5223 isOpenMPNestingDistributeDirective(CurrentRegion)) {
5224 // OpenMP 4.5 [2.17 Nesting of Regions]
5225 // The region associated with the distribute construct must be strictly
5226 // nested inside a teams region
5227 NestingProhibited =
5228 (ParentRegion != OMPD_teams && ParentRegion != OMPD_target_teams);
5229 Recommend = ShouldBeInTeamsRegion;
5230 }
5231 if (!NestingProhibited &&
5232 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5233 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5234 // OpenMP 4.5 [2.17 Nesting of Regions]
5235 // If a target, target update, target data, target enter data, or
5236 // target exit data construct is encountered during execution of a
5237 // target region, the behavior is unspecified.
5238 NestingProhibited = Stack->hasDirective(
5239 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5240 SourceLocation) {
5241 if (isOpenMPTargetExecutionDirective(K)) {
5242 OffendingRegion = K;
5243 return true;
5244 }
5245 return false;
5246 },
5247 false /* don't skip top directive */);
5248 CloseNesting = false;
5249 }
5250 if (NestingProhibited) {
5251 if (OrphanSeen) {
5252 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5253 << getOpenMPDirectiveName(CurrentRegion) << Recommend;
5254 } else {
5255 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5256 << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
5257 << Recommend << getOpenMPDirectiveName(CurrentRegion);
5258 }
5259 return true;
5260 }
5261 }
5262 return false;
5263 }
5264
5265 struct Kind2Unsigned {
5266 using argument_type = OpenMPDirectiveKind;
operator ()Kind2Unsigned5267 unsigned operator()(argument_type DK) { return unsigned(DK); }
5268 };
checkIfClauses(Sema & S,OpenMPDirectiveKind Kind,ArrayRef<OMPClause * > Clauses,ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers)5269 static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
5270 ArrayRef<OMPClause *> Clauses,
5271 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5272 bool ErrorFound = false;
5273 unsigned NamedModifiersNumber = 0;
5274 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5275 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5276 SmallVector<SourceLocation, 4> NameModifierLoc;
5277 for (const OMPClause *C : Clauses) {
5278 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5279 // At most one if clause without a directive-name-modifier can appear on
5280 // the directive.
5281 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5282 if (FoundNameModifiers[CurNM]) {
5283 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5284 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
5285 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
5286 ErrorFound = true;
5287 } else if (CurNM != OMPD_unknown) {
5288 NameModifierLoc.push_back(IC->getNameModifierLoc());
5289 ++NamedModifiersNumber;
5290 }
5291 FoundNameModifiers[CurNM] = IC;
5292 if (CurNM == OMPD_unknown)
5293 continue;
5294 // Check if the specified name modifier is allowed for the current
5295 // directive.
5296 // At most one if clause with the particular directive-name-modifier can
5297 // appear on the directive.
5298 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5299 S.Diag(IC->getNameModifierLoc(),
5300 diag::err_omp_wrong_if_directive_name_modifier)
5301 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
5302 ErrorFound = true;
5303 }
5304 }
5305 }
5306 // If any if clause on the directive includes a directive-name-modifier then
5307 // all if clauses on the directive must include a directive-name-modifier.
5308 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5309 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5310 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5311 diag::err_omp_no_more_if_clause);
5312 } else {
5313 std::string Values;
5314 std::string Sep(", ");
5315 unsigned AllowedCnt = 0;
5316 unsigned TotalAllowedNum =
5317 AllowedNameModifiers.size() - NamedModifiersNumber;
5318 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5319 ++Cnt) {
5320 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5321 if (!FoundNameModifiers[NM]) {
5322 Values += "'";
5323 Values += getOpenMPDirectiveName(NM);
5324 Values += "'";
5325 if (AllowedCnt + 2 == TotalAllowedNum)
5326 Values += " or ";
5327 else if (AllowedCnt + 1 != TotalAllowedNum)
5328 Values += Sep;
5329 ++AllowedCnt;
5330 }
5331 }
5332 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5333 diag::err_omp_unnamed_if_clause)
5334 << (TotalAllowedNum > 1) << Values;
5335 }
5336 for (SourceLocation Loc : NameModifierLoc) {
5337 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5338 }
5339 ErrorFound = true;
5340 }
5341 return ErrorFound;
5342 }
5343
getPrivateItem(Sema & S,Expr * & RefExpr,SourceLocation & ELoc,SourceRange & ERange,bool AllowArraySection,StringRef DiagType)5344 static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5345 SourceLocation &ELoc,
5346 SourceRange &ERange,
5347 bool AllowArraySection,
5348 StringRef DiagType) {
5349 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5350 RefExpr->containsUnexpandedParameterPack())
5351 return std::make_pair(nullptr, true);
5352
5353 // OpenMP [3.1, C/C++]
5354 // A list item is a variable name.
5355 // OpenMP [2.9.3.3, Restrictions, p.1]
5356 // A variable that is part of another variable (as an array or
5357 // structure element) cannot appear in a private clause.
5358 RefExpr = RefExpr->IgnoreParens();
5359 enum {
5360 NoArrayExpr = -1,
5361 ArraySubscript = 0,
5362 OMPArraySection = 1
5363 } IsArrayExpr = NoArrayExpr;
5364 if (AllowArraySection) {
5365 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5366 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5367 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5368 Base = TempASE->getBase()->IgnoreParenImpCasts();
5369 RefExpr = Base;
5370 IsArrayExpr = ArraySubscript;
5371 } else if (auto *OASE = dyn_cast_or_null<OMPArraySectionExpr>(RefExpr)) {
5372 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5373 while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
5374 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5375 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5376 Base = TempASE->getBase()->IgnoreParenImpCasts();
5377 RefExpr = Base;
5378 IsArrayExpr = OMPArraySection;
5379 }
5380 }
5381 ELoc = RefExpr->getExprLoc();
5382 ERange = RefExpr->getSourceRange();
5383 RefExpr = RefExpr->IgnoreParenImpCasts();
5384 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5385 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5386 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5387 (S.getCurrentThisType().isNull() || !ME ||
5388 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5389 !isa<FieldDecl>(ME->getMemberDecl()))) {
5390 if (IsArrayExpr != NoArrayExpr) {
5391 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5392 << IsArrayExpr << ERange;
5393 } else if (!DiagType.empty()) {
5394 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5395 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5396 : 0;
5397 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5398 << DiagSelect << DiagType << ERange;
5399 } else {
5400 S.Diag(ELoc,
5401 AllowArraySection
5402 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5403 : diag::err_omp_expected_var_name_member_expr)
5404 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5405 }
5406 return std::make_pair(nullptr, false);
5407 }
5408 return std::make_pair(
5409 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5410 }
5411
5412 namespace {
5413 /// Checks if the allocator is used in uses_allocators clause to be allowed in
5414 /// target regions.
5415 class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5416 DSAStackTy *S = nullptr;
5417
5418 public:
VisitDeclRefExpr(const DeclRefExpr * E)5419 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5420 return S->isUsesAllocatorsDecl(E->getDecl())
5421 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5422 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5423 }
VisitStmt(const Stmt * S)5424 bool VisitStmt(const Stmt *S) {
5425 for (const Stmt *Child : S->children()) {
5426 if (Child && Visit(Child))
5427 return true;
5428 }
5429 return false;
5430 }
AllocatorChecker(DSAStackTy * S)5431 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5432 };
5433 } // namespace
5434
checkAllocateClauses(Sema & S,DSAStackTy * Stack,ArrayRef<OMPClause * > Clauses)5435 static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5436 ArrayRef<OMPClause *> Clauses) {
5437 assert(!S.CurContext->isDependentContext() &&
5438 "Expected non-dependent context.");
5439 auto AllocateRange =
5440 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5441 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5442 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5443 return isOpenMPPrivate(C->getClauseKind());
5444 });
5445 for (OMPClause *Cl : PrivateRange) {
5446 MutableArrayRef<Expr *>::iterator I, It, Et;
5447 if (Cl->getClauseKind() == OMPC_private) {
5448 auto *PC = cast<OMPPrivateClause>(Cl);
5449 I = PC->private_copies().begin();
5450 It = PC->varlist_begin();
5451 Et = PC->varlist_end();
5452 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5453 auto *PC = cast<OMPFirstprivateClause>(Cl);
5454 I = PC->private_copies().begin();
5455 It = PC->varlist_begin();
5456 Et = PC->varlist_end();
5457 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5458 auto *PC = cast<OMPLastprivateClause>(Cl);
5459 I = PC->private_copies().begin();
5460 It = PC->varlist_begin();
5461 Et = PC->varlist_end();
5462 } else if (Cl->getClauseKind() == OMPC_linear) {
5463 auto *PC = cast<OMPLinearClause>(Cl);
5464 I = PC->privates().begin();
5465 It = PC->varlist_begin();
5466 Et = PC->varlist_end();
5467 } else if (Cl->getClauseKind() == OMPC_reduction) {
5468 auto *PC = cast<OMPReductionClause>(Cl);
5469 I = PC->privates().begin();
5470 It = PC->varlist_begin();
5471 Et = PC->varlist_end();
5472 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5473 auto *PC = cast<OMPTaskReductionClause>(Cl);
5474 I = PC->privates().begin();
5475 It = PC->varlist_begin();
5476 Et = PC->varlist_end();
5477 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5478 auto *PC = cast<OMPInReductionClause>(Cl);
5479 I = PC->privates().begin();
5480 It = PC->varlist_begin();
5481 Et = PC->varlist_end();
5482 } else {
5483 llvm_unreachable("Expected private clause.");
5484 }
5485 for (Expr *E : llvm::make_range(It, Et)) {
5486 if (!*I) {
5487 ++I;
5488 continue;
5489 }
5490 SourceLocation ELoc;
5491 SourceRange ERange;
5492 Expr *SimpleRefExpr = E;
5493 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5494 /*AllowArraySection=*/true);
5495 DeclToCopy.try_emplace(Res.first,
5496 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5497 ++I;
5498 }
5499 }
5500 for (OMPClause *C : AllocateRange) {
5501 auto *AC = cast<OMPAllocateClause>(C);
5502 if (S.getLangOpts().OpenMP >= 50 &&
5503 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5504 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5505 AC->getAllocator()) {
5506 Expr *Allocator = AC->getAllocator();
5507 // OpenMP, 2.12.5 target Construct
5508 // Memory allocators that do not appear in a uses_allocators clause cannot
5509 // appear as an allocator in an allocate clause or be used in the target
5510 // region unless a requires directive with the dynamic_allocators clause
5511 // is present in the same compilation unit.
5512 AllocatorChecker Checker(Stack);
5513 if (Checker.Visit(Allocator))
5514 S.Diag(Allocator->getExprLoc(),
5515 diag::err_omp_allocator_not_in_uses_allocators)
5516 << Allocator->getSourceRange();
5517 }
5518 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5519 getAllocatorKind(S, Stack, AC->getAllocator());
5520 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5521 // For task, taskloop or target directives, allocation requests to memory
5522 // allocators with the trait access set to thread result in unspecified
5523 // behavior.
5524 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5525 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5526 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5527 S.Diag(AC->getAllocator()->getExprLoc(),
5528 diag::warn_omp_allocate_thread_on_task_target_directive)
5529 << getOpenMPDirectiveName(Stack->getCurrentDirective());
5530 }
5531 for (Expr *E : AC->varlists()) {
5532 SourceLocation ELoc;
5533 SourceRange ERange;
5534 Expr *SimpleRefExpr = E;
5535 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5536 ValueDecl *VD = Res.first;
5537 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5538 if (!isOpenMPPrivate(Data.CKind)) {
5539 S.Diag(E->getExprLoc(),
5540 diag::err_omp_expected_private_copy_for_allocate);
5541 continue;
5542 }
5543 VarDecl *PrivateVD = DeclToCopy[VD];
5544 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5545 AllocatorKind, AC->getAllocator()))
5546 continue;
5547 // Placeholder until allocate clause supports align modifier.
5548 Expr *Alignment = nullptr;
5549 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5550 Alignment, E->getSourceRange());
5551 }
5552 }
5553 }
5554
5555 namespace {
5556 /// Rewrite statements and expressions for Sema \p Actions CurContext.
5557 ///
5558 /// Used to wrap already parsed statements/expressions into a new CapturedStmt
5559 /// context. DeclRefExpr used inside the new context are changed to refer to the
5560 /// captured variable instead.
5561 class CaptureVars : public TreeTransform<CaptureVars> {
5562 using BaseTransform = TreeTransform<CaptureVars>;
5563
5564 public:
CaptureVars(Sema & Actions)5565 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5566
AlwaysRebuild()5567 bool AlwaysRebuild() { return true; }
5568 };
5569 } // namespace
5570
precomputeExpr(Sema & Actions,SmallVectorImpl<Stmt * > & BodyStmts,Expr * E,StringRef Name)5571 static VarDecl *precomputeExpr(Sema &Actions,
5572 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5573 StringRef Name) {
5574 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5575 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5576 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5577 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5578 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5579 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5580 BodyStmts.push_back(NewDeclStmt);
5581 return NewVar;
5582 }
5583
5584 /// Create a closure that computes the number of iterations of a loop.
5585 ///
5586 /// \param Actions The Sema object.
5587 /// \param LogicalTy Type for the logical iteration number.
5588 /// \param Rel Comparison operator of the loop condition.
5589 /// \param StartExpr Value of the loop counter at the first iteration.
5590 /// \param StopExpr Expression the loop counter is compared against in the loop
5591 /// condition. \param StepExpr Amount of increment after each iteration.
5592 ///
5593 /// \return Closure (CapturedStmt) of the distance calculation.
buildDistanceFunc(Sema & Actions,QualType LogicalTy,BinaryOperator::Opcode Rel,Expr * StartExpr,Expr * StopExpr,Expr * StepExpr)5594 static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5595 BinaryOperator::Opcode Rel,
5596 Expr *StartExpr, Expr *StopExpr,
5597 Expr *StepExpr) {
5598 ASTContext &Ctx = Actions.getASTContext();
5599 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5600
5601 // Captured regions currently don't support return values, we use an
5602 // out-parameter instead. All inputs are implicit captures.
5603 // TODO: Instead of capturing each DeclRefExpr occurring in
5604 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5605 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5606 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5607 {StringRef(), QualType()}};
5608 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5609
5610 Stmt *Body;
5611 {
5612 Sema::CompoundScopeRAII CompoundScope(Actions);
5613 CapturedDecl *CS = cast<CapturedDecl>(Actions.CurContext);
5614
5615 // Get the LValue expression for the result.
5616 ImplicitParamDecl *DistParam = CS->getParam(0);
5617 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5618 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5619
5620 SmallVector<Stmt *, 4> BodyStmts;
5621
5622 // Capture all referenced variable references.
5623 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5624 // CapturedStmt, we could compute them before and capture the result, to be
5625 // used jointly with the LoopVar function.
5626 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5627 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5628 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5629 auto BuildVarRef = [&](VarDecl *VD) {
5630 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5631 };
5632
5633 IntegerLiteral *Zero = IntegerLiteral::Create(
5634 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5635 IntegerLiteral *One = IntegerLiteral::Create(
5636 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5637 Expr *Dist;
5638 if (Rel == BO_NE) {
5639 // When using a != comparison, the increment can be +1 or -1. This can be
5640 // dynamic at runtime, so we need to check for the direction.
5641 Expr *IsNegStep = AssertSuccess(
5642 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5643
5644 // Positive increment.
5645 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5646 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5647 ForwardRange = AssertSuccess(
5648 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5649 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5650 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5651
5652 // Negative increment.
5653 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5654 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5655 BackwardRange = AssertSuccess(
5656 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5657 Expr *NegIncAmount = AssertSuccess(
5658 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5659 Expr *BackwardDist = AssertSuccess(
5660 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5661
5662 // Use the appropriate case.
5663 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5664 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5665 } else {
5666 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5667 "Expected one of these relational operators");
5668
5669 // We can derive the direction from any other comparison operator. It is
5670 // non well-formed OpenMP if Step increments/decrements in the other
5671 // directions. Whether at least the first iteration passes the loop
5672 // condition.
5673 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5674 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5675
5676 // Compute the range between first and last counter value.
5677 Expr *Range;
5678 if (Rel == BO_GE || Rel == BO_GT)
5679 Range = AssertSuccess(Actions.BuildBinOp(
5680 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5681 else
5682 Range = AssertSuccess(Actions.BuildBinOp(
5683 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5684
5685 // Ensure unsigned range space.
5686 Range =
5687 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5688
5689 if (Rel == BO_LE || Rel == BO_GE) {
5690 // Add one to the range if the relational operator is inclusive.
5691 Range =
5692 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5693 }
5694
5695 // Divide by the absolute step amount. If the range is not a multiple of
5696 // the step size, rounding-up the effective upper bound ensures that the
5697 // last iteration is included.
5698 // Note that the rounding-up may cause an overflow in a temporry that
5699 // could be avoided, but would have occurred in a C-style for-loop as well.
5700 Expr *Divisor = BuildVarRef(NewStep);
5701 if (Rel == BO_GE || Rel == BO_GT)
5702 Divisor =
5703 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5704 Expr *DivisorMinusOne =
5705 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5706 Expr *RangeRoundUp = AssertSuccess(
5707 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5708 Dist = AssertSuccess(
5709 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5710
5711 // If there is not at least one iteration, the range contains garbage. Fix
5712 // to zero in this case.
5713 Dist = AssertSuccess(
5714 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5715 }
5716
5717 // Assign the result to the out-parameter.
5718 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5719 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5720 BodyStmts.push_back(ResultAssign);
5721
5722 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5723 }
5724
5725 return cast<CapturedStmt>(
5726 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5727 }
5728
5729 /// Create a closure that computes the loop variable from the logical iteration
5730 /// number.
5731 ///
5732 /// \param Actions The Sema object.
5733 /// \param LoopVarTy Type for the loop variable used for result value.
5734 /// \param LogicalTy Type for the logical iteration number.
5735 /// \param StartExpr Value of the loop counter at the first iteration.
5736 /// \param Step Amount of increment after each iteration.
5737 /// \param Deref Whether the loop variable is a dereference of the loop
5738 /// counter variable.
5739 ///
5740 /// \return Closure (CapturedStmt) of the loop value calculation.
buildLoopVarFunc(Sema & Actions,QualType LoopVarTy,QualType LogicalTy,DeclRefExpr * StartExpr,Expr * Step,bool Deref)5741 static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5742 QualType LogicalTy,
5743 DeclRefExpr *StartExpr, Expr *Step,
5744 bool Deref) {
5745 ASTContext &Ctx = Actions.getASTContext();
5746
5747 // Pass the result as an out-parameter. Passing as return value would require
5748 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5749 // invoke a copy constructor.
5750 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5751 Sema::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5752 {"Logical", LogicalTy},
5753 {StringRef(), QualType()}};
5754 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5755
5756 // Capture the initial iterator which represents the LoopVar value at the
5757 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5758 // it in every iteration, capture it by value before it is modified.
5759 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5760 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5761 Sema::TryCapture_ExplicitByVal, {});
5762 (void)Invalid;
5763 assert(!Invalid && "Expecting capture-by-value to work.");
5764
5765 Expr *Body;
5766 {
5767 Sema::CompoundScopeRAII CompoundScope(Actions);
5768 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5769
5770 ImplicitParamDecl *TargetParam = CS->getParam(0);
5771 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5772 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5773 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5774 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5775 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5776
5777 // Capture the Start expression.
5778 CaptureVars Recap(Actions);
5779 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5780 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5781
5782 Expr *Skip = AssertSuccess(
5783 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5784 // TODO: Explicitly cast to the iterator's difference_type instead of
5785 // relying on implicit conversion.
5786 Expr *Advanced =
5787 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5788
5789 if (Deref) {
5790 // For range-based for-loops convert the loop counter value to a concrete
5791 // loop variable value by dereferencing the iterator.
5792 Advanced =
5793 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5794 }
5795
5796 // Assign the result to the output parameter.
5797 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5798 BO_Assign, TargetRef, Advanced));
5799 }
5800 return cast<CapturedStmt>(
5801 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5802 }
5803
ActOnOpenMPCanonicalLoop(Stmt * AStmt)5804 StmtResult Sema::ActOnOpenMPCanonicalLoop(Stmt *AStmt) {
5805 ASTContext &Ctx = getASTContext();
5806
5807 // Extract the common elements of ForStmt and CXXForRangeStmt:
5808 // Loop variable, repeat condition, increment
5809 Expr *Cond, *Inc;
5810 VarDecl *LIVDecl, *LUVDecl;
5811 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5812 Stmt *Init = For->getInit();
5813 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5814 // For statement declares loop variable.
5815 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5816 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5817 // For statement reuses variable.
5818 assert(LCAssign->getOpcode() == BO_Assign &&
5819 "init part must be a loop variable assignment");
5820 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5821 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5822 } else
5823 llvm_unreachable("Cannot determine loop variable");
5824 LUVDecl = LIVDecl;
5825
5826 Cond = For->getCond();
5827 Inc = For->getInc();
5828 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5829 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5830 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5831 LUVDecl = RangeFor->getLoopVariable();
5832
5833 Cond = RangeFor->getCond();
5834 Inc = RangeFor->getInc();
5835 } else
5836 llvm_unreachable("unhandled kind of loop");
5837
5838 QualType CounterTy = LIVDecl->getType();
5839 QualType LVTy = LUVDecl->getType();
5840
5841 // Analyze the loop condition.
5842 Expr *LHS, *RHS;
5843 BinaryOperator::Opcode CondRel;
5844 Cond = Cond->IgnoreImplicit();
5845 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5846 LHS = CondBinExpr->getLHS();
5847 RHS = CondBinExpr->getRHS();
5848 CondRel = CondBinExpr->getOpcode();
5849 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5850 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5851 LHS = CondCXXOp->getArg(0);
5852 RHS = CondCXXOp->getArg(1);
5853 switch (CondCXXOp->getOperator()) {
5854 case OO_ExclaimEqual:
5855 CondRel = BO_NE;
5856 break;
5857 case OO_Less:
5858 CondRel = BO_LT;
5859 break;
5860 case OO_LessEqual:
5861 CondRel = BO_LE;
5862 break;
5863 case OO_Greater:
5864 CondRel = BO_GT;
5865 break;
5866 case OO_GreaterEqual:
5867 CondRel = BO_GE;
5868 break;
5869 default:
5870 llvm_unreachable("unexpected iterator operator");
5871 }
5872 } else
5873 llvm_unreachable("unexpected loop condition");
5874
5875 // Normalize such that the loop counter is on the LHS.
5876 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5877 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5878 std::swap(LHS, RHS);
5879 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5880 }
5881 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5882
5883 // Decide the bit width for the logical iteration counter. By default use the
5884 // unsigned ptrdiff_t integer size (for iterators and pointers).
5885 // TODO: For iterators, use iterator::difference_type,
5886 // std::iterator_traits<>::difference_type or decltype(it - end).
5887 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5888 if (CounterTy->isIntegerType()) {
5889 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5890 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5891 }
5892
5893 // Analyze the loop increment.
5894 Expr *Step;
5895 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5896 int Direction;
5897 switch (IncUn->getOpcode()) {
5898 case UO_PreInc:
5899 case UO_PostInc:
5900 Direction = 1;
5901 break;
5902 case UO_PreDec:
5903 case UO_PostDec:
5904 Direction = -1;
5905 break;
5906 default:
5907 llvm_unreachable("unhandled unary increment operator");
5908 }
5909 Step = IntegerLiteral::Create(
5910 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction), LogicalTy, {});
5911 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5912 if (IncBin->getOpcode() == BO_AddAssign) {
5913 Step = IncBin->getRHS();
5914 } else if (IncBin->getOpcode() == BO_SubAssign) {
5915 Step =
5916 AssertSuccess(BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5917 } else
5918 llvm_unreachable("unhandled binary increment operator");
5919 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5920 switch (CondCXXOp->getOperator()) {
5921 case OO_PlusPlus:
5922 Step = IntegerLiteral::Create(
5923 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5924 break;
5925 case OO_MinusMinus:
5926 Step = IntegerLiteral::Create(
5927 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5928 break;
5929 case OO_PlusEqual:
5930 Step = CondCXXOp->getArg(1);
5931 break;
5932 case OO_MinusEqual:
5933 Step = AssertSuccess(
5934 BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5935 break;
5936 default:
5937 llvm_unreachable("unhandled overloaded increment operator");
5938 }
5939 } else
5940 llvm_unreachable("unknown increment expression");
5941
5942 CapturedStmt *DistanceFunc =
5943 buildDistanceFunc(*this, LogicalTy, CondRel, LHS, RHS, Step);
5944 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5945 *this, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5946 DeclRefExpr *LVRef = BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue,
5947 {}, nullptr, nullptr, {}, nullptr);
5948 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
5949 LoopVarFunc, LVRef);
5950 }
5951
ActOnOpenMPLoopnest(Stmt * AStmt)5952 StmtResult Sema::ActOnOpenMPLoopnest(Stmt *AStmt) {
5953 // Handle a literal loop.
5954 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5955 return ActOnOpenMPCanonicalLoop(AStmt);
5956
5957 // If not a literal loop, it must be the result of a loop transformation.
5958 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(AStmt);
5959 assert(
5960 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
5961 "Loop transformation directive expected");
5962 return LoopTransform;
5963 }
5964
5965 static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
5966 CXXScopeSpec &MapperIdScopeSpec,
5967 const DeclarationNameInfo &MapperId,
5968 QualType Type,
5969 Expr *UnresolvedMapper);
5970
5971 /// Perform DFS through the structure/class data members trying to find
5972 /// member(s) with user-defined 'default' mapper and generate implicit map
5973 /// clauses for such members with the found 'default' mapper.
5974 static void
processImplicitMapsWithDefaultMappers(Sema & S,DSAStackTy * Stack,SmallVectorImpl<OMPClause * > & Clauses)5975 processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack,
5976 SmallVectorImpl<OMPClause *> &Clauses) {
5977 // Check for the deault mapper for data members.
5978 if (S.getLangOpts().OpenMP < 50)
5979 return;
5980 SmallVector<OMPClause *, 4> ImplicitMaps;
5981 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5982 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5983 if (!C)
5984 continue;
5985 SmallVector<Expr *, 4> SubExprs;
5986 auto *MI = C->mapperlist_begin();
5987 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
5988 ++I, ++MI) {
5989 // Expression is mapped using mapper - skip it.
5990 if (*MI)
5991 continue;
5992 Expr *E = *I;
5993 // Expression is dependent - skip it, build the mapper when it gets
5994 // instantiated.
5995 if (E->isTypeDependent() || E->isValueDependent() ||
5996 E->containsUnexpandedParameterPack())
5997 continue;
5998 // Array section - need to check for the mapping of the array section
5999 // element.
6000 QualType CanonType = E->getType().getCanonicalType();
6001 if (CanonType->isSpecificBuiltinType(BuiltinType::OMPArraySection)) {
6002 const auto *OASE = cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts());
6003 QualType BaseType =
6004 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
6005 QualType ElemType;
6006 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6007 ElemType = ATy->getElementType();
6008 else
6009 ElemType = BaseType->getPointeeType();
6010 CanonType = ElemType;
6011 }
6012
6013 // DFS over data members in structures/classes.
6014 SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(
6015 1, {CanonType, nullptr});
6016 llvm::DenseMap<const Type *, Expr *> Visited;
6017 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(
6018 1, {nullptr, 1});
6019 while (!Types.empty()) {
6020 QualType BaseType;
6021 FieldDecl *CurFD;
6022 std::tie(BaseType, CurFD) = Types.pop_back_val();
6023 while (ParentChain.back().second == 0)
6024 ParentChain.pop_back();
6025 --ParentChain.back().second;
6026 if (BaseType.isNull())
6027 continue;
6028 // Only structs/classes are allowed to have mappers.
6029 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6030 if (!RD)
6031 continue;
6032 auto It = Visited.find(BaseType.getTypePtr());
6033 if (It == Visited.end()) {
6034 // Try to find the associated user-defined mapper.
6035 CXXScopeSpec MapperIdScopeSpec;
6036 DeclarationNameInfo DefaultMapperId;
6037 DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
6038 &S.Context.Idents.get("default")));
6039 DefaultMapperId.setLoc(E->getExprLoc());
6040 ExprResult ER = buildUserDefinedMapperRef(
6041 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
6042 BaseType, /*UnresolvedMapper=*/nullptr);
6043 if (ER.isInvalid())
6044 continue;
6045 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
6046 }
6047 // Found default mapper.
6048 if (It->second) {
6049 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
6050 VK_LValue, OK_Ordinary, E);
6051 OE->setIsUnique(/*V=*/true);
6052 Expr *BaseExpr = OE;
6053 for (const auto &P : ParentChain) {
6054 if (P.first) {
6055 BaseExpr = S.BuildMemberExpr(
6056 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6057 NestedNameSpecifierLoc(), SourceLocation(), P.first,
6058 DeclAccessPair::make(P.first, P.first->getAccess()),
6059 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6060 P.first->getType(), VK_LValue, OK_Ordinary);
6061 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
6062 }
6063 }
6064 if (CurFD)
6065 BaseExpr = S.BuildMemberExpr(
6066 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6067 NestedNameSpecifierLoc(), SourceLocation(), CurFD,
6068 DeclAccessPair::make(CurFD, CurFD->getAccess()),
6069 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6070 CurFD->getType(), VK_LValue, OK_Ordinary);
6071 SubExprs.push_back(BaseExpr);
6072 continue;
6073 }
6074 // Check for the "default" mapper for data members.
6075 bool FirstIter = true;
6076 for (FieldDecl *FD : RD->fields()) {
6077 if (!FD)
6078 continue;
6079 QualType FieldTy = FD->getType();
6080 if (FieldTy.isNull() ||
6081 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6082 continue;
6083 if (FirstIter) {
6084 FirstIter = false;
6085 ParentChain.emplace_back(CurFD, 1);
6086 } else {
6087 ++ParentChain.back().second;
6088 }
6089 Types.emplace_back(FieldTy, FD);
6090 }
6091 }
6092 }
6093 if (SubExprs.empty())
6094 continue;
6095 CXXScopeSpec MapperIdScopeSpec;
6096 DeclarationNameInfo MapperId;
6097 if (OMPClause *NewClause = S.ActOnOpenMPMapClause(
6098 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
6099 MapperIdScopeSpec, MapperId, C->getMapType(),
6100 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6101 SubExprs, OMPVarListLocTy()))
6102 Clauses.push_back(NewClause);
6103 }
6104 }
6105
ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,const DeclarationNameInfo & DirName,OpenMPDirectiveKind CancelRegion,ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)6106 StmtResult Sema::ActOnOpenMPExecutableDirective(
6107 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6108 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6109 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
6110 StmtResult Res = StmtError();
6111 OpenMPBindClauseKind BindKind = OMPC_BIND_unknown;
6112 if (const OMPBindClause *BC =
6113 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6114 BindKind = BC->getBindKind();
6115 // First check CancelRegion which is then used in checkNestingOfRegions.
6116 if (checkCancelRegion(*this, Kind, CancelRegion, StartLoc) ||
6117 checkNestingOfRegions(*this, DSAStack, Kind, DirName, CancelRegion,
6118 BindKind, StartLoc))
6119 return StmtError();
6120
6121 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6122 VarsWithInheritedDSAType VarsWithInheritedDSA;
6123 bool ErrorFound = false;
6124 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6125 if (AStmt && !CurContext->isDependentContext() && Kind != OMPD_atomic &&
6126 Kind != OMPD_critical && Kind != OMPD_section && Kind != OMPD_master &&
6127 Kind != OMPD_masked && !isOpenMPLoopTransformationDirective(Kind)) {
6128 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6129
6130 // Check default data sharing attributes for referenced variables.
6131 DSAAttrChecker DSAChecker(DSAStack, *this, cast<CapturedStmt>(AStmt));
6132 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6133 Stmt *S = AStmt;
6134 while (--ThisCaptureLevel >= 0)
6135 S = cast<CapturedStmt>(S)->getCapturedStmt();
6136 DSAChecker.Visit(S);
6137 if (!isOpenMPTargetDataManagementDirective(Kind) &&
6138 !isOpenMPTaskingDirective(Kind)) {
6139 // Visit subcaptures to generate implicit clauses for captured vars.
6140 auto *CS = cast<CapturedStmt>(AStmt);
6141 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
6142 getOpenMPCaptureRegions(CaptureRegions, Kind);
6143 // Ignore outer tasking regions for target directives.
6144 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6145 CS = cast<CapturedStmt>(CS->getCapturedStmt());
6146 DSAChecker.visitSubCaptures(CS);
6147 }
6148 if (DSAChecker.isErrorFound())
6149 return StmtError();
6150 // Generate list of implicitly defined firstprivate variables.
6151 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6152
6153 SmallVector<Expr *, 4> ImplicitFirstprivates(
6154 DSAChecker.getImplicitFirstprivate().begin(),
6155 DSAChecker.getImplicitFirstprivate().end());
6156 SmallVector<Expr *, 4> ImplicitPrivates(
6157 DSAChecker.getImplicitPrivate().begin(),
6158 DSAChecker.getImplicitPrivate().end());
6159 const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_pointer + 1;
6160 SmallVector<Expr *, 4> ImplicitMaps[DefaultmapKindNum][OMPC_MAP_delete];
6161 SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
6162 ImplicitMapModifiers[DefaultmapKindNum];
6163 SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers>
6164 ImplicitMapModifiersLoc[DefaultmapKindNum];
6165 // Get the original location of present modifier from Defaultmap clause.
6166 SourceLocation PresentModifierLocs[DefaultmapKindNum];
6167 for (OMPClause *C : Clauses) {
6168 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6169 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6170 PresentModifierLocs[DMC->getDefaultmapKind()] =
6171 DMC->getDefaultmapModifierLoc();
6172 }
6173 for (unsigned VC = 0; VC < DefaultmapKindNum; ++VC) {
6174 auto Kind = static_cast<OpenMPDefaultmapClauseKind>(VC);
6175 for (unsigned I = 0; I < OMPC_MAP_delete; ++I) {
6176 ArrayRef<Expr *> ImplicitMap = DSAChecker.getImplicitMap(
6177 Kind, static_cast<OpenMPMapClauseKind>(I));
6178 ImplicitMaps[VC][I].append(ImplicitMap.begin(), ImplicitMap.end());
6179 }
6180 ArrayRef<OpenMPMapModifierKind> ImplicitModifier =
6181 DSAChecker.getImplicitMapModifier(Kind);
6182 ImplicitMapModifiers[VC].append(ImplicitModifier.begin(),
6183 ImplicitModifier.end());
6184 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[VC]),
6185 ImplicitModifier.size(), PresentModifierLocs[VC]);
6186 }
6187 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6188 for (OMPClause *C : Clauses) {
6189 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6190 for (Expr *E : IRC->taskgroup_descriptors())
6191 if (E)
6192 ImplicitFirstprivates.emplace_back(E);
6193 }
6194 // OpenMP 5.0, 2.10.1 task Construct
6195 // [detach clause]... The event-handle will be considered as if it was
6196 // specified on a firstprivate clause.
6197 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6198 ImplicitFirstprivates.push_back(DC->getEventHandler());
6199 }
6200 if (!ImplicitFirstprivates.empty()) {
6201 if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
6202 ImplicitFirstprivates, SourceLocation(), SourceLocation(),
6203 SourceLocation())) {
6204 ClausesWithImplicit.push_back(Implicit);
6205 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6206 ImplicitFirstprivates.size();
6207 } else {
6208 ErrorFound = true;
6209 }
6210 }
6211 if (!ImplicitPrivates.empty()) {
6212 if (OMPClause *Implicit =
6213 ActOnOpenMPPrivateClause(ImplicitPrivates, SourceLocation(),
6214 SourceLocation(), SourceLocation())) {
6215 ClausesWithImplicit.push_back(Implicit);
6216 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6217 ImplicitPrivates.size();
6218 } else {
6219 ErrorFound = true;
6220 }
6221 }
6222 // OpenMP 5.0 [2.19.7]
6223 // If a list item appears in a reduction, lastprivate or linear
6224 // clause on a combined target construct then it is treated as
6225 // if it also appears in a map clause with a map-type of tofrom
6226 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6227 isOpenMPTargetExecutionDirective(Kind)) {
6228 SmallVector<Expr *, 4> ImplicitExprs;
6229 for (OMPClause *C : Clauses) {
6230 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6231 for (Expr *E : RC->varlists())
6232 if (!isa<DeclRefExpr>(E->IgnoreParenImpCasts()))
6233 ImplicitExprs.emplace_back(E);
6234 }
6235 if (!ImplicitExprs.empty()) {
6236 ArrayRef<Expr *> Exprs = ImplicitExprs;
6237 CXXScopeSpec MapperIdScopeSpec;
6238 DeclarationNameInfo MapperId;
6239 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6240 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(),
6241 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6242 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6243 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6244 ClausesWithImplicit.emplace_back(Implicit);
6245 }
6246 }
6247 for (unsigned I = 0, E = DefaultmapKindNum; I < E; ++I) {
6248 int ClauseKindCnt = -1;
6249 for (ArrayRef<Expr *> ImplicitMap : ImplicitMaps[I]) {
6250 ++ClauseKindCnt;
6251 if (ImplicitMap.empty())
6252 continue;
6253 CXXScopeSpec MapperIdScopeSpec;
6254 DeclarationNameInfo MapperId;
6255 auto Kind = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6256 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6257 nullptr, ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I],
6258 MapperIdScopeSpec, MapperId, Kind, /*IsMapTypeImplicit=*/true,
6259 SourceLocation(), SourceLocation(), ImplicitMap,
6260 OMPVarListLocTy())) {
6261 ClausesWithImplicit.emplace_back(Implicit);
6262 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6263 ImplicitMap.size();
6264 } else {
6265 ErrorFound = true;
6266 }
6267 }
6268 }
6269 // Build expressions for implicit maps of data members with 'default'
6270 // mappers.
6271 if (LangOpts.OpenMP >= 50)
6272 processImplicitMapsWithDefaultMappers(*this, DSAStack,
6273 ClausesWithImplicit);
6274 }
6275
6276 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6277 switch (Kind) {
6278 case OMPD_parallel:
6279 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6280 EndLoc);
6281 AllowedNameModifiers.push_back(OMPD_parallel);
6282 break;
6283 case OMPD_simd:
6284 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6285 VarsWithInheritedDSA);
6286 if (LangOpts.OpenMP >= 50)
6287 AllowedNameModifiers.push_back(OMPD_simd);
6288 break;
6289 case OMPD_tile:
6290 Res =
6291 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6292 break;
6293 case OMPD_unroll:
6294 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6295 EndLoc);
6296 break;
6297 case OMPD_for:
6298 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6299 VarsWithInheritedDSA);
6300 break;
6301 case OMPD_for_simd:
6302 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6303 EndLoc, VarsWithInheritedDSA);
6304 if (LangOpts.OpenMP >= 50)
6305 AllowedNameModifiers.push_back(OMPD_simd);
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 AllowedNameModifiers.push_back(OMPD_parallel);
6337 break;
6338 case OMPD_parallel_for_simd:
6339 Res = ActOnOpenMPParallelForSimdDirective(
6340 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6341 AllowedNameModifiers.push_back(OMPD_parallel);
6342 if (LangOpts.OpenMP >= 50)
6343 AllowedNameModifiers.push_back(OMPD_simd);
6344 break;
6345 case OMPD_parallel_master:
6346 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6347 StartLoc, EndLoc);
6348 AllowedNameModifiers.push_back(OMPD_parallel);
6349 break;
6350 case OMPD_parallel_masked:
6351 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6352 StartLoc, EndLoc);
6353 AllowedNameModifiers.push_back(OMPD_parallel);
6354 break;
6355 case OMPD_parallel_sections:
6356 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6357 StartLoc, EndLoc);
6358 AllowedNameModifiers.push_back(OMPD_parallel);
6359 break;
6360 case OMPD_task:
6361 Res =
6362 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6363 AllowedNameModifiers.push_back(OMPD_task);
6364 break;
6365 case OMPD_taskyield:
6366 assert(ClausesWithImplicit.empty() &&
6367 "No clauses are allowed for 'omp taskyield' directive");
6368 assert(AStmt == nullptr &&
6369 "No associated statement allowed for 'omp taskyield' directive");
6370 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6371 break;
6372 case OMPD_error:
6373 assert(AStmt == nullptr &&
6374 "No associated statement allowed for 'omp error' directive");
6375 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6376 break;
6377 case OMPD_barrier:
6378 assert(ClausesWithImplicit.empty() &&
6379 "No clauses are allowed for 'omp barrier' directive");
6380 assert(AStmt == nullptr &&
6381 "No associated statement allowed for 'omp barrier' directive");
6382 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6383 break;
6384 case OMPD_taskwait:
6385 assert(AStmt == nullptr &&
6386 "No associated statement allowed for 'omp taskwait' directive");
6387 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6388 break;
6389 case OMPD_taskgroup:
6390 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6391 EndLoc);
6392 break;
6393 case OMPD_flush:
6394 assert(AStmt == nullptr &&
6395 "No associated statement allowed for 'omp flush' directive");
6396 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6397 break;
6398 case OMPD_depobj:
6399 assert(AStmt == nullptr &&
6400 "No associated statement allowed for 'omp depobj' directive");
6401 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6402 break;
6403 case OMPD_scan:
6404 assert(AStmt == nullptr &&
6405 "No associated statement allowed for 'omp scan' directive");
6406 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6407 break;
6408 case OMPD_ordered:
6409 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6410 EndLoc);
6411 break;
6412 case OMPD_atomic:
6413 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6414 EndLoc);
6415 break;
6416 case OMPD_teams:
6417 Res =
6418 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6419 break;
6420 case OMPD_target:
6421 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6422 EndLoc);
6423 AllowedNameModifiers.push_back(OMPD_target);
6424 break;
6425 case OMPD_target_parallel:
6426 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6427 StartLoc, EndLoc);
6428 AllowedNameModifiers.push_back(OMPD_target);
6429 AllowedNameModifiers.push_back(OMPD_parallel);
6430 break;
6431 case OMPD_target_parallel_for:
6432 Res = ActOnOpenMPTargetParallelForDirective(
6433 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6434 AllowedNameModifiers.push_back(OMPD_target);
6435 AllowedNameModifiers.push_back(OMPD_parallel);
6436 break;
6437 case OMPD_cancellation_point:
6438 assert(ClausesWithImplicit.empty() &&
6439 "No clauses are allowed for 'omp cancellation point' directive");
6440 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6441 "cancellation point' directive");
6442 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6443 break;
6444 case OMPD_cancel:
6445 assert(AStmt == nullptr &&
6446 "No associated statement allowed for 'omp cancel' directive");
6447 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6448 CancelRegion);
6449 AllowedNameModifiers.push_back(OMPD_cancel);
6450 break;
6451 case OMPD_target_data:
6452 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6453 EndLoc);
6454 AllowedNameModifiers.push_back(OMPD_target_data);
6455 break;
6456 case OMPD_target_enter_data:
6457 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6458 EndLoc, AStmt);
6459 AllowedNameModifiers.push_back(OMPD_target_enter_data);
6460 break;
6461 case OMPD_target_exit_data:
6462 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6463 EndLoc, AStmt);
6464 AllowedNameModifiers.push_back(OMPD_target_exit_data);
6465 break;
6466 case OMPD_taskloop:
6467 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6468 EndLoc, VarsWithInheritedDSA);
6469 AllowedNameModifiers.push_back(OMPD_taskloop);
6470 break;
6471 case OMPD_taskloop_simd:
6472 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6473 EndLoc, VarsWithInheritedDSA);
6474 AllowedNameModifiers.push_back(OMPD_taskloop);
6475 if (LangOpts.OpenMP >= 50)
6476 AllowedNameModifiers.push_back(OMPD_simd);
6477 break;
6478 case OMPD_master_taskloop:
6479 Res = ActOnOpenMPMasterTaskLoopDirective(
6480 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6481 AllowedNameModifiers.push_back(OMPD_taskloop);
6482 break;
6483 case OMPD_masked_taskloop:
6484 Res = ActOnOpenMPMaskedTaskLoopDirective(
6485 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6486 AllowedNameModifiers.push_back(OMPD_taskloop);
6487 break;
6488 case OMPD_master_taskloop_simd:
6489 Res = ActOnOpenMPMasterTaskLoopSimdDirective(
6490 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6491 AllowedNameModifiers.push_back(OMPD_taskloop);
6492 if (LangOpts.OpenMP >= 50)
6493 AllowedNameModifiers.push_back(OMPD_simd);
6494 break;
6495 case OMPD_masked_taskloop_simd:
6496 Res = ActOnOpenMPMaskedTaskLoopSimdDirective(
6497 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6498 if (LangOpts.OpenMP >= 51) {
6499 AllowedNameModifiers.push_back(OMPD_taskloop);
6500 AllowedNameModifiers.push_back(OMPD_simd);
6501 }
6502 break;
6503 case OMPD_parallel_master_taskloop:
6504 Res = ActOnOpenMPParallelMasterTaskLoopDirective(
6505 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6506 AllowedNameModifiers.push_back(OMPD_taskloop);
6507 AllowedNameModifiers.push_back(OMPD_parallel);
6508 break;
6509 case OMPD_parallel_masked_taskloop:
6510 Res = ActOnOpenMPParallelMaskedTaskLoopDirective(
6511 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6512 if (LangOpts.OpenMP >= 51) {
6513 AllowedNameModifiers.push_back(OMPD_taskloop);
6514 AllowedNameModifiers.push_back(OMPD_parallel);
6515 }
6516 break;
6517 case OMPD_parallel_master_taskloop_simd:
6518 Res = ActOnOpenMPParallelMasterTaskLoopSimdDirective(
6519 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6520 AllowedNameModifiers.push_back(OMPD_taskloop);
6521 AllowedNameModifiers.push_back(OMPD_parallel);
6522 if (LangOpts.OpenMP >= 50)
6523 AllowedNameModifiers.push_back(OMPD_simd);
6524 break;
6525 case OMPD_parallel_masked_taskloop_simd:
6526 Res = ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
6527 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6528 if (LangOpts.OpenMP >= 51) {
6529 AllowedNameModifiers.push_back(OMPD_taskloop);
6530 AllowedNameModifiers.push_back(OMPD_parallel);
6531 AllowedNameModifiers.push_back(OMPD_simd);
6532 }
6533 break;
6534 case OMPD_distribute:
6535 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6536 EndLoc, VarsWithInheritedDSA);
6537 break;
6538 case OMPD_target_update:
6539 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6540 EndLoc, AStmt);
6541 AllowedNameModifiers.push_back(OMPD_target_update);
6542 break;
6543 case OMPD_distribute_parallel_for:
6544 Res = ActOnOpenMPDistributeParallelForDirective(
6545 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6546 AllowedNameModifiers.push_back(OMPD_parallel);
6547 break;
6548 case OMPD_distribute_parallel_for_simd:
6549 Res = ActOnOpenMPDistributeParallelForSimdDirective(
6550 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6551 AllowedNameModifiers.push_back(OMPD_parallel);
6552 if (LangOpts.OpenMP >= 50)
6553 AllowedNameModifiers.push_back(OMPD_simd);
6554 break;
6555 case OMPD_distribute_simd:
6556 Res = ActOnOpenMPDistributeSimdDirective(
6557 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6558 if (LangOpts.OpenMP >= 50)
6559 AllowedNameModifiers.push_back(OMPD_simd);
6560 break;
6561 case OMPD_target_parallel_for_simd:
6562 Res = ActOnOpenMPTargetParallelForSimdDirective(
6563 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6564 AllowedNameModifiers.push_back(OMPD_target);
6565 AllowedNameModifiers.push_back(OMPD_parallel);
6566 if (LangOpts.OpenMP >= 50)
6567 AllowedNameModifiers.push_back(OMPD_simd);
6568 break;
6569 case OMPD_target_simd:
6570 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6571 EndLoc, VarsWithInheritedDSA);
6572 AllowedNameModifiers.push_back(OMPD_target);
6573 if (LangOpts.OpenMP >= 50)
6574 AllowedNameModifiers.push_back(OMPD_simd);
6575 break;
6576 case OMPD_teams_distribute:
6577 Res = ActOnOpenMPTeamsDistributeDirective(
6578 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6579 break;
6580 case OMPD_teams_distribute_simd:
6581 Res = ActOnOpenMPTeamsDistributeSimdDirective(
6582 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6583 if (LangOpts.OpenMP >= 50)
6584 AllowedNameModifiers.push_back(OMPD_simd);
6585 break;
6586 case OMPD_teams_distribute_parallel_for_simd:
6587 Res = ActOnOpenMPTeamsDistributeParallelForSimdDirective(
6588 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6589 AllowedNameModifiers.push_back(OMPD_parallel);
6590 if (LangOpts.OpenMP >= 50)
6591 AllowedNameModifiers.push_back(OMPD_simd);
6592 break;
6593 case OMPD_teams_distribute_parallel_for:
6594 Res = ActOnOpenMPTeamsDistributeParallelForDirective(
6595 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6596 AllowedNameModifiers.push_back(OMPD_parallel);
6597 break;
6598 case OMPD_target_teams:
6599 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6600 EndLoc);
6601 AllowedNameModifiers.push_back(OMPD_target);
6602 break;
6603 case OMPD_target_teams_distribute:
6604 Res = ActOnOpenMPTargetTeamsDistributeDirective(
6605 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6606 AllowedNameModifiers.push_back(OMPD_target);
6607 break;
6608 case OMPD_target_teams_distribute_parallel_for:
6609 Res = ActOnOpenMPTargetTeamsDistributeParallelForDirective(
6610 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6611 AllowedNameModifiers.push_back(OMPD_target);
6612 AllowedNameModifiers.push_back(OMPD_parallel);
6613 break;
6614 case OMPD_target_teams_distribute_parallel_for_simd:
6615 Res = ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
6616 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6617 AllowedNameModifiers.push_back(OMPD_target);
6618 AllowedNameModifiers.push_back(OMPD_parallel);
6619 if (LangOpts.OpenMP >= 50)
6620 AllowedNameModifiers.push_back(OMPD_simd);
6621 break;
6622 case OMPD_target_teams_distribute_simd:
6623 Res = ActOnOpenMPTargetTeamsDistributeSimdDirective(
6624 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6625 AllowedNameModifiers.push_back(OMPD_target);
6626 if (LangOpts.OpenMP >= 50)
6627 AllowedNameModifiers.push_back(OMPD_simd);
6628 break;
6629 case OMPD_interop:
6630 assert(AStmt == nullptr &&
6631 "No associated statement allowed for 'omp interop' directive");
6632 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6633 break;
6634 case OMPD_dispatch:
6635 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6636 EndLoc);
6637 break;
6638 case OMPD_loop:
6639 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6640 EndLoc, VarsWithInheritedDSA);
6641 break;
6642 case OMPD_teams_loop:
6643 Res = ActOnOpenMPTeamsGenericLoopDirective(
6644 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6645 break;
6646 case OMPD_target_teams_loop:
6647 Res = ActOnOpenMPTargetTeamsGenericLoopDirective(
6648 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6649 break;
6650 case OMPD_parallel_loop:
6651 Res = ActOnOpenMPParallelGenericLoopDirective(
6652 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6653 break;
6654 case OMPD_target_parallel_loop:
6655 Res = ActOnOpenMPTargetParallelGenericLoopDirective(
6656 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6657 break;
6658 case OMPD_declare_target:
6659 case OMPD_end_declare_target:
6660 case OMPD_threadprivate:
6661 case OMPD_allocate:
6662 case OMPD_declare_reduction:
6663 case OMPD_declare_mapper:
6664 case OMPD_declare_simd:
6665 case OMPD_requires:
6666 case OMPD_declare_variant:
6667 case OMPD_begin_declare_variant:
6668 case OMPD_end_declare_variant:
6669 llvm_unreachable("OpenMP Directive is not allowed");
6670 case OMPD_unknown:
6671 default:
6672 llvm_unreachable("Unknown OpenMP directive");
6673 }
6674
6675 ErrorFound = Res.isInvalid() || ErrorFound;
6676
6677 // Check variables in the clauses if default(none) or
6678 // default(firstprivate) was specified.
6679 if (DSAStack->getDefaultDSA() == DSA_none ||
6680 DSAStack->getDefaultDSA() == DSA_private ||
6681 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6682 DSAAttrChecker DSAChecker(DSAStack, *this, nullptr);
6683 for (OMPClause *C : Clauses) {
6684 switch (C->getClauseKind()) {
6685 case OMPC_num_threads:
6686 case OMPC_dist_schedule:
6687 // Do not analyse if no parent teams directive.
6688 if (isOpenMPTeamsDirective(Kind))
6689 break;
6690 continue;
6691 case OMPC_if:
6692 if (isOpenMPTeamsDirective(Kind) &&
6693 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6694 break;
6695 if (isOpenMPParallelDirective(Kind) &&
6696 isOpenMPTaskLoopDirective(Kind) &&
6697 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6698 break;
6699 continue;
6700 case OMPC_schedule:
6701 case OMPC_detach:
6702 break;
6703 case OMPC_grainsize:
6704 case OMPC_num_tasks:
6705 case OMPC_final:
6706 case OMPC_priority:
6707 case OMPC_novariants:
6708 case OMPC_nocontext:
6709 // Do not analyze if no parent parallel directive.
6710 if (isOpenMPParallelDirective(Kind))
6711 break;
6712 continue;
6713 case OMPC_ordered:
6714 case OMPC_device:
6715 case OMPC_num_teams:
6716 case OMPC_thread_limit:
6717 case OMPC_hint:
6718 case OMPC_collapse:
6719 case OMPC_safelen:
6720 case OMPC_simdlen:
6721 case OMPC_sizes:
6722 case OMPC_default:
6723 case OMPC_proc_bind:
6724 case OMPC_private:
6725 case OMPC_firstprivate:
6726 case OMPC_lastprivate:
6727 case OMPC_shared:
6728 case OMPC_reduction:
6729 case OMPC_task_reduction:
6730 case OMPC_in_reduction:
6731 case OMPC_linear:
6732 case OMPC_aligned:
6733 case OMPC_copyin:
6734 case OMPC_copyprivate:
6735 case OMPC_nowait:
6736 case OMPC_untied:
6737 case OMPC_mergeable:
6738 case OMPC_allocate:
6739 case OMPC_read:
6740 case OMPC_write:
6741 case OMPC_update:
6742 case OMPC_capture:
6743 case OMPC_compare:
6744 case OMPC_seq_cst:
6745 case OMPC_acq_rel:
6746 case OMPC_acquire:
6747 case OMPC_release:
6748 case OMPC_relaxed:
6749 case OMPC_depend:
6750 case OMPC_threads:
6751 case OMPC_simd:
6752 case OMPC_map:
6753 case OMPC_nogroup:
6754 case OMPC_defaultmap:
6755 case OMPC_to:
6756 case OMPC_from:
6757 case OMPC_use_device_ptr:
6758 case OMPC_use_device_addr:
6759 case OMPC_is_device_ptr:
6760 case OMPC_has_device_addr:
6761 case OMPC_nontemporal:
6762 case OMPC_order:
6763 case OMPC_destroy:
6764 case OMPC_inclusive:
6765 case OMPC_exclusive:
6766 case OMPC_uses_allocators:
6767 case OMPC_affinity:
6768 case OMPC_bind:
6769 case OMPC_filter:
6770 continue;
6771 case OMPC_allocator:
6772 case OMPC_flush:
6773 case OMPC_depobj:
6774 case OMPC_threadprivate:
6775 case OMPC_uniform:
6776 case OMPC_unknown:
6777 case OMPC_unified_address:
6778 case OMPC_unified_shared_memory:
6779 case OMPC_reverse_offload:
6780 case OMPC_dynamic_allocators:
6781 case OMPC_atomic_default_mem_order:
6782 case OMPC_device_type:
6783 case OMPC_match:
6784 case OMPC_when:
6785 case OMPC_at:
6786 case OMPC_severity:
6787 case OMPC_message:
6788 default:
6789 llvm_unreachable("Unexpected clause");
6790 }
6791 for (Stmt *CC : C->children()) {
6792 if (CC)
6793 DSAChecker.Visit(CC);
6794 }
6795 }
6796 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6797 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6798 }
6799 for (const auto &P : VarsWithInheritedDSA) {
6800 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6801 continue;
6802 ErrorFound = true;
6803 if (DSAStack->getDefaultDSA() == DSA_none ||
6804 DSAStack->getDefaultDSA() == DSA_private ||
6805 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6806 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6807 << P.first << P.second->getSourceRange();
6808 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6809 } else if (getLangOpts().OpenMP >= 50) {
6810 Diag(P.second->getExprLoc(),
6811 diag::err_omp_defaultmap_no_attr_for_variable)
6812 << P.first << P.second->getSourceRange();
6813 Diag(DSAStack->getDefaultDSALocation(),
6814 diag::note_omp_defaultmap_attr_none);
6815 }
6816 }
6817
6818 if (!AllowedNameModifiers.empty())
6819 ErrorFound = checkIfClauses(*this, Kind, Clauses, AllowedNameModifiers) ||
6820 ErrorFound;
6821
6822 if (ErrorFound)
6823 return StmtError();
6824
6825 if (!CurContext->isDependentContext() &&
6826 isOpenMPTargetExecutionDirective(Kind) &&
6827 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6828 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6829 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6830 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6831 // Register target to DSA Stack.
6832 DSAStack->addTargetDirLocation(StartLoc);
6833 }
6834
6835 return Res;
6836 }
6837
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)6838 Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
6839 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6840 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6841 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6842 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6843 assert(Aligneds.size() == Alignments.size());
6844 assert(Linears.size() == LinModifiers.size());
6845 assert(Linears.size() == Steps.size());
6846 if (!DG || DG.get().isNull())
6847 return DeclGroupPtrTy();
6848
6849 const int SimdId = 0;
6850 if (!DG.get().isSingleDecl()) {
6851 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6852 << SimdId;
6853 return DG;
6854 }
6855 Decl *ADecl = DG.get().getSingleDecl();
6856 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6857 ADecl = FTD->getTemplatedDecl();
6858
6859 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6860 if (!FD) {
6861 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6862 return DeclGroupPtrTy();
6863 }
6864
6865 // OpenMP [2.8.2, declare simd construct, Description]
6866 // The parameter of the simdlen clause must be a constant positive integer
6867 // expression.
6868 ExprResult SL;
6869 if (Simdlen)
6870 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6871 // OpenMP [2.8.2, declare simd construct, Description]
6872 // The special this pointer can be used as if was one of the arguments to the
6873 // function in any of the linear, aligned, or uniform clauses.
6874 // The uniform clause declares one or more arguments to have an invariant
6875 // value for all concurrent invocations of the function in the execution of a
6876 // single SIMD loop.
6877 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6878 const Expr *UniformedLinearThis = nullptr;
6879 for (const Expr *E : Uniforms) {
6880 E = E->IgnoreParenImpCasts();
6881 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6882 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6883 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6884 FD->getParamDecl(PVD->getFunctionScopeIndex())
6885 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
6886 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6887 continue;
6888 }
6889 if (isa<CXXThisExpr>(E)) {
6890 UniformedLinearThis = E;
6891 continue;
6892 }
6893 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6894 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6895 }
6896 // OpenMP [2.8.2, declare simd construct, Description]
6897 // The aligned clause declares that the object to which each list item points
6898 // is aligned to the number of bytes expressed in the optional parameter of
6899 // the aligned clause.
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 // The type of list items appearing in the aligned clause must be array,
6903 // pointer, reference to array, or reference to pointer.
6904 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6905 const Expr *AlignedThis = nullptr;
6906 for (const Expr *E : Aligneds) {
6907 E = E->IgnoreParenImpCasts();
6908 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6909 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6910 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6911 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6912 FD->getParamDecl(PVD->getFunctionScopeIndex())
6913 ->getCanonicalDecl() == CanonPVD) {
6914 // OpenMP [2.8.1, simd construct, Restrictions]
6915 // A list-item cannot appear in more than one aligned clause.
6916 if (AlignedArgs.count(CanonPVD) > 0) {
6917 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6918 << 1 << getOpenMPClauseName(OMPC_aligned)
6919 << E->getSourceRange();
6920 Diag(AlignedArgs[CanonPVD]->getExprLoc(),
6921 diag::note_omp_explicit_dsa)
6922 << getOpenMPClauseName(OMPC_aligned);
6923 continue;
6924 }
6925 AlignedArgs[CanonPVD] = E;
6926 QualType QTy = PVD->getType()
6927 .getNonReferenceType()
6928 .getUnqualifiedType()
6929 .getCanonicalType();
6930 const Type *Ty = QTy.getTypePtrOrNull();
6931 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
6932 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
6933 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
6934 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6935 }
6936 continue;
6937 }
6938 }
6939 if (isa<CXXThisExpr>(E)) {
6940 if (AlignedThis) {
6941 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6942 << 2 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange();
6943 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
6944 << getOpenMPClauseName(OMPC_aligned);
6945 }
6946 AlignedThis = E;
6947 continue;
6948 }
6949 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6950 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6951 }
6952 // The optional parameter of the aligned clause, alignment, must be a constant
6953 // positive integer expression. If no optional parameter is specified,
6954 // implementation-defined default alignments for SIMD instructions on the
6955 // target platforms are assumed.
6956 SmallVector<const Expr *, 4> NewAligns;
6957 for (Expr *E : Alignments) {
6958 ExprResult Align;
6959 if (E)
6960 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
6961 NewAligns.push_back(Align.get());
6962 }
6963 // OpenMP [2.8.2, declare simd construct, Description]
6964 // The linear clause declares one or more list items to be private to a SIMD
6965 // lane and to have a linear relationship with respect to the iteration space
6966 // of a loop.
6967 // The special this pointer can be used as if was one of the arguments to the
6968 // function in any of the linear, aligned, or uniform clauses.
6969 // When a linear-step expression is specified in a linear clause it must be
6970 // either a constant integer expression or an integer-typed parameter that is
6971 // specified in a uniform clause on the directive.
6972 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
6973 const bool IsUniformedThis = UniformedLinearThis != nullptr;
6974 auto MI = LinModifiers.begin();
6975 for (const Expr *E : Linears) {
6976 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
6977 ++MI;
6978 E = E->IgnoreParenImpCasts();
6979 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6980 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6981 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6982 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6983 FD->getParamDecl(PVD->getFunctionScopeIndex())
6984 ->getCanonicalDecl() == CanonPVD) {
6985 // OpenMP [2.15.3.7, linear Clause, Restrictions]
6986 // A list-item cannot appear in more than one linear clause.
6987 if (LinearArgs.count(CanonPVD) > 0) {
6988 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6989 << getOpenMPClauseName(OMPC_linear)
6990 << getOpenMPClauseName(OMPC_linear) << E->getSourceRange();
6991 Diag(LinearArgs[CanonPVD]->getExprLoc(),
6992 diag::note_omp_explicit_dsa)
6993 << getOpenMPClauseName(OMPC_linear);
6994 continue;
6995 }
6996 // Each argument can appear in at most one uniform or linear clause.
6997 if (UniformedArgs.count(CanonPVD) > 0) {
6998 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6999 << getOpenMPClauseName(OMPC_linear)
7000 << getOpenMPClauseName(OMPC_uniform) << E->getSourceRange();
7001 Diag(UniformedArgs[CanonPVD]->getExprLoc(),
7002 diag::note_omp_explicit_dsa)
7003 << getOpenMPClauseName(OMPC_uniform);
7004 continue;
7005 }
7006 LinearArgs[CanonPVD] = E;
7007 if (E->isValueDependent() || E->isTypeDependent() ||
7008 E->isInstantiationDependent() ||
7009 E->containsUnexpandedParameterPack())
7010 continue;
7011 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
7012 PVD->getOriginalType(),
7013 /*IsDeclareSimd=*/true);
7014 continue;
7015 }
7016 }
7017 if (isa<CXXThisExpr>(E)) {
7018 if (UniformedLinearThis) {
7019 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7020 << getOpenMPClauseName(OMPC_linear)
7021 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear)
7022 << E->getSourceRange();
7023 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
7024 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform
7025 : OMPC_linear);
7026 continue;
7027 }
7028 UniformedLinearThis = E;
7029 if (E->isValueDependent() || E->isTypeDependent() ||
7030 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
7031 continue;
7032 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
7033 E->getType(), /*IsDeclareSimd=*/true);
7034 continue;
7035 }
7036 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7037 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7038 }
7039 Expr *Step = nullptr;
7040 Expr *NewStep = nullptr;
7041 SmallVector<Expr *, 4> NewSteps;
7042 for (Expr *E : Steps) {
7043 // Skip the same step expression, it was checked already.
7044 if (Step == E || !E) {
7045 NewSteps.push_back(E ? NewStep : nullptr);
7046 continue;
7047 }
7048 Step = E;
7049 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
7050 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7051 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7052 if (UniformedArgs.count(CanonPVD) == 0) {
7053 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
7054 << Step->getSourceRange();
7055 } else if (E->isValueDependent() || E->isTypeDependent() ||
7056 E->isInstantiationDependent() ||
7057 E->containsUnexpandedParameterPack() ||
7058 CanonPVD->getType()->hasIntegerRepresentation()) {
7059 NewSteps.push_back(Step);
7060 } else {
7061 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
7062 << Step->getSourceRange();
7063 }
7064 continue;
7065 }
7066 NewStep = Step;
7067 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
7068 !Step->isInstantiationDependent() &&
7069 !Step->containsUnexpandedParameterPack()) {
7070 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
7071 .get();
7072 if (NewStep)
7073 NewStep =
7074 VerifyIntegerConstantExpression(NewStep, /*FIXME*/ AllowFold).get();
7075 }
7076 NewSteps.push_back(NewStep);
7077 }
7078 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7079 Context, BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
7080 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
7081 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
7082 const_cast<Expr **>(Linears.data()), Linears.size(),
7083 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
7084 NewSteps.data(), NewSteps.size(), SR);
7085 ADecl->addAttr(NewAttr);
7086 return DG;
7087 }
7088
setPrototype(Sema & S,FunctionDecl * FD,FunctionDecl * FDWithProto,QualType NewType)7089 static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7090 QualType NewType) {
7091 assert(NewType->isFunctionProtoType() &&
7092 "Expected function type with prototype.");
7093 assert(FD->getType()->isFunctionNoProtoType() &&
7094 "Expected function with type with no prototype.");
7095 assert(FDWithProto->getType()->isFunctionProtoType() &&
7096 "Expected function with prototype.");
7097 // Synthesize parameters with the same types.
7098 FD->setType(NewType);
7099 SmallVector<ParmVarDecl *, 16> Params;
7100 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7101 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
7102 SourceLocation(), nullptr, P->getType(),
7103 /*TInfo=*/nullptr, SC_None, nullptr);
7104 Param->setScopeInfo(0, Params.size());
7105 Param->setImplicit();
7106 Params.push_back(Param);
7107 }
7108
7109 FD->setParams(Params);
7110 }
7111
ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl * D)7112 void Sema::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) {
7113 if (D->isInvalidDecl())
7114 return;
7115 FunctionDecl *FD = nullptr;
7116 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7117 FD = UTemplDecl->getTemplatedDecl();
7118 else
7119 FD = cast<FunctionDecl>(D);
7120 assert(FD && "Expected a function declaration!");
7121
7122 // If we are instantiating templates we do *not* apply scoped assumptions but
7123 // only global ones. We apply scoped assumption to the template definition
7124 // though.
7125 if (!inTemplateInstantiation()) {
7126 for (AssumptionAttr *AA : OMPAssumeScoped)
7127 FD->addAttr(AA);
7128 }
7129 for (AssumptionAttr *AA : OMPAssumeGlobal)
7130 FD->addAttr(AA);
7131 }
7132
OMPDeclareVariantScope(OMPTraitInfo & TI)7133 Sema::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7134 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7135
ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope * S,Declarator & D,MultiTemplateParamsArg TemplateParamLists,SmallVectorImpl<FunctionDecl * > & Bases)7136 void Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
7137 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7138 SmallVectorImpl<FunctionDecl *> &Bases) {
7139 if (!D.getIdentifier())
7140 return;
7141
7142 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7143
7144 // Template specialization is an extension, check if we do it.
7145 bool IsTemplated = !TemplateParamLists.empty();
7146 if (IsTemplated &
7147 !DVScope.TI->isExtensionActive(
7148 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7149 return;
7150
7151 IdentifierInfo *BaseII = D.getIdentifier();
7152 LookupResult Lookup(*this, DeclarationName(BaseII), D.getIdentifierLoc(),
7153 LookupOrdinaryName);
7154 LookupParsedName(Lookup, S, &D.getCXXScopeSpec());
7155
7156 TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
7157 QualType FType = TInfo->getType();
7158
7159 bool IsConstexpr =
7160 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr;
7161 bool IsConsteval =
7162 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval;
7163
7164 for (auto *Candidate : Lookup) {
7165 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7166 FunctionDecl *UDecl = nullptr;
7167 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7168 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7169 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7170 UDecl = FTD->getTemplatedDecl();
7171 } else if (!IsTemplated)
7172 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7173 if (!UDecl)
7174 continue;
7175
7176 // Don't specialize constexpr/consteval functions with
7177 // non-constexpr/consteval functions.
7178 if (UDecl->isConstexpr() && !IsConstexpr)
7179 continue;
7180 if (UDecl->isConsteval() && !IsConsteval)
7181 continue;
7182
7183 QualType UDeclTy = UDecl->getType();
7184 if (!UDeclTy->isDependentType()) {
7185 QualType NewType = Context.mergeFunctionTypes(
7186 FType, UDeclTy, /* OfBlockPointer */ false,
7187 /* Unqualified */ false, /* AllowCXX */ true);
7188 if (NewType.isNull())
7189 continue;
7190 }
7191
7192 // Found a base!
7193 Bases.push_back(UDecl);
7194 }
7195
7196 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7197 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7198 // If no base was found we create a declaration that we use as base.
7199 if (Bases.empty() && UseImplicitBase) {
7200 D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
7201 Decl *BaseD = HandleDeclarator(S, D, TemplateParamLists);
7202 BaseD->setImplicit(true);
7203 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7204 Bases.push_back(BaseTemplD->getTemplatedDecl());
7205 else
7206 Bases.push_back(cast<FunctionDecl>(BaseD));
7207 }
7208
7209 std::string MangledName;
7210 MangledName += D.getIdentifier()->getName();
7211 MangledName += getOpenMPVariantManglingSeparatorStr();
7212 MangledName += DVScope.NameSuffix;
7213 IdentifierInfo &VariantII = Context.Idents.get(MangledName);
7214
7215 VariantII.setMangledOpenMPVariantName(true);
7216 D.SetIdentifier(&VariantII, D.getBeginLoc());
7217 }
7218
ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(Decl * D,SmallVectorImpl<FunctionDecl * > & Bases)7219 void Sema::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
7220 Decl *D, SmallVectorImpl<FunctionDecl *> &Bases) {
7221 // Do not mark function as is used to prevent its emission if this is the
7222 // only place where it is used.
7223 EnterExpressionEvaluationContext Unevaluated(
7224 *this, Sema::ExpressionEvaluationContext::Unevaluated);
7225
7226 FunctionDecl *FD = nullptr;
7227 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7228 FD = UTemplDecl->getTemplatedDecl();
7229 else
7230 FD = cast<FunctionDecl>(D);
7231 auto *VariantFuncRef = DeclRefExpr::Create(
7232 Context, NestedNameSpecifierLoc(), SourceLocation(), FD,
7233 /* RefersToEnclosingVariableOrCapture */ false,
7234 /* NameLoc */ FD->getLocation(), FD->getType(),
7235 ExprValueKind::VK_PRValue);
7236
7237 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7238 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7239 Context, VariantFuncRef, DVScope.TI,
7240 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7241 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7242 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7243 for (FunctionDecl *BaseFD : Bases)
7244 BaseFD->addAttr(OMPDeclareVariantA);
7245 }
7246
ActOnOpenMPCall(ExprResult Call,Scope * Scope,SourceLocation LParenLoc,MultiExprArg ArgExprs,SourceLocation RParenLoc,Expr * ExecConfig)7247 ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
7248 SourceLocation LParenLoc,
7249 MultiExprArg ArgExprs,
7250 SourceLocation RParenLoc, Expr *ExecConfig) {
7251 // The common case is a regular call we do not want to specialize at all. Try
7252 // to make that case fast by bailing early.
7253 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7254 if (!CE)
7255 return Call;
7256
7257 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7258 if (!CalleeFnDecl)
7259 return Call;
7260
7261 if (LangOpts.OpenMP >= 51 && CalleeFnDecl->getIdentifier() &&
7262 CalleeFnDecl->getName().startswith_insensitive("omp_")) {
7263 // checking for any calls inside an Order region
7264 if (Scope && Scope->isOpenMPOrderClauseScope())
7265 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7266 }
7267
7268 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7269 return Call;
7270
7271 ASTContext &Context = getASTContext();
7272 std::function<void(StringRef)> DiagUnknownTrait = [this,
7273 CE](StringRef ISATrait) {
7274 // TODO Track the selector locations in a way that is accessible here to
7275 // improve the diagnostic location.
7276 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7277 << ISATrait;
7278 };
7279 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7280 getCurFunctionDecl(), DSAStack->getConstructTraits());
7281
7282 QualType CalleeFnType = CalleeFnDecl->getType();
7283
7284 SmallVector<Expr *, 4> Exprs;
7285 SmallVector<VariantMatchInfo, 4> VMIs;
7286 while (CalleeFnDecl) {
7287 for (OMPDeclareVariantAttr *A :
7288 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7289 Expr *VariantRef = A->getVariantFuncRef();
7290
7291 VariantMatchInfo VMI;
7292 OMPTraitInfo &TI = A->getTraitInfo();
7293 TI.getAsVariantMatchInfo(Context, VMI);
7294 if (!isVariantApplicableInContext(VMI, OMPCtx,
7295 /* DeviceSetOnly */ false))
7296 continue;
7297
7298 VMIs.push_back(VMI);
7299 Exprs.push_back(VariantRef);
7300 }
7301
7302 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7303 }
7304
7305 ExprResult NewCall;
7306 do {
7307 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7308 if (BestIdx < 0)
7309 return Call;
7310 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7311 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7312
7313 {
7314 // Try to build a (member) call expression for the current best applicable
7315 // variant expression. We allow this to fail in which case we continue
7316 // with the next best variant expression. The fail case is part of the
7317 // implementation defined behavior in the OpenMP standard when it talks
7318 // about what differences in the function prototypes: "Any differences
7319 // that the specific OpenMP context requires in the prototype of the
7320 // variant from the base function prototype are implementation defined."
7321 // This wording is there to allow the specialized variant to have a
7322 // different type than the base function. This is intended and OK but if
7323 // we cannot create a call the difference is not in the "implementation
7324 // defined range" we allow.
7325 Sema::TentativeAnalysisScope Trap(*this);
7326
7327 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7328 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7329 BestExpr = MemberExpr::CreateImplicit(
7330 Context, MemberCall->getImplicitObjectArgument(),
7331 /* IsArrow */ false, SpecializedMethod, Context.BoundMemberTy,
7332 MemberCall->getValueKind(), MemberCall->getObjectKind());
7333 }
7334 NewCall = BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs, RParenLoc,
7335 ExecConfig);
7336 if (NewCall.isUsable()) {
7337 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7338 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7339 QualType NewType = Context.mergeFunctionTypes(
7340 CalleeFnType, NewCalleeFnDecl->getType(),
7341 /* OfBlockPointer */ false,
7342 /* Unqualified */ false, /* AllowCXX */ true);
7343 if (!NewType.isNull())
7344 break;
7345 // Don't use the call if the function type was not compatible.
7346 NewCall = nullptr;
7347 }
7348 }
7349 }
7350
7351 VMIs.erase(VMIs.begin() + BestIdx);
7352 Exprs.erase(Exprs.begin() + BestIdx);
7353 } while (!VMIs.empty());
7354
7355 if (!NewCall.isUsable())
7356 return Call;
7357 return PseudoObjectExpr::Create(Context, CE, {NewCall.get()}, 0);
7358 }
7359
7360 std::optional<std::pair<FunctionDecl *, Expr *>>
checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG,Expr * VariantRef,OMPTraitInfo & TI,unsigned NumAppendArgs,SourceRange SR)7361 Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG,
7362 Expr *VariantRef, OMPTraitInfo &TI,
7363 unsigned NumAppendArgs,
7364 SourceRange SR) {
7365 if (!DG || DG.get().isNull())
7366 return std::nullopt;
7367
7368 const int VariantId = 1;
7369 // Must be applied only to single decl.
7370 if (!DG.get().isSingleDecl()) {
7371 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7372 << VariantId << SR;
7373 return std::nullopt;
7374 }
7375 Decl *ADecl = DG.get().getSingleDecl();
7376 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7377 ADecl = FTD->getTemplatedDecl();
7378
7379 // Decl must be a function.
7380 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7381 if (!FD) {
7382 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7383 << VariantId << SR;
7384 return std::nullopt;
7385 }
7386
7387 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7388 // The 'target' attribute needs to be separately checked because it does
7389 // not always signify a multiversion function declaration.
7390 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7391 };
7392 // OpenMP is not compatible with multiversion function attributes.
7393 if (HasMultiVersionAttributes(FD)) {
7394 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7395 << SR;
7396 return std::nullopt;
7397 }
7398
7399 // Allow #pragma omp declare variant only if the function is not used.
7400 if (FD->isUsed(false))
7401 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7402 << FD->getLocation();
7403
7404 // Check if the function was emitted already.
7405 const FunctionDecl *Definition;
7406 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7407 (LangOpts.EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7408 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7409 << FD->getLocation();
7410
7411 // The VariantRef must point to function.
7412 if (!VariantRef) {
7413 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7414 return std::nullopt;
7415 }
7416
7417 auto ShouldDelayChecks = [](Expr *&E, bool) {
7418 return E && (E->isTypeDependent() || E->isValueDependent() ||
7419 E->containsUnexpandedParameterPack() ||
7420 E->isInstantiationDependent());
7421 };
7422 // Do not check templates, wait until instantiation.
7423 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7424 TI.anyScoreOrCondition(ShouldDelayChecks))
7425 return std::make_pair(FD, VariantRef);
7426
7427 // Deal with non-constant score and user condition expressions.
7428 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7429 bool IsScore) -> bool {
7430 if (!E || E->isIntegerConstantExpr(Context))
7431 return false;
7432
7433 if (IsScore) {
7434 // We warn on non-constant scores and pretend they were not present.
7435 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7436 << E;
7437 E = nullptr;
7438 } else {
7439 // We could replace a non-constant user condition with "false" but we
7440 // will soon need to handle these anyway for the dynamic version of
7441 // OpenMP context selectors.
7442 Diag(E->getExprLoc(),
7443 diag::err_omp_declare_variant_user_condition_not_constant)
7444 << E;
7445 }
7446 return true;
7447 };
7448 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7449 return std::nullopt;
7450
7451 QualType AdjustedFnType = FD->getType();
7452 if (NumAppendArgs) {
7453 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7454 if (!PTy) {
7455 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7456 << SR;
7457 return std::nullopt;
7458 }
7459 // Adjust the function type to account for an extra omp_interop_t for each
7460 // specified in the append_args clause.
7461 const TypeDecl *TD = nullptr;
7462 LookupResult Result(*this, &Context.Idents.get("omp_interop_t"),
7463 SR.getBegin(), Sema::LookupOrdinaryName);
7464 if (LookupName(Result, getCurScope())) {
7465 NamedDecl *ND = Result.getFoundDecl();
7466 TD = dyn_cast_or_null<TypeDecl>(ND);
7467 }
7468 if (!TD) {
7469 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7470 return std::nullopt;
7471 }
7472 QualType InteropType = Context.getTypeDeclType(TD);
7473 if (PTy->isVariadic()) {
7474 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7475 return std::nullopt;
7476 }
7477 llvm::SmallVector<QualType, 8> Params;
7478 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7479 Params.insert(Params.end(), NumAppendArgs, InteropType);
7480 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7481 PTy->getExtProtoInfo());
7482 }
7483
7484 // Convert VariantRef expression to the type of the original function to
7485 // resolve possible conflicts.
7486 ExprResult VariantRefCast = VariantRef;
7487 if (LangOpts.CPlusPlus) {
7488 QualType FnPtrType;
7489 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7490 if (Method && !Method->isStatic()) {
7491 const Type *ClassType =
7492 Context.getTypeDeclType(Method->getParent()).getTypePtr();
7493 FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType);
7494 ExprResult ER;
7495 {
7496 // Build adrr_of unary op to correctly handle type checks for member
7497 // functions.
7498 Sema::TentativeAnalysisScope Trap(*this);
7499 ER = CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7500 VariantRef);
7501 }
7502 if (!ER.isUsable()) {
7503 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7504 << VariantId << VariantRef->getSourceRange();
7505 return std::nullopt;
7506 }
7507 VariantRef = ER.get();
7508 } else {
7509 FnPtrType = Context.getPointerType(AdjustedFnType);
7510 }
7511 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7512 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7513 ImplicitConversionSequence ICS = TryImplicitConversion(
7514 VariantRef, FnPtrType.getUnqualifiedType(),
7515 /*SuppressUserConversions=*/false, AllowedExplicit::None,
7516 /*InOverloadResolution=*/false,
7517 /*CStyle=*/false,
7518 /*AllowObjCWritebackConversion=*/false);
7519 if (ICS.isFailure()) {
7520 Diag(VariantRef->getExprLoc(),
7521 diag::err_omp_declare_variant_incompat_types)
7522 << VariantRef->getType()
7523 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7524 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7525 return std::nullopt;
7526 }
7527 VariantRefCast = PerformImplicitConversion(
7528 VariantRef, FnPtrType.getUnqualifiedType(), AA_Converting);
7529 if (!VariantRefCast.isUsable())
7530 return std::nullopt;
7531 }
7532 // Drop previously built artificial addr_of unary op for member functions.
7533 if (Method && !Method->isStatic()) {
7534 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7535 if (auto *UO = dyn_cast<UnaryOperator>(
7536 PossibleAddrOfVariantRef->IgnoreImplicit()))
7537 VariantRefCast = UO->getSubExpr();
7538 }
7539 }
7540
7541 ExprResult ER = CheckPlaceholderExpr(VariantRefCast.get());
7542 if (!ER.isUsable() ||
7543 !ER.get()->IgnoreParenImpCasts()->getType()->isFunctionType()) {
7544 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7545 << VariantId << VariantRef->getSourceRange();
7546 return std::nullopt;
7547 }
7548
7549 // The VariantRef must point to function.
7550 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7551 if (!DRE) {
7552 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7553 << VariantId << VariantRef->getSourceRange();
7554 return std::nullopt;
7555 }
7556 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7557 if (!NewFD) {
7558 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7559 << VariantId << VariantRef->getSourceRange();
7560 return std::nullopt;
7561 }
7562
7563 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7564 Diag(VariantRef->getExprLoc(),
7565 diag::err_omp_declare_variant_same_base_function)
7566 << VariantRef->getSourceRange();
7567 return std::nullopt;
7568 }
7569
7570 // Check if function types are compatible in C.
7571 if (!LangOpts.CPlusPlus) {
7572 QualType NewType =
7573 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7574 if (NewType.isNull()) {
7575 Diag(VariantRef->getExprLoc(),
7576 diag::err_omp_declare_variant_incompat_types)
7577 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7578 << VariantRef->getSourceRange();
7579 return std::nullopt;
7580 }
7581 if (NewType->isFunctionProtoType()) {
7582 if (FD->getType()->isFunctionNoProtoType())
7583 setPrototype(*this, FD, NewFD, NewType);
7584 else if (NewFD->getType()->isFunctionNoProtoType())
7585 setPrototype(*this, NewFD, FD, NewType);
7586 }
7587 }
7588
7589 // Check if variant function is not marked with declare variant directive.
7590 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7591 Diag(VariantRef->getExprLoc(),
7592 diag::warn_omp_declare_variant_marked_as_declare_variant)
7593 << VariantRef->getSourceRange();
7594 SourceRange SR =
7595 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7596 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7597 return std::nullopt;
7598 }
7599
7600 enum DoesntSupport {
7601 VirtFuncs = 1,
7602 Constructors = 3,
7603 Destructors = 4,
7604 DeletedFuncs = 5,
7605 DefaultedFuncs = 6,
7606 ConstexprFuncs = 7,
7607 ConstevalFuncs = 8,
7608 };
7609 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7610 if (CXXFD->isVirtual()) {
7611 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7612 << VirtFuncs;
7613 return std::nullopt;
7614 }
7615
7616 if (isa<CXXConstructorDecl>(FD)) {
7617 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7618 << Constructors;
7619 return std::nullopt;
7620 }
7621
7622 if (isa<CXXDestructorDecl>(FD)) {
7623 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7624 << Destructors;
7625 return std::nullopt;
7626 }
7627 }
7628
7629 if (FD->isDeleted()) {
7630 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7631 << DeletedFuncs;
7632 return std::nullopt;
7633 }
7634
7635 if (FD->isDefaulted()) {
7636 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7637 << DefaultedFuncs;
7638 return std::nullopt;
7639 }
7640
7641 if (FD->isConstexpr()) {
7642 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7643 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7644 return std::nullopt;
7645 }
7646
7647 // Check general compatibility.
7648 if (areMultiversionVariantFunctionsCompatible(
7649 FD, NewFD, PartialDiagnostic::NullDiagnostic(),
7650 PartialDiagnosticAt(SourceLocation(),
7651 PartialDiagnostic::NullDiagnostic()),
7652 PartialDiagnosticAt(
7653 VariantRef->getExprLoc(),
7654 PDiag(diag::err_omp_declare_variant_doesnt_support)),
7655 PartialDiagnosticAt(VariantRef->getExprLoc(),
7656 PDiag(diag::err_omp_declare_variant_diff)
7657 << FD->getLocation()),
7658 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7659 /*CLinkageMayDiffer=*/true))
7660 return std::nullopt;
7661 return std::make_pair(FD, cast<Expr>(DRE));
7662 }
7663
ActOnOpenMPDeclareVariantDirective(FunctionDecl * FD,Expr * VariantRef,OMPTraitInfo & TI,ArrayRef<Expr * > AdjustArgsNothing,ArrayRef<Expr * > AdjustArgsNeedDevicePtr,ArrayRef<OMPInteropInfo> AppendArgs,SourceLocation AdjustArgsLoc,SourceLocation AppendArgsLoc,SourceRange SR)7664 void Sema::ActOnOpenMPDeclareVariantDirective(
7665 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7666 ArrayRef<Expr *> AdjustArgsNothing,
7667 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7668 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7669 SourceLocation AppendArgsLoc, SourceRange SR) {
7670
7671 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7672 // An adjust_args clause or append_args clause can only be specified if the
7673 // dispatch selector of the construct selector set appears in the match
7674 // clause.
7675
7676 SmallVector<Expr *, 8> AllAdjustArgs;
7677 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7678 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7679
7680 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7681 VariantMatchInfo VMI;
7682 TI.getAsVariantMatchInfo(Context, VMI);
7683 if (!llvm::is_contained(
7684 VMI.ConstructTraits,
7685 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7686 if (!AllAdjustArgs.empty())
7687 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7688 << getOpenMPClauseName(OMPC_adjust_args);
7689 if (!AppendArgs.empty())
7690 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7691 << getOpenMPClauseName(OMPC_append_args);
7692 return;
7693 }
7694 }
7695
7696 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7697 // Each argument can only appear in a single adjust_args clause for each
7698 // declare variant directive.
7699 llvm::SmallPtrSet<const VarDecl *, 4> AdjustVars;
7700
7701 for (Expr *E : AllAdjustArgs) {
7702 E = E->IgnoreParenImpCasts();
7703 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7704 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7705 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7706 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7707 FD->getParamDecl(PVD->getFunctionScopeIndex())
7708 ->getCanonicalDecl() == CanonPVD) {
7709 // It's a parameter of the function, check duplicates.
7710 if (!AdjustVars.insert(CanonPVD).second) {
7711 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7712 << PVD;
7713 return;
7714 }
7715 continue;
7716 }
7717 }
7718 }
7719 // Anything that is not a function parameter is an error.
7720 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7721 return;
7722 }
7723
7724 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7725 Context, VariantRef, &TI, const_cast<Expr **>(AdjustArgsNothing.data()),
7726 AdjustArgsNothing.size(),
7727 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7728 AdjustArgsNeedDevicePtr.size(),
7729 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7730 FD->addAttr(NewAttr);
7731 }
7732
ActOnOpenMPParallelDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)7733 StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
7734 Stmt *AStmt,
7735 SourceLocation StartLoc,
7736 SourceLocation EndLoc) {
7737 if (!AStmt)
7738 return StmtError();
7739
7740 auto *CS = cast<CapturedStmt>(AStmt);
7741 // 1.2.2 OpenMP Language Terminology
7742 // Structured block - An executable statement with a single entry at the
7743 // top and a single exit at the bottom.
7744 // The point of exit cannot be a branch out of the structured block.
7745 // longjmp() and throw() must not violate the entry/exit criteria.
7746 CS->getCapturedDecl()->setNothrow();
7747
7748 setFunctionHasBranchProtectedScope();
7749
7750 return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
7751 DSAStack->getTaskgroupReductionRef(),
7752 DSAStack->isCancelRegion());
7753 }
7754
7755 namespace {
7756 /// Iteration space of a single for loop.
7757 struct LoopIterationSpace final {
7758 /// True if the condition operator is the strict compare operator (<, > or
7759 /// !=).
7760 bool IsStrictCompare = false;
7761 /// Condition of the loop.
7762 Expr *PreCond = nullptr;
7763 /// This expression calculates the number of iterations in the loop.
7764 /// It is always possible to calculate it before starting the loop.
7765 Expr *NumIterations = nullptr;
7766 /// The loop counter variable.
7767 Expr *CounterVar = nullptr;
7768 /// Private loop counter variable.
7769 Expr *PrivateCounterVar = nullptr;
7770 /// This is initializer for the initial value of #CounterVar.
7771 Expr *CounterInit = nullptr;
7772 /// This is step for the #CounterVar used to generate its update:
7773 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7774 Expr *CounterStep = nullptr;
7775 /// Should step be subtracted?
7776 bool Subtract = false;
7777 /// Source range of the loop init.
7778 SourceRange InitSrcRange;
7779 /// Source range of the loop condition.
7780 SourceRange CondSrcRange;
7781 /// Source range of the loop increment.
7782 SourceRange IncSrcRange;
7783 /// Minimum value that can have the loop control variable. Used to support
7784 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7785 /// since only such variables can be used in non-loop invariant expressions.
7786 Expr *MinValue = nullptr;
7787 /// Maximum value that can have the loop control variable. Used to support
7788 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7789 /// since only such variables can be used in non-loop invariant expressions.
7790 Expr *MaxValue = nullptr;
7791 /// true, if the lower bound depends on the outer loop control var.
7792 bool IsNonRectangularLB = false;
7793 /// true, if the upper bound depends on the outer loop control var.
7794 bool IsNonRectangularUB = false;
7795 /// Index of the loop this loop depends on and forms non-rectangular loop
7796 /// nest.
7797 unsigned LoopDependentIdx = 0;
7798 /// Final condition for the non-rectangular loop nest support. It is used to
7799 /// check that the number of iterations for this particular counter must be
7800 /// finished.
7801 Expr *FinalCondition = nullptr;
7802 };
7803
7804 /// Helper class for checking canonical form of the OpenMP loops and
7805 /// extracting iteration space of each loop in the loop nest, that will be used
7806 /// for IR generation.
7807 class OpenMPIterationSpaceChecker {
7808 /// Reference to Sema.
7809 Sema &SemaRef;
7810 /// Does the loop associated directive support non-rectangular loops?
7811 bool SupportsNonRectangular;
7812 /// Data-sharing stack.
7813 DSAStackTy &Stack;
7814 /// A location for diagnostics (when there is no some better location).
7815 SourceLocation DefaultLoc;
7816 /// A location for diagnostics (when increment is not compatible).
7817 SourceLocation ConditionLoc;
7818 /// A source location for referring to loop init later.
7819 SourceRange InitSrcRange;
7820 /// A source location for referring to condition later.
7821 SourceRange ConditionSrcRange;
7822 /// A source location for referring to increment later.
7823 SourceRange IncrementSrcRange;
7824 /// Loop variable.
7825 ValueDecl *LCDecl = nullptr;
7826 /// Reference to loop variable.
7827 Expr *LCRef = nullptr;
7828 /// Lower bound (initializer for the var).
7829 Expr *LB = nullptr;
7830 /// Upper bound.
7831 Expr *UB = nullptr;
7832 /// Loop step (increment).
7833 Expr *Step = nullptr;
7834 /// This flag is true when condition is one of:
7835 /// Var < UB
7836 /// Var <= UB
7837 /// UB > Var
7838 /// UB >= Var
7839 /// This will have no value when the condition is !=
7840 std::optional<bool> TestIsLessOp;
7841 /// This flag is true when condition is strict ( < or > ).
7842 bool TestIsStrictOp = false;
7843 /// This flag is true when step is subtracted on each iteration.
7844 bool SubtractStep = false;
7845 /// The outer loop counter this loop depends on (if any).
7846 const ValueDecl *DepDecl = nullptr;
7847 /// Contains number of loop (starts from 1) on which loop counter init
7848 /// expression of this loop depends on.
7849 std::optional<unsigned> InitDependOnLC;
7850 /// Contains number of loop (starts from 1) on which loop counter condition
7851 /// expression of this loop depends on.
7852 std::optional<unsigned> CondDependOnLC;
7853 /// Checks if the provide statement depends on the loop counter.
7854 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
7855 bool IsInitializer);
7856 /// Original condition required for checking of the exit condition for
7857 /// non-rectangular loop.
7858 Expr *Condition = nullptr;
7859
7860 public:
OpenMPIterationSpaceChecker(Sema & SemaRef,bool SupportsNonRectangular,DSAStackTy & Stack,SourceLocation DefaultLoc)7861 OpenMPIterationSpaceChecker(Sema &SemaRef, bool SupportsNonRectangular,
7862 DSAStackTy &Stack, SourceLocation DefaultLoc)
7863 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7864 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {}
7865 /// Check init-expr for canonical loop form and save loop counter
7866 /// variable - #Var and its initialization value - #LB.
7867 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
7868 /// Check test-expr for canonical form, save upper-bound (#UB), flags
7869 /// for less/greater and for strict/non-strict comparison.
7870 bool checkAndSetCond(Expr *S);
7871 /// Check incr-expr for canonical loop form and return true if it
7872 /// does not conform, otherwise save loop step (#Step).
7873 bool checkAndSetInc(Expr *S);
7874 /// Return the loop counter variable.
getLoopDecl() const7875 ValueDecl *getLoopDecl() const { return LCDecl; }
7876 /// Return the reference expression to loop counter variable.
getLoopDeclRefExpr() const7877 Expr *getLoopDeclRefExpr() const { return LCRef; }
7878 /// Source range of the loop init.
getInitSrcRange() const7879 SourceRange getInitSrcRange() const { return InitSrcRange; }
7880 /// Source range of the loop condition.
getConditionSrcRange() const7881 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
7882 /// Source range of the loop increment.
getIncrementSrcRange() const7883 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
7884 /// True if the step should be subtracted.
shouldSubtractStep() const7885 bool shouldSubtractStep() const { return SubtractStep; }
7886 /// True, if the compare operator is strict (<, > or !=).
isStrictTestOp() const7887 bool isStrictTestOp() const { return TestIsStrictOp; }
7888 /// Build the expression to calculate the number of iterations.
7889 Expr *buildNumIterations(
7890 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
7891 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7892 /// Build the precondition expression for the loops.
7893 Expr *
7894 buildPreCond(Scope *S, Expr *Cond,
7895 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7896 /// Build reference expression to the counter be used for codegen.
7897 DeclRefExpr *
7898 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7899 DSAStackTy &DSA) const;
7900 /// Build reference expression to the private counter be used for
7901 /// codegen.
7902 Expr *buildPrivateCounterVar() const;
7903 /// Build initialization of the counter be used for codegen.
7904 Expr *buildCounterInit() const;
7905 /// Build step of the counter be used for codegen.
7906 Expr *buildCounterStep() const;
7907 /// Build loop data with counter value for depend clauses in ordered
7908 /// directives.
7909 Expr *
7910 buildOrderedLoopData(Scope *S, Expr *Counter,
7911 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7912 SourceLocation Loc, Expr *Inc = nullptr,
7913 OverloadedOperatorKind OOK = OO_Amp);
7914 /// Builds the minimum value for the loop counter.
7915 std::pair<Expr *, Expr *> buildMinMaxValues(
7916 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7917 /// Builds final condition for the non-rectangular loops.
7918 Expr *buildFinalCondition(Scope *S) const;
7919 /// Return true if any expression is dependent.
7920 bool dependent() const;
7921 /// Returns true if the initializer forms non-rectangular loop.
doesInitDependOnLC() const7922 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
7923 /// Returns true if the condition forms non-rectangular loop.
doesCondDependOnLC() const7924 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
7925 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
getLoopDependentIdx() const7926 unsigned getLoopDependentIdx() const {
7927 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
7928 }
7929
7930 private:
7931 /// Check the right-hand side of an assignment in the increment
7932 /// expression.
7933 bool checkAndSetIncRHS(Expr *RHS);
7934 /// Helper to set loop counter variable and its initializer.
7935 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
7936 bool EmitDiags);
7937 /// Helper to set upper bound.
7938 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
7939 SourceRange SR, SourceLocation SL);
7940 /// Helper to set loop increment.
7941 bool setStep(Expr *NewStep, bool Subtract);
7942 };
7943
dependent() const7944 bool OpenMPIterationSpaceChecker::dependent() const {
7945 if (!LCDecl) {
7946 assert(!LB && !UB && !Step);
7947 return false;
7948 }
7949 return LCDecl->getType()->isDependentType() ||
7950 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
7951 (Step && Step->isValueDependent());
7952 }
7953
setLCDeclAndLB(ValueDecl * NewLCDecl,Expr * NewLCRefExpr,Expr * NewLB,bool EmitDiags)7954 bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
7955 Expr *NewLCRefExpr,
7956 Expr *NewLB, bool EmitDiags) {
7957 // State consistency checking to ensure correct usage.
7958 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
7959 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7960 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
7961 return true;
7962 LCDecl = getCanonicalDecl(NewLCDecl);
7963 LCRef = NewLCRefExpr;
7964 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
7965 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
7966 if ((Ctor->isCopyOrMoveConstructor() ||
7967 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
7968 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
7969 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
7970 LB = NewLB;
7971 if (EmitDiags)
7972 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
7973 return false;
7974 }
7975
setUB(Expr * NewUB,std::optional<bool> LessOp,bool StrictOp,SourceRange SR,SourceLocation SL)7976 bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
7977 bool StrictOp, SourceRange SR,
7978 SourceLocation SL) {
7979 // State consistency checking to ensure correct usage.
7980 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
7981 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7982 if (!NewUB || NewUB->containsErrors())
7983 return true;
7984 UB = NewUB;
7985 if (LessOp)
7986 TestIsLessOp = LessOp;
7987 TestIsStrictOp = StrictOp;
7988 ConditionSrcRange = SR;
7989 ConditionLoc = SL;
7990 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
7991 return false;
7992 }
7993
setStep(Expr * NewStep,bool Subtract)7994 bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
7995 // State consistency checking to ensure correct usage.
7996 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
7997 if (!NewStep || NewStep->containsErrors())
7998 return true;
7999 if (!NewStep->isValueDependent()) {
8000 // Check that the step is integer expression.
8001 SourceLocation StepLoc = NewStep->getBeginLoc();
8002 ExprResult Val = SemaRef.PerformOpenMPImplicitIntegerConversion(
8003 StepLoc, getExprAsWritten(NewStep));
8004 if (Val.isInvalid())
8005 return true;
8006 NewStep = Val.get();
8007
8008 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8009 // If test-expr is of form var relational-op b and relational-op is < or
8010 // <= then incr-expr must cause var to increase on each iteration of the
8011 // loop. If test-expr is of form var relational-op b and relational-op is
8012 // > or >= then incr-expr must cause var to decrease on each iteration of
8013 // the loop.
8014 // If test-expr is of form b relational-op var and relational-op is < or
8015 // <= then incr-expr must cause var to decrease on each iteration of the
8016 // loop. If test-expr is of form b relational-op var and relational-op is
8017 // > or >= then incr-expr must cause var to increase on each iteration of
8018 // the loop.
8019 std::optional<llvm::APSInt> Result =
8020 NewStep->getIntegerConstantExpr(SemaRef.Context);
8021 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
8022 bool IsConstNeg =
8023 Result && Result->isSigned() && (Subtract != Result->isNegative());
8024 bool IsConstPos =
8025 Result && Result->isSigned() && (Subtract == Result->isNegative());
8026 bool IsConstZero = Result && !Result->getBoolValue();
8027
8028 // != with increment is treated as <; != with decrement is treated as >
8029 if (!TestIsLessOp)
8030 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8031 if (UB && (IsConstZero ||
8032 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8033 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8034 SemaRef.Diag(NewStep->getExprLoc(),
8035 diag::err_omp_loop_incr_not_compatible)
8036 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
8037 SemaRef.Diag(ConditionLoc,
8038 diag::note_omp_loop_cond_requres_compatible_incr)
8039 << *TestIsLessOp << ConditionSrcRange;
8040 return true;
8041 }
8042 if (*TestIsLessOp == Subtract) {
8043 NewStep =
8044 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
8045 .get();
8046 Subtract = !Subtract;
8047 }
8048 }
8049
8050 Step = NewStep;
8051 SubtractStep = Subtract;
8052 return false;
8053 }
8054
8055 namespace {
8056 /// Checker for the non-rectangular loops. Checks if the initializer or
8057 /// condition expression references loop counter variable.
8058 class LoopCounterRefChecker final
8059 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8060 Sema &SemaRef;
8061 DSAStackTy &Stack;
8062 const ValueDecl *CurLCDecl = nullptr;
8063 const ValueDecl *DepDecl = nullptr;
8064 const ValueDecl *PrevDepDecl = nullptr;
8065 bool IsInitializer = true;
8066 bool SupportsNonRectangular;
8067 unsigned BaseLoopId = 0;
checkDecl(const Expr * E,const ValueDecl * VD)8068 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8069 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
8070 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8071 << (IsInitializer ? 0 : 1);
8072 return false;
8073 }
8074 const auto &&Data = Stack.isLoopControlVariable(VD);
8075 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8076 // The type of the loop iterator on which we depend may not have a random
8077 // access iterator type.
8078 if (Data.first && VD->getType()->isRecordType()) {
8079 SmallString<128> Name;
8080 llvm::raw_svector_ostream OS(Name);
8081 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8082 /*Qualified=*/true);
8083 SemaRef.Diag(E->getExprLoc(),
8084 diag::err_omp_wrong_dependency_iterator_type)
8085 << OS.str();
8086 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8087 return false;
8088 }
8089 if (Data.first && !SupportsNonRectangular) {
8090 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8091 return false;
8092 }
8093 if (Data.first &&
8094 (DepDecl || (PrevDepDecl &&
8095 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8096 if (!DepDecl && PrevDepDecl)
8097 DepDecl = PrevDepDecl;
8098 SmallString<128> Name;
8099 llvm::raw_svector_ostream OS(Name);
8100 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8101 /*Qualified=*/true);
8102 SemaRef.Diag(E->getExprLoc(),
8103 diag::err_omp_invariant_or_linear_dependency)
8104 << OS.str();
8105 return false;
8106 }
8107 if (Data.first) {
8108 DepDecl = VD;
8109 BaseLoopId = Data.first;
8110 }
8111 return Data.first;
8112 }
8113
8114 public:
VisitDeclRefExpr(const DeclRefExpr * E)8115 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8116 const ValueDecl *VD = E->getDecl();
8117 if (isa<VarDecl>(VD))
8118 return checkDecl(E, VD);
8119 return false;
8120 }
VisitMemberExpr(const MemberExpr * E)8121 bool VisitMemberExpr(const MemberExpr *E) {
8122 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8123 const ValueDecl *VD = E->getMemberDecl();
8124 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8125 return checkDecl(E, VD);
8126 }
8127 return false;
8128 }
VisitStmt(const Stmt * S)8129 bool VisitStmt(const Stmt *S) {
8130 bool Res = false;
8131 for (const Stmt *Child : S->children())
8132 Res = (Child && Visit(Child)) || Res;
8133 return Res;
8134 }
LoopCounterRefChecker(Sema & SemaRef,DSAStackTy & Stack,const ValueDecl * CurLCDecl,bool IsInitializer,const ValueDecl * PrevDepDecl=nullptr,bool SupportsNonRectangular=true)8135 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8136 const ValueDecl *CurLCDecl, bool IsInitializer,
8137 const ValueDecl *PrevDepDecl = nullptr,
8138 bool SupportsNonRectangular = true)
8139 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8140 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8141 SupportsNonRectangular(SupportsNonRectangular) {}
getBaseLoopId() const8142 unsigned getBaseLoopId() const {
8143 assert(CurLCDecl && "Expected loop dependency.");
8144 return BaseLoopId;
8145 }
getDepDecl() const8146 const ValueDecl *getDepDecl() const {
8147 assert(CurLCDecl && "Expected loop dependency.");
8148 return DepDecl;
8149 }
8150 };
8151 } // namespace
8152
8153 std::optional<unsigned>
doesDependOnLoopCounter(const Stmt * S,bool IsInitializer)8154 OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8155 bool IsInitializer) {
8156 // Check for the non-rectangular loops.
8157 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8158 DepDecl, SupportsNonRectangular);
8159 if (LoopStmtChecker.Visit(S)) {
8160 DepDecl = LoopStmtChecker.getDepDecl();
8161 return LoopStmtChecker.getBaseLoopId();
8162 }
8163 return std::nullopt;
8164 }
8165
checkAndSetInit(Stmt * S,bool EmitDiags)8166 bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8167 // Check init-expr for canonical loop form and save loop counter
8168 // variable - #Var and its initialization value - #LB.
8169 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8170 // var = lb
8171 // integer-type var = lb
8172 // random-access-iterator-type var = lb
8173 // pointer-type var = lb
8174 //
8175 if (!S) {
8176 if (EmitDiags) {
8177 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8178 }
8179 return true;
8180 }
8181 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8182 if (!ExprTemp->cleanupsHaveSideEffects())
8183 S = ExprTemp->getSubExpr();
8184
8185 InitSrcRange = S->getSourceRange();
8186 if (Expr *E = dyn_cast<Expr>(S))
8187 S = E->IgnoreParens();
8188 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8189 if (BO->getOpcode() == BO_Assign) {
8190 Expr *LHS = BO->getLHS()->IgnoreParens();
8191 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8192 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8193 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8194 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8195 EmitDiags);
8196 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8197 }
8198 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8199 if (ME->isArrow() &&
8200 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8201 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8202 EmitDiags);
8203 }
8204 }
8205 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8206 if (DS->isSingleDecl()) {
8207 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8208 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8209 // Accept non-canonical init form here but emit ext. warning.
8210 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8211 SemaRef.Diag(S->getBeginLoc(),
8212 diag::ext_omp_loop_not_canonical_init)
8213 << S->getSourceRange();
8214 return setLCDeclAndLB(
8215 Var,
8216 buildDeclRefExpr(SemaRef, Var,
8217 Var->getType().getNonReferenceType(),
8218 DS->getBeginLoc()),
8219 Var->getInit(), EmitDiags);
8220 }
8221 }
8222 }
8223 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8224 if (CE->getOperator() == OO_Equal) {
8225 Expr *LHS = CE->getArg(0);
8226 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8227 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8228 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8229 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8230 EmitDiags);
8231 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8232 }
8233 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8234 if (ME->isArrow() &&
8235 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8236 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8237 EmitDiags);
8238 }
8239 }
8240 }
8241
8242 if (dependent() || SemaRef.CurContext->isDependentContext())
8243 return false;
8244 if (EmitDiags) {
8245 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8246 << S->getSourceRange();
8247 }
8248 return true;
8249 }
8250
8251 /// Ignore parenthesizes, implicit casts, copy constructor and return the
8252 /// variable (which may be the loop variable) if possible.
getInitLCDecl(const Expr * E)8253 static const ValueDecl *getInitLCDecl(const Expr *E) {
8254 if (!E)
8255 return nullptr;
8256 E = getExprAsWritten(E);
8257 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8258 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8259 if ((Ctor->isCopyOrMoveConstructor() ||
8260 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8261 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8262 E = CE->getArg(0)->IgnoreParenImpCasts();
8263 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8264 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8265 return getCanonicalDecl(VD);
8266 }
8267 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8268 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8269 return getCanonicalDecl(ME->getMemberDecl());
8270 return nullptr;
8271 }
8272
checkAndSetCond(Expr * S)8273 bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8274 // Check test-expr for canonical form, save upper-bound UB, flags for
8275 // less/greater and for strict/non-strict comparison.
8276 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8277 // var relational-op b
8278 // b relational-op var
8279 //
8280 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8281 if (!S) {
8282 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8283 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8284 return true;
8285 }
8286 Condition = S;
8287 S = getExprAsWritten(S);
8288 SourceLocation CondLoc = S->getBeginLoc();
8289 auto &&CheckAndSetCond =
8290 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8291 const Expr *RHS, SourceRange SR,
8292 SourceLocation OpLoc) -> std::optional<bool> {
8293 if (BinaryOperator::isRelationalOp(Opcode)) {
8294 if (getInitLCDecl(LHS) == LCDecl)
8295 return setUB(const_cast<Expr *>(RHS),
8296 (Opcode == BO_LT || Opcode == BO_LE),
8297 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8298 if (getInitLCDecl(RHS) == LCDecl)
8299 return setUB(const_cast<Expr *>(LHS),
8300 (Opcode == BO_GT || Opcode == BO_GE),
8301 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8302 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8303 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8304 /*LessOp=*/std::nullopt,
8305 /*StrictOp=*/true, SR, OpLoc);
8306 }
8307 return std::nullopt;
8308 };
8309 std::optional<bool> Res;
8310 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8311 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8312 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8313 RBO->getOperatorLoc());
8314 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8315 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8316 BO->getSourceRange(), BO->getOperatorLoc());
8317 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8318 if (CE->getNumArgs() == 2) {
8319 Res = CheckAndSetCond(
8320 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8321 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8322 }
8323 }
8324 if (Res)
8325 return *Res;
8326 if (dependent() || SemaRef.CurContext->isDependentContext())
8327 return false;
8328 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8329 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8330 return true;
8331 }
8332
checkAndSetIncRHS(Expr * RHS)8333 bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8334 // RHS of canonical loop form increment can be:
8335 // var + incr
8336 // incr + var
8337 // var - incr
8338 //
8339 RHS = RHS->IgnoreParenImpCasts();
8340 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8341 if (BO->isAdditiveOp()) {
8342 bool IsAdd = BO->getOpcode() == BO_Add;
8343 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8344 return setStep(BO->getRHS(), !IsAdd);
8345 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8346 return setStep(BO->getLHS(), /*Subtract=*/false);
8347 }
8348 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8349 bool IsAdd = CE->getOperator() == OO_Plus;
8350 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8351 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8352 return setStep(CE->getArg(1), !IsAdd);
8353 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8354 return setStep(CE->getArg(0), /*Subtract=*/false);
8355 }
8356 }
8357 if (dependent() || SemaRef.CurContext->isDependentContext())
8358 return false;
8359 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8360 << RHS->getSourceRange() << LCDecl;
8361 return true;
8362 }
8363
checkAndSetInc(Expr * S)8364 bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8365 // Check incr-expr for canonical loop form and return true if it
8366 // does not conform.
8367 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8368 // ++var
8369 // var++
8370 // --var
8371 // var--
8372 // var += incr
8373 // var -= incr
8374 // var = var + incr
8375 // var = incr + var
8376 // var = var - incr
8377 //
8378 if (!S) {
8379 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8380 return true;
8381 }
8382 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8383 if (!ExprTemp->cleanupsHaveSideEffects())
8384 S = ExprTemp->getSubExpr();
8385
8386 IncrementSrcRange = S->getSourceRange();
8387 S = S->IgnoreParens();
8388 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8389 if (UO->isIncrementDecrementOp() &&
8390 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8391 return setStep(SemaRef
8392 .ActOnIntegerConstant(UO->getBeginLoc(),
8393 (UO->isDecrementOp() ? -1 : 1))
8394 .get(),
8395 /*Subtract=*/false);
8396 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8397 switch (BO->getOpcode()) {
8398 case BO_AddAssign:
8399 case BO_SubAssign:
8400 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8401 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8402 break;
8403 case BO_Assign:
8404 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8405 return checkAndSetIncRHS(BO->getRHS());
8406 break;
8407 default:
8408 break;
8409 }
8410 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8411 switch (CE->getOperator()) {
8412 case OO_PlusPlus:
8413 case OO_MinusMinus:
8414 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8415 return setStep(SemaRef
8416 .ActOnIntegerConstant(
8417 CE->getBeginLoc(),
8418 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8419 .get(),
8420 /*Subtract=*/false);
8421 break;
8422 case OO_PlusEqual:
8423 case OO_MinusEqual:
8424 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8425 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8426 break;
8427 case OO_Equal:
8428 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8429 return checkAndSetIncRHS(CE->getArg(1));
8430 break;
8431 default:
8432 break;
8433 }
8434 }
8435 if (dependent() || SemaRef.CurContext->isDependentContext())
8436 return false;
8437 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8438 << S->getSourceRange() << LCDecl;
8439 return true;
8440 }
8441
8442 static ExprResult
tryBuildCapture(Sema & SemaRef,Expr * Capture,llvm::MapVector<const Expr *,DeclRefExpr * > & Captures)8443 tryBuildCapture(Sema &SemaRef, Expr *Capture,
8444 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8445 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8446 return Capture;
8447 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8448 return SemaRef.PerformImplicitConversion(
8449 Capture->IgnoreImpCasts(), Capture->getType(), Sema::AA_Converting,
8450 /*AllowExplicit=*/true);
8451 auto I = Captures.find(Capture);
8452 if (I != Captures.end())
8453 return buildCapture(SemaRef, Capture, I->second);
8454 DeclRefExpr *Ref = nullptr;
8455 ExprResult Res = buildCapture(SemaRef, Capture, Ref);
8456 Captures[Capture] = Ref;
8457 return Res;
8458 }
8459
8460 /// Calculate number of iterations, transforming to unsigned, if number of
8461 /// iterations may be larger than the original type.
8462 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)8463 calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8464 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8465 bool TestIsStrictOp, bool RoundToStep,
8466 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8467 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures);
8468 if (!NewStep.isUsable())
8469 return nullptr;
8470 llvm::APSInt LRes, SRes;
8471 bool IsLowerConst = false, IsStepConst = false;
8472 if (std::optional<llvm::APSInt> Res =
8473 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8474 LRes = *Res;
8475 IsLowerConst = true;
8476 }
8477 if (std::optional<llvm::APSInt> Res =
8478 Step->getIntegerConstantExpr(SemaRef.Context)) {
8479 SRes = *Res;
8480 IsStepConst = true;
8481 }
8482 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8483 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8484 (TestIsStrictOp && LRes.isStrictlyPositive()));
8485 bool NeedToReorganize = false;
8486 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8487 if (!NoNeedToConvert && IsLowerConst &&
8488 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8489 NoNeedToConvert = true;
8490 if (RoundToStep) {
8491 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8492 ? LRes.getBitWidth()
8493 : SRes.getBitWidth();
8494 LRes = LRes.extend(BW + 1);
8495 LRes.setIsSigned(true);
8496 SRes = SRes.extend(BW + 1);
8497 SRes.setIsSigned(true);
8498 LRes -= SRes;
8499 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8500 LRes = LRes.trunc(BW);
8501 }
8502 if (TestIsStrictOp) {
8503 unsigned BW = LRes.getBitWidth();
8504 LRes = LRes.extend(BW + 1);
8505 LRes.setIsSigned(true);
8506 ++LRes;
8507 NoNeedToConvert =
8508 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8509 // truncate to the original bitwidth.
8510 LRes = LRes.trunc(BW);
8511 }
8512 NeedToReorganize = NoNeedToConvert;
8513 }
8514 llvm::APSInt URes;
8515 bool IsUpperConst = false;
8516 if (std::optional<llvm::APSInt> Res =
8517 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8518 URes = *Res;
8519 IsUpperConst = true;
8520 }
8521 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8522 (!RoundToStep || IsStepConst)) {
8523 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8524 : URes.getBitWidth();
8525 LRes = LRes.extend(BW + 1);
8526 LRes.setIsSigned(true);
8527 URes = URes.extend(BW + 1);
8528 URes.setIsSigned(true);
8529 URes -= LRes;
8530 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8531 NeedToReorganize = NoNeedToConvert;
8532 }
8533 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8534 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8535 // unsigned.
8536 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8537 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8538 QualType LowerTy = Lower->getType();
8539 QualType UpperTy = Upper->getType();
8540 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8541 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8542 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8543 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8544 QualType CastType = SemaRef.Context.getIntTypeForBitwidth(
8545 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8546 Upper =
8547 SemaRef
8548 .PerformImplicitConversion(
8549 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8550 CastType, Sema::AA_Converting)
8551 .get();
8552 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8553 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8554 }
8555 }
8556 if (!Lower || !Upper || NewStep.isInvalid())
8557 return nullptr;
8558
8559 ExprResult Diff;
8560 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8561 // 1]).
8562 if (NeedToReorganize) {
8563 Diff = Lower;
8564
8565 if (RoundToStep) {
8566 // Lower - Step
8567 Diff =
8568 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8569 if (!Diff.isUsable())
8570 return nullptr;
8571 }
8572
8573 // Lower - Step [+ 1]
8574 if (TestIsStrictOp)
8575 Diff = SemaRef.BuildBinOp(
8576 S, DefaultLoc, BO_Add, Diff.get(),
8577 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8578 if (!Diff.isUsable())
8579 return nullptr;
8580
8581 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8582 if (!Diff.isUsable())
8583 return nullptr;
8584
8585 // Upper - (Lower - Step [+ 1]).
8586 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8587 if (!Diff.isUsable())
8588 return nullptr;
8589 } else {
8590 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8591
8592 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8593 // BuildBinOp already emitted error, this one is to point user to upper
8594 // and lower bound, and to tell what is passed to 'operator-'.
8595 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8596 << Upper->getSourceRange() << Lower->getSourceRange();
8597 return nullptr;
8598 }
8599
8600 if (!Diff.isUsable())
8601 return nullptr;
8602
8603 // Upper - Lower [- 1]
8604 if (TestIsStrictOp)
8605 Diff = SemaRef.BuildBinOp(
8606 S, DefaultLoc, BO_Sub, Diff.get(),
8607 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8608 if (!Diff.isUsable())
8609 return nullptr;
8610
8611 if (RoundToStep) {
8612 // Upper - Lower [- 1] + Step
8613 Diff =
8614 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8615 if (!Diff.isUsable())
8616 return nullptr;
8617 }
8618 }
8619
8620 // Parentheses (for dumping/debugging purposes only).
8621 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8622 if (!Diff.isUsable())
8623 return nullptr;
8624
8625 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8626 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8627 if (!Diff.isUsable())
8628 return nullptr;
8629
8630 return Diff.get();
8631 }
8632
8633 /// Build the expression to calculate the number of iterations.
buildNumIterations(Scope * S,ArrayRef<LoopIterationSpace> ResultIterSpaces,bool LimitedType,llvm::MapVector<const Expr *,DeclRefExpr * > & Captures) const8634 Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8635 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8636 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8637 QualType VarType = LCDecl->getType().getNonReferenceType();
8638 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8639 !SemaRef.getLangOpts().CPlusPlus)
8640 return nullptr;
8641 Expr *LBVal = LB;
8642 Expr *UBVal = UB;
8643 // LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8644 // max(LB(MinVal), LB(MaxVal))
8645 if (InitDependOnLC) {
8646 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8647 if (!IS.MinValue || !IS.MaxValue)
8648 return nullptr;
8649 // OuterVar = Min
8650 ExprResult MinValue =
8651 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8652 if (!MinValue.isUsable())
8653 return nullptr;
8654
8655 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8656 IS.CounterVar, MinValue.get());
8657 if (!LBMinVal.isUsable())
8658 return nullptr;
8659 // OuterVar = Min, LBVal
8660 LBMinVal =
8661 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8662 if (!LBMinVal.isUsable())
8663 return nullptr;
8664 // (OuterVar = Min, LBVal)
8665 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8666 if (!LBMinVal.isUsable())
8667 return nullptr;
8668
8669 // OuterVar = Max
8670 ExprResult MaxValue =
8671 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8672 if (!MaxValue.isUsable())
8673 return nullptr;
8674
8675 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8676 IS.CounterVar, MaxValue.get());
8677 if (!LBMaxVal.isUsable())
8678 return nullptr;
8679 // OuterVar = Max, LBVal
8680 LBMaxVal =
8681 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8682 if (!LBMaxVal.isUsable())
8683 return nullptr;
8684 // (OuterVar = Max, LBVal)
8685 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8686 if (!LBMaxVal.isUsable())
8687 return nullptr;
8688
8689 Expr *LBMin = tryBuildCapture(SemaRef, LBMinVal.get(), Captures).get();
8690 Expr *LBMax = tryBuildCapture(SemaRef, LBMaxVal.get(), Captures).get();
8691 if (!LBMin || !LBMax)
8692 return nullptr;
8693 // LB(MinVal) < LB(MaxVal)
8694 ExprResult MinLessMaxRes =
8695 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8696 if (!MinLessMaxRes.isUsable())
8697 return nullptr;
8698 Expr *MinLessMax =
8699 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures).get();
8700 if (!MinLessMax)
8701 return nullptr;
8702 if (*TestIsLessOp) {
8703 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8704 // LB(MaxVal))
8705 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8706 MinLessMax, LBMin, LBMax);
8707 if (!MinLB.isUsable())
8708 return nullptr;
8709 LBVal = MinLB.get();
8710 } else {
8711 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8712 // LB(MaxVal))
8713 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8714 MinLessMax, LBMax, LBMin);
8715 if (!MaxLB.isUsable())
8716 return nullptr;
8717 LBVal = MaxLB.get();
8718 }
8719 }
8720 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8721 // min(UB(MinVal), UB(MaxVal))
8722 if (CondDependOnLC) {
8723 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8724 if (!IS.MinValue || !IS.MaxValue)
8725 return nullptr;
8726 // OuterVar = Min
8727 ExprResult MinValue =
8728 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8729 if (!MinValue.isUsable())
8730 return nullptr;
8731
8732 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8733 IS.CounterVar, MinValue.get());
8734 if (!UBMinVal.isUsable())
8735 return nullptr;
8736 // OuterVar = Min, UBVal
8737 UBMinVal =
8738 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
8739 if (!UBMinVal.isUsable())
8740 return nullptr;
8741 // (OuterVar = Min, UBVal)
8742 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
8743 if (!UBMinVal.isUsable())
8744 return nullptr;
8745
8746 // OuterVar = Max
8747 ExprResult MaxValue =
8748 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8749 if (!MaxValue.isUsable())
8750 return nullptr;
8751
8752 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8753 IS.CounterVar, MaxValue.get());
8754 if (!UBMaxVal.isUsable())
8755 return nullptr;
8756 // OuterVar = Max, UBVal
8757 UBMaxVal =
8758 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
8759 if (!UBMaxVal.isUsable())
8760 return nullptr;
8761 // (OuterVar = Max, UBVal)
8762 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
8763 if (!UBMaxVal.isUsable())
8764 return nullptr;
8765
8766 Expr *UBMin = tryBuildCapture(SemaRef, UBMinVal.get(), Captures).get();
8767 Expr *UBMax = tryBuildCapture(SemaRef, UBMaxVal.get(), Captures).get();
8768 if (!UBMin || !UBMax)
8769 return nullptr;
8770 // UB(MinVal) > UB(MaxVal)
8771 ExprResult MinGreaterMaxRes =
8772 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8773 if (!MinGreaterMaxRes.isUsable())
8774 return nullptr;
8775 Expr *MinGreaterMax =
8776 tryBuildCapture(SemaRef, MinGreaterMaxRes.get(), Captures).get();
8777 if (!MinGreaterMax)
8778 return nullptr;
8779 if (*TestIsLessOp) {
8780 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8781 // UB(MaxVal))
8782 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
8783 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8784 if (!MaxUB.isUsable())
8785 return nullptr;
8786 UBVal = MaxUB.get();
8787 } else {
8788 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
8789 // UB(MaxVal))
8790 ExprResult MinUB = SemaRef.ActOnConditionalOp(
8791 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
8792 if (!MinUB.isUsable())
8793 return nullptr;
8794 UBVal = MinUB.get();
8795 }
8796 }
8797 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
8798 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
8799 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures).get();
8800 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures).get();
8801 if (!Upper || !Lower)
8802 return nullptr;
8803
8804 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8805 Step, VarType, TestIsStrictOp,
8806 /*RoundToStep=*/true, Captures);
8807 if (!Diff.isUsable())
8808 return nullptr;
8809
8810 // OpenMP runtime requires 32-bit or 64-bit loop variables.
8811 QualType Type = Diff.get()->getType();
8812 ASTContext &C = SemaRef.Context;
8813 bool UseVarType = VarType->hasIntegerRepresentation() &&
8814 C.getTypeSize(Type) > C.getTypeSize(VarType);
8815 if (!Type->isIntegerType() || UseVarType) {
8816 unsigned NewSize =
8817 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
8818 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
8819 : Type->hasSignedIntegerRepresentation();
8820 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
8821 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
8822 Diff = SemaRef.PerformImplicitConversion(
8823 Diff.get(), Type, Sema::AA_Converting, /*AllowExplicit=*/true);
8824 if (!Diff.isUsable())
8825 return nullptr;
8826 }
8827 }
8828 if (LimitedType) {
8829 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
8830 if (NewSize != C.getTypeSize(Type)) {
8831 if (NewSize < C.getTypeSize(Type)) {
8832 assert(NewSize == 64 && "incorrect loop var size");
8833 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8834 << InitSrcRange << ConditionSrcRange;
8835 }
8836 QualType NewType = C.getIntTypeForBitwidth(
8837 NewSize, Type->hasSignedIntegerRepresentation() ||
8838 C.getTypeSize(Type) < NewSize);
8839 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
8840 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
8841 Sema::AA_Converting, true);
8842 if (!Diff.isUsable())
8843 return nullptr;
8844 }
8845 }
8846 }
8847
8848 return Diff.get();
8849 }
8850
buildMinMaxValues(Scope * S,llvm::MapVector<const Expr *,DeclRefExpr * > & Captures) const8851 std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
8852 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8853 // Do not build for iterators, they cannot be used in non-rectangular loop
8854 // nests.
8855 if (LCDecl->getType()->isRecordType())
8856 return std::make_pair(nullptr, nullptr);
8857 // If we subtract, the min is in the condition, otherwise the min is in the
8858 // init value.
8859 Expr *MinExpr = nullptr;
8860 Expr *MaxExpr = nullptr;
8861 Expr *LBExpr = *TestIsLessOp ? LB : UB;
8862 Expr *UBExpr = *TestIsLessOp ? UB : LB;
8863 bool LBNonRect =
8864 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
8865 bool UBNonRect =
8866 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
8867 Expr *Lower =
8868 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
8869 Expr *Upper =
8870 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
8871 if (!Upper || !Lower)
8872 return std::make_pair(nullptr, nullptr);
8873
8874 if (*TestIsLessOp)
8875 MinExpr = Lower;
8876 else
8877 MaxExpr = Upper;
8878
8879 // Build minimum/maximum value based on number of iterations.
8880 QualType VarType = LCDecl->getType().getNonReferenceType();
8881
8882 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8883 Step, VarType, TestIsStrictOp,
8884 /*RoundToStep=*/false, Captures);
8885 if (!Diff.isUsable())
8886 return std::make_pair(nullptr, nullptr);
8887
8888 // ((Upper - Lower [- 1]) / Step) * Step
8889 // Parentheses (for dumping/debugging purposes only).
8890 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8891 if (!Diff.isUsable())
8892 return std::make_pair(nullptr, nullptr);
8893
8894 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures);
8895 if (!NewStep.isUsable())
8896 return std::make_pair(nullptr, nullptr);
8897 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
8898 if (!Diff.isUsable())
8899 return std::make_pair(nullptr, nullptr);
8900
8901 // Parentheses (for dumping/debugging purposes only).
8902 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8903 if (!Diff.isUsable())
8904 return std::make_pair(nullptr, nullptr);
8905
8906 // Convert to the ptrdiff_t, if original type is pointer.
8907 if (VarType->isAnyPointerType() &&
8908 !SemaRef.Context.hasSameType(
8909 Diff.get()->getType(),
8910 SemaRef.Context.getUnsignedPointerDiffType())) {
8911 Diff = SemaRef.PerformImplicitConversion(
8912 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
8913 Sema::AA_Converting, /*AllowExplicit=*/true);
8914 }
8915 if (!Diff.isUsable())
8916 return std::make_pair(nullptr, nullptr);
8917
8918 if (*TestIsLessOp) {
8919 // MinExpr = Lower;
8920 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
8921 Diff = SemaRef.BuildBinOp(
8922 S, DefaultLoc, BO_Add,
8923 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
8924 Diff.get());
8925 if (!Diff.isUsable())
8926 return std::make_pair(nullptr, nullptr);
8927 } else {
8928 // MaxExpr = Upper;
8929 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
8930 Diff = SemaRef.BuildBinOp(
8931 S, DefaultLoc, BO_Sub,
8932 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8933 Diff.get());
8934 if (!Diff.isUsable())
8935 return std::make_pair(nullptr, nullptr);
8936 }
8937
8938 // Convert to the original type.
8939 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
8940 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
8941 Sema::AA_Converting,
8942 /*AllowExplicit=*/true);
8943 if (!Diff.isUsable())
8944 return std::make_pair(nullptr, nullptr);
8945
8946 Sema::TentativeAnalysisScope Trap(SemaRef);
8947 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
8948 if (!Diff.isUsable())
8949 return std::make_pair(nullptr, nullptr);
8950
8951 if (*TestIsLessOp)
8952 MaxExpr = Diff.get();
8953 else
8954 MinExpr = Diff.get();
8955
8956 return std::make_pair(MinExpr, MaxExpr);
8957 }
8958
buildFinalCondition(Scope * S) const8959 Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
8960 if (InitDependOnLC || CondDependOnLC)
8961 return Condition;
8962 return nullptr;
8963 }
8964
buildPreCond(Scope * S,Expr * Cond,llvm::MapVector<const Expr *,DeclRefExpr * > & Captures) const8965 Expr *OpenMPIterationSpaceChecker::buildPreCond(
8966 Scope *S, Expr *Cond,
8967 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8968 // Do not build a precondition when the condition/initialization is dependent
8969 // to prevent pessimistic early loop exit.
8970 // TODO: this can be improved by calculating min/max values but not sure that
8971 // it will be very effective.
8972 if (CondDependOnLC || InitDependOnLC)
8973 return SemaRef
8974 .PerformImplicitConversion(
8975 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
8976 SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
8977 /*AllowExplicit=*/true)
8978 .get();
8979
8980 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
8981 Sema::TentativeAnalysisScope Trap(SemaRef);
8982
8983 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
8984 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
8985 if (!NewLB.isUsable() || !NewUB.isUsable())
8986 return nullptr;
8987
8988 ExprResult CondExpr =
8989 SemaRef.BuildBinOp(S, DefaultLoc,
8990 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
8991 : (TestIsStrictOp ? BO_GT : BO_GE),
8992 NewLB.get(), NewUB.get());
8993 if (CondExpr.isUsable()) {
8994 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
8995 SemaRef.Context.BoolTy))
8996 CondExpr = SemaRef.PerformImplicitConversion(
8997 CondExpr.get(), SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
8998 /*AllowExplicit=*/true);
8999 }
9000
9001 // Otherwise use original loop condition and evaluate it in runtime.
9002 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9003 }
9004
9005 /// Build reference expression to the counter be used for codegen.
buildCounterVar(llvm::MapVector<const Expr *,DeclRefExpr * > & Captures,DSAStackTy & DSA) const9006 DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9007 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9008 DSAStackTy &DSA) const {
9009 auto *VD = dyn_cast<VarDecl>(LCDecl);
9010 if (!VD) {
9011 VD = SemaRef.isOpenMPCapturedDecl(LCDecl);
9012 DeclRefExpr *Ref = buildDeclRefExpr(
9013 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
9014 const DSAStackTy::DSAVarData Data =
9015 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
9016 // If the loop control decl is explicitly marked as private, do not mark it
9017 // as captured again.
9018 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
9019 Captures.insert(std::make_pair(LCRef, Ref));
9020 return Ref;
9021 }
9022 return cast<DeclRefExpr>(LCRef);
9023 }
9024
buildPrivateCounterVar() const9025 Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9026 if (LCDecl && !LCDecl->isInvalidDecl()) {
9027 QualType Type = LCDecl->getType().getNonReferenceType();
9028 VarDecl *PrivateVar = buildVarDecl(
9029 SemaRef, DefaultLoc, Type, LCDecl->getName(),
9030 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9031 isa<VarDecl>(LCDecl)
9032 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
9033 : nullptr);
9034 if (PrivateVar->isInvalidDecl())
9035 return nullptr;
9036 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
9037 }
9038 return nullptr;
9039 }
9040
9041 /// Build initialization of the counter to be used for codegen.
buildCounterInit() const9042 Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9043
9044 /// Build step of the counter be used for codegen.
buildCounterStep() const9045 Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9046
buildOrderedLoopData(Scope * S,Expr * Counter,llvm::MapVector<const Expr *,DeclRefExpr * > & Captures,SourceLocation Loc,Expr * Inc,OverloadedOperatorKind OOK)9047 Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9048 Scope *S, Expr *Counter,
9049 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9050 Expr *Inc, OverloadedOperatorKind OOK) {
9051 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
9052 if (!Cnt)
9053 return nullptr;
9054 if (Inc) {
9055 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9056 "Expected only + or - operations for depend clauses.");
9057 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9058 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
9059 if (!Cnt)
9060 return nullptr;
9061 }
9062 QualType VarType = LCDecl->getType().getNonReferenceType();
9063 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9064 !SemaRef.getLangOpts().CPlusPlus)
9065 return nullptr;
9066 // Upper - Lower
9067 Expr *Upper =
9068 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9069 Expr *Lower =
9070 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9071 if (!Upper || !Lower)
9072 return nullptr;
9073
9074 ExprResult Diff = calculateNumIters(
9075 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9076 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9077 if (!Diff.isUsable())
9078 return nullptr;
9079
9080 return Diff.get();
9081 }
9082 } // namespace
9083
ActOnOpenMPLoopInitialization(SourceLocation ForLoc,Stmt * Init)9084 void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {
9085 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9086 assert(Init && "Expected loop in canonical form.");
9087 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9088 if (AssociatedLoops > 0 &&
9089 isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
9090 DSAStack->loopStart();
9091 OpenMPIterationSpaceChecker ISC(*this, /*SupportsNonRectangular=*/true,
9092 *DSAStack, ForLoc);
9093 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9094 if (ValueDecl *D = ISC.getLoopDecl()) {
9095 auto *VD = dyn_cast<VarDecl>(D);
9096 DeclRefExpr *PrivateRef = nullptr;
9097 if (!VD) {
9098 if (VarDecl *Private = isOpenMPCapturedDecl(D)) {
9099 VD = Private;
9100 } else {
9101 PrivateRef = buildCapture(*this, D, ISC.getLoopDeclRefExpr(),
9102 /*WithInit=*/false);
9103 VD = cast<VarDecl>(PrivateRef->getDecl());
9104 }
9105 }
9106 DSAStack->addLoopControlVariable(D, VD);
9107 const Decl *LD = DSAStack->getPossiblyLoopCunter();
9108 if (LD != D->getCanonicalDecl()) {
9109 DSAStack->resetPossibleLoopCounter();
9110 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9111 MarkDeclarationsReferencedInExpr(
9112 buildDeclRefExpr(*this, const_cast<VarDecl *>(Var),
9113 Var->getType().getNonLValueExprType(Context),
9114 ForLoc, /*RefersToCapture=*/true));
9115 }
9116 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9117 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9118 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9119 // associated for-loop of a simd construct with just one associated
9120 // for-loop may be listed in a linear clause with a constant-linear-step
9121 // that is the increment of the associated for-loop. The loop iteration
9122 // variable(s) in the associated for-loop(s) of a for or parallel for
9123 // construct may be listed in a private or lastprivate clause.
9124 DSAStackTy::DSAVarData DVar =
9125 DSAStack->getTopDSA(D, /*FromParent=*/false);
9126 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9127 // is declared in the loop and it is predetermined as a private.
9128 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9129 OpenMPClauseKind PredeterminedCKind =
9130 isOpenMPSimdDirective(DKind)
9131 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9132 : OMPC_private;
9133 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9134 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9135 (LangOpts.OpenMP <= 45 || (DVar.CKind != OMPC_lastprivate &&
9136 DVar.CKind != OMPC_private))) ||
9137 ((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop ||
9138 DKind == OMPD_master_taskloop || DKind == OMPD_masked_taskloop ||
9139 DKind == OMPD_parallel_master_taskloop ||
9140 DKind == OMPD_parallel_masked_taskloop ||
9141 isOpenMPDistributeDirective(DKind)) &&
9142 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9143 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9144 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9145 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9146 << getOpenMPClauseName(DVar.CKind)
9147 << getOpenMPDirectiveName(DKind)
9148 << getOpenMPClauseName(PredeterminedCKind);
9149 if (DVar.RefExpr == nullptr)
9150 DVar.CKind = PredeterminedCKind;
9151 reportOriginalDsa(*this, DSAStack, D, DVar,
9152 /*IsLoopIterVar=*/true);
9153 } else if (LoopDeclRefExpr) {
9154 // Make the loop iteration variable private (for worksharing
9155 // constructs), linear (for simd directives with the only one
9156 // associated loop) or lastprivate (for simd directives with several
9157 // collapsed or ordered loops).
9158 if (DVar.CKind == OMPC_unknown)
9159 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind,
9160 PrivateRef);
9161 }
9162 }
9163 }
9164 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9165 }
9166 }
9167
9168 /// Called on a for stmt to check and extract its iteration space
9169 /// 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,Sema::VarsWithInheritedDSAType & VarsWithImplicitDSA,llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces,llvm::MapVector<const Expr *,DeclRefExpr * > & Captures)9170 static bool checkOpenMPIterationSpace(
9171 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9172 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9173 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9174 Expr *OrderedLoopCountExpr,
9175 Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9176 llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces,
9177 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9178 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9179 // OpenMP [2.9.1, Canonical Loop Form]
9180 // for (init-expr; test-expr; incr-expr) structured-block
9181 // for (range-decl: range-expr) structured-block
9182 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9183 S = CanonLoop->getLoopStmt();
9184 auto *For = dyn_cast_or_null<ForStmt>(S);
9185 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9186 // Ranged for is supported only in OpenMP 5.0.
9187 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9188 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9189 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9190 << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount
9191 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9192 if (TotalNestedLoopCount > 1) {
9193 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9194 SemaRef.Diag(DSA.getConstructLoc(),
9195 diag::note_omp_collapse_ordered_expr)
9196 << 2 << CollapseLoopCountExpr->getSourceRange()
9197 << OrderedLoopCountExpr->getSourceRange();
9198 else if (CollapseLoopCountExpr)
9199 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9200 diag::note_omp_collapse_ordered_expr)
9201 << 0 << CollapseLoopCountExpr->getSourceRange();
9202 else
9203 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9204 diag::note_omp_collapse_ordered_expr)
9205 << 1 << OrderedLoopCountExpr->getSourceRange();
9206 }
9207 return true;
9208 }
9209 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9210 "No loop body.");
9211 // Postpone analysis in dependent contexts for ranged for loops.
9212 if (CXXFor && SemaRef.CurContext->isDependentContext())
9213 return false;
9214
9215 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9216 For ? For->getForLoc() : CXXFor->getForLoc());
9217
9218 // Check init.
9219 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9220 if (ISC.checkAndSetInit(Init))
9221 return true;
9222
9223 bool HasErrors = false;
9224
9225 // Check loop variable's type.
9226 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9227 // OpenMP [2.6, Canonical Loop Form]
9228 // Var is one of the following:
9229 // A variable of signed or unsigned integer type.
9230 // For C++, a variable of a random access iterator type.
9231 // For C, a variable of a pointer type.
9232 QualType VarType = LCDecl->getType().getNonReferenceType();
9233 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9234 !VarType->isPointerType() &&
9235 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9236 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9237 << SemaRef.getLangOpts().CPlusPlus;
9238 HasErrors = true;
9239 }
9240
9241 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9242 // a Construct
9243 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9244 // parallel for construct is (are) private.
9245 // The loop iteration variable in the associated for-loop of a simd
9246 // construct with just one associated for-loop is linear with a
9247 // constant-linear-step that is the increment of the associated for-loop.
9248 // Exclude loop var from the list of variables with implicitly defined data
9249 // sharing attributes.
9250 VarsWithImplicitDSA.erase(LCDecl);
9251
9252 assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
9253
9254 // Check test-expr.
9255 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9256
9257 // Check incr-expr.
9258 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9259 }
9260
9261 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9262 return HasErrors;
9263
9264 // Build the loop's iteration space representation.
9265 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9266 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9267 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9268 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9269 (isOpenMPWorksharingDirective(DKind) ||
9270 isOpenMPGenericLoopDirective(DKind) ||
9271 isOpenMPTaskLoopDirective(DKind) ||
9272 isOpenMPDistributeDirective(DKind) ||
9273 isOpenMPLoopTransformationDirective(DKind)),
9274 Captures);
9275 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9276 ISC.buildCounterVar(Captures, DSA);
9277 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9278 ISC.buildPrivateCounterVar();
9279 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9280 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9281 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9282 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9283 ISC.getConditionSrcRange();
9284 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9285 ISC.getIncrementSrcRange();
9286 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9287 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9288 ISC.isStrictTestOp();
9289 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9290 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9291 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9292 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9293 ISC.buildFinalCondition(DSA.getCurScope());
9294 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9295 ISC.doesInitDependOnLC();
9296 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9297 ISC.doesCondDependOnLC();
9298 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9299 ISC.getLoopDependentIdx();
9300
9301 HasErrors |=
9302 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9303 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9304 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9305 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9306 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9307 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9308 if (!HasErrors && DSA.isOrderedRegion()) {
9309 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9310 if (CurrentNestedLoopCount <
9311 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9312 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9313 CurrentNestedLoopCount,
9314 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9315 DSA.getOrderedRegionParam().second->setLoopCounter(
9316 CurrentNestedLoopCount,
9317 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9318 }
9319 }
9320 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9321 if (CurrentNestedLoopCount >= Pair.first->getNumLoops()) {
9322 // Erroneous case - clause has some problems.
9323 continue;
9324 }
9325 if (Pair.first->getDependencyKind() == OMPC_DEPEND_sink &&
9326 Pair.second.size() <= CurrentNestedLoopCount) {
9327 // Erroneous case - clause has some problems.
9328 Pair.first->setLoopData(CurrentNestedLoopCount, nullptr);
9329 continue;
9330 }
9331 Expr *CntValue;
9332 if (Pair.first->getDependencyKind() == OMPC_DEPEND_source)
9333 CntValue = ISC.buildOrderedLoopData(
9334 DSA.getCurScope(),
9335 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9336 Pair.first->getDependencyLoc());
9337 else
9338 CntValue = ISC.buildOrderedLoopData(
9339 DSA.getCurScope(),
9340 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9341 Pair.first->getDependencyLoc(),
9342 Pair.second[CurrentNestedLoopCount].first,
9343 Pair.second[CurrentNestedLoopCount].second);
9344 Pair.first->setLoopData(CurrentNestedLoopCount, CntValue);
9345 }
9346 }
9347
9348 return HasErrors;
9349 }
9350
9351 /// Build 'VarRef = Start.
9352 static ExprResult
buildCounterInit(Sema & SemaRef,Scope * S,SourceLocation Loc,ExprResult VarRef,ExprResult Start,bool IsNonRectangularLB,llvm::MapVector<const Expr *,DeclRefExpr * > & Captures)9353 buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9354 ExprResult Start, bool IsNonRectangularLB,
9355 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9356 // Build 'VarRef = Start.
9357 ExprResult NewStart = IsNonRectangularLB
9358 ? Start.get()
9359 : tryBuildCapture(SemaRef, Start.get(), Captures);
9360 if (!NewStart.isUsable())
9361 return ExprError();
9362 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9363 VarRef.get()->getType())) {
9364 NewStart = SemaRef.PerformImplicitConversion(
9365 NewStart.get(), VarRef.get()->getType(), Sema::AA_Converting,
9366 /*AllowExplicit=*/true);
9367 if (!NewStart.isUsable())
9368 return ExprError();
9369 }
9370
9371 ExprResult Init =
9372 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9373 return Init;
9374 }
9375
9376 /// 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)9377 static ExprResult buildCounterUpdate(
9378 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9379 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9380 bool IsNonRectangularLB,
9381 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9382 // Add parentheses (for debugging purposes only).
9383 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9384 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9385 !Step.isUsable())
9386 return ExprError();
9387
9388 ExprResult NewStep = Step;
9389 if (Captures)
9390 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9391 if (NewStep.isInvalid())
9392 return ExprError();
9393 ExprResult Update =
9394 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9395 if (!Update.isUsable())
9396 return ExprError();
9397
9398 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9399 // 'VarRef = Start (+|-) Iter * Step'.
9400 if (!Start.isUsable())
9401 return ExprError();
9402 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9403 if (!NewStart.isUsable())
9404 return ExprError();
9405 if (Captures && !IsNonRectangularLB)
9406 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9407 if (NewStart.isInvalid())
9408 return ExprError();
9409
9410 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9411 ExprResult SavedUpdate = Update;
9412 ExprResult UpdateVal;
9413 if (VarRef.get()->getType()->isOverloadableType() ||
9414 NewStart.get()->getType()->isOverloadableType() ||
9415 Update.get()->getType()->isOverloadableType()) {
9416 Sema::TentativeAnalysisScope Trap(SemaRef);
9417
9418 Update =
9419 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9420 if (Update.isUsable()) {
9421 UpdateVal =
9422 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9423 VarRef.get(), SavedUpdate.get());
9424 if (UpdateVal.isUsable()) {
9425 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9426 UpdateVal.get());
9427 }
9428 }
9429 }
9430
9431 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9432 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9433 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9434 NewStart.get(), SavedUpdate.get());
9435 if (!Update.isUsable())
9436 return ExprError();
9437
9438 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9439 VarRef.get()->getType())) {
9440 Update = SemaRef.PerformImplicitConversion(
9441 Update.get(), VarRef.get()->getType(), Sema::AA_Converting, true);
9442 if (!Update.isUsable())
9443 return ExprError();
9444 }
9445
9446 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9447 }
9448 return Update;
9449 }
9450
9451 /// Convert integer expression \a E to make it have at least \a Bits
9452 /// bits.
widenIterationCount(unsigned Bits,Expr * E,Sema & SemaRef)9453 static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9454 if (E == nullptr)
9455 return ExprError();
9456 ASTContext &C = SemaRef.Context;
9457 QualType OldType = E->getType();
9458 unsigned HasBits = C.getTypeSize(OldType);
9459 if (HasBits >= Bits)
9460 return ExprResult(E);
9461 // OK to convert to signed, because new type has more bits than old.
9462 QualType NewType = C.getIntTypeForBitwidth(Bits, /* Signed */ true);
9463 return SemaRef.PerformImplicitConversion(E, NewType, Sema::AA_Converting,
9464 true);
9465 }
9466
9467 /// Check if the given expression \a E is a constant integer that fits
9468 /// into \a Bits bits.
fitsInto(unsigned Bits,bool Signed,const Expr * E,Sema & SemaRef)9469 static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9470 if (E == nullptr)
9471 return false;
9472 if (std::optional<llvm::APSInt> Result =
9473 E->getIntegerConstantExpr(SemaRef.Context))
9474 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9475 return false;
9476 }
9477
9478 /// Build preinits statement for the given declarations.
buildPreInits(ASTContext & Context,MutableArrayRef<Decl * > PreInits)9479 static Stmt *buildPreInits(ASTContext &Context,
9480 MutableArrayRef<Decl *> PreInits) {
9481 if (!PreInits.empty()) {
9482 return new (Context) DeclStmt(
9483 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9484 SourceLocation(), SourceLocation());
9485 }
9486 return nullptr;
9487 }
9488
9489 /// Build preinits statement for the given declarations.
9490 static Stmt *
buildPreInits(ASTContext & Context,const llvm::MapVector<const Expr *,DeclRefExpr * > & Captures)9491 buildPreInits(ASTContext &Context,
9492 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9493 if (!Captures.empty()) {
9494 SmallVector<Decl *, 16> PreInits;
9495 for (const auto &Pair : Captures)
9496 PreInits.push_back(Pair.second->getDecl());
9497 return buildPreInits(Context, PreInits);
9498 }
9499 return nullptr;
9500 }
9501
9502 /// Build postupdate expression for the given list of postupdates expressions.
buildPostUpdate(Sema & S,ArrayRef<Expr * > PostUpdates)9503 static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9504 Expr *PostUpdate = nullptr;
9505 if (!PostUpdates.empty()) {
9506 for (Expr *E : PostUpdates) {
9507 Expr *ConvE = S.BuildCStyleCastExpr(
9508 E->getExprLoc(),
9509 S.Context.getTrivialTypeSourceInfo(S.Context.VoidTy),
9510 E->getExprLoc(), E)
9511 .get();
9512 PostUpdate = PostUpdate
9513 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9514 PostUpdate, ConvE)
9515 .get()
9516 : ConvE;
9517 }
9518 }
9519 return PostUpdate;
9520 }
9521
9522 /// Called on a for stmt to check itself and nested loops (if any).
9523 /// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9524 /// number of collapsed loops otherwise.
9525 static unsigned
checkOpenMPLoop(OpenMPDirectiveKind DKind,Expr * CollapseLoopCountExpr,Expr * OrderedLoopCountExpr,Stmt * AStmt,Sema & SemaRef,DSAStackTy & DSA,Sema::VarsWithInheritedDSAType & VarsWithImplicitDSA,OMPLoopBasedDirective::HelperExprs & Built)9526 checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9527 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9528 DSAStackTy &DSA,
9529 Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9530 OMPLoopBasedDirective::HelperExprs &Built) {
9531 unsigned NestedLoopCount = 1;
9532 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9533 !isOpenMPLoopTransformationDirective(DKind);
9534
9535 if (CollapseLoopCountExpr) {
9536 // Found 'collapse' clause - calculate collapse number.
9537 Expr::EvalResult Result;
9538 if (!CollapseLoopCountExpr->isValueDependent() &&
9539 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9540 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9541 } else {
9542 Built.clear(/*Size=*/1);
9543 return 1;
9544 }
9545 }
9546 unsigned OrderedLoopCount = 1;
9547 if (OrderedLoopCountExpr) {
9548 // Found 'ordered' clause - calculate collapse number.
9549 Expr::EvalResult EVResult;
9550 if (!OrderedLoopCountExpr->isValueDependent() &&
9551 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9552 SemaRef.getASTContext())) {
9553 llvm::APSInt Result = EVResult.Val.getInt();
9554 if (Result.getLimitedValue() < NestedLoopCount) {
9555 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9556 diag::err_omp_wrong_ordered_loop_count)
9557 << OrderedLoopCountExpr->getSourceRange();
9558 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9559 diag::note_collapse_loop_count)
9560 << CollapseLoopCountExpr->getSourceRange();
9561 }
9562 OrderedLoopCount = Result.getLimitedValue();
9563 } else {
9564 Built.clear(/*Size=*/1);
9565 return 1;
9566 }
9567 }
9568 // This is helper routine for loop directives (e.g., 'for', 'simd',
9569 // 'for simd', etc.).
9570 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9571 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9572 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9573 if (!OMPLoopBasedDirective::doForAllLoops(
9574 AStmt->IgnoreContainers(!isOpenMPLoopTransformationDirective(DKind)),
9575 SupportsNonPerfectlyNested, NumLoops,
9576 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9577 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9578 &IterSpaces, &Captures](unsigned Cnt, Stmt *CurStmt) {
9579 if (checkOpenMPIterationSpace(
9580 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9581 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9582 VarsWithImplicitDSA, IterSpaces, Captures))
9583 return true;
9584 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9585 IterSpaces[Cnt].CounterVar) {
9586 // Handle initialization of captured loop iterator variables.
9587 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9588 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9589 Captures[DRE] = DRE;
9590 }
9591 }
9592 return false;
9593 },
9594 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9595 Stmt *DependentPreInits = Transform->getPreInits();
9596 if (!DependentPreInits)
9597 return;
9598 for (Decl *C : cast<DeclStmt>(DependentPreInits)->getDeclGroup()) {
9599 auto *D = cast<VarDecl>(C);
9600 DeclRefExpr *Ref = buildDeclRefExpr(SemaRef, D, D->getType(),
9601 Transform->getBeginLoc());
9602 Captures[Ref] = Ref;
9603 }
9604 }))
9605 return 0;
9606
9607 Built.clear(/* size */ NestedLoopCount);
9608
9609 if (SemaRef.CurContext->isDependentContext())
9610 return NestedLoopCount;
9611
9612 // An example of what is generated for the following code:
9613 //
9614 // #pragma omp simd collapse(2) ordered(2)
9615 // for (i = 0; i < NI; ++i)
9616 // for (k = 0; k < NK; ++k)
9617 // for (j = J0; j < NJ; j+=2) {
9618 // <loop body>
9619 // }
9620 //
9621 // We generate the code below.
9622 // Note: the loop body may be outlined in CodeGen.
9623 // Note: some counters may be C++ classes, operator- is used to find number of
9624 // iterations and operator+= to calculate counter value.
9625 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9626 // or i64 is currently supported).
9627 //
9628 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9629 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9630 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9631 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9632 // // similar updates for vars in clauses (e.g. 'linear')
9633 // <loop body (using local i and j)>
9634 // }
9635 // i = NI; // assign final values of counters
9636 // j = NJ;
9637 //
9638
9639 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9640 // the iteration counts of the collapsed for loops.
9641 // Precondition tests if there is at least one iteration (all conditions are
9642 // true).
9643 auto PreCond = ExprResult(IterSpaces[0].PreCond);
9644 Expr *N0 = IterSpaces[0].NumIterations;
9645 ExprResult LastIteration32 =
9646 widenIterationCount(/*Bits=*/32,
9647 SemaRef
9648 .PerformImplicitConversion(
9649 N0->IgnoreImpCasts(), N0->getType(),
9650 Sema::AA_Converting, /*AllowExplicit=*/true)
9651 .get(),
9652 SemaRef);
9653 ExprResult LastIteration64 = widenIterationCount(
9654 /*Bits=*/64,
9655 SemaRef
9656 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
9657 Sema::AA_Converting,
9658 /*AllowExplicit=*/true)
9659 .get(),
9660 SemaRef);
9661
9662 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
9663 return NestedLoopCount;
9664
9665 ASTContext &C = SemaRef.Context;
9666 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
9667
9668 Scope *CurScope = DSA.getCurScope();
9669 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9670 if (PreCond.isUsable()) {
9671 PreCond =
9672 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
9673 PreCond.get(), IterSpaces[Cnt].PreCond);
9674 }
9675 Expr *N = IterSpaces[Cnt].NumIterations;
9676 SourceLocation Loc = N->getExprLoc();
9677 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
9678 if (LastIteration32.isUsable())
9679 LastIteration32 = SemaRef.BuildBinOp(
9680 CurScope, Loc, BO_Mul, LastIteration32.get(),
9681 SemaRef
9682 .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
9683 Sema::AA_Converting,
9684 /*AllowExplicit=*/true)
9685 .get());
9686 if (LastIteration64.isUsable())
9687 LastIteration64 = SemaRef.BuildBinOp(
9688 CurScope, Loc, BO_Mul, LastIteration64.get(),
9689 SemaRef
9690 .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
9691 Sema::AA_Converting,
9692 /*AllowExplicit=*/true)
9693 .get());
9694 }
9695
9696 // Choose either the 32-bit or 64-bit version.
9697 ExprResult LastIteration = LastIteration64;
9698 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
9699 (LastIteration32.isUsable() &&
9700 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
9701 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9702 fitsInto(
9703 /*Bits=*/32,
9704 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
9705 LastIteration64.get(), SemaRef))))
9706 LastIteration = LastIteration32;
9707 QualType VType = LastIteration.get()->getType();
9708 QualType RealVType = VType;
9709 QualType StrideVType = VType;
9710 if (isOpenMPTaskLoopDirective(DKind)) {
9711 VType =
9712 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9713 StrideVType =
9714 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9715 }
9716
9717 if (!LastIteration.isUsable())
9718 return 0;
9719
9720 // Save the number of iterations.
9721 ExprResult NumIterations = LastIteration;
9722 {
9723 LastIteration = SemaRef.BuildBinOp(
9724 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
9725 LastIteration.get(),
9726 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9727 if (!LastIteration.isUsable())
9728 return 0;
9729 }
9730
9731 // Calculate the last iteration number beforehand instead of doing this on
9732 // each iteration. Do not do this if the number of iterations may be kfold-ed.
9733 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
9734 ExprResult CalcLastIteration;
9735 if (!IsConstant) {
9736 ExprResult SaveRef =
9737 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
9738 LastIteration = SaveRef;
9739
9740 // Prepare SaveRef + 1.
9741 NumIterations = SemaRef.BuildBinOp(
9742 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
9743 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9744 if (!NumIterations.isUsable())
9745 return 0;
9746 }
9747
9748 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
9749
9750 // Build variables passed into runtime, necessary for worksharing directives.
9751 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9752 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
9753 isOpenMPDistributeDirective(DKind) ||
9754 isOpenMPGenericLoopDirective(DKind) ||
9755 isOpenMPLoopTransformationDirective(DKind)) {
9756 // Lower bound variable, initialized with zero.
9757 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
9758 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
9759 SemaRef.AddInitializerToDecl(LBDecl,
9760 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9761 /*DirectInit*/ false);
9762
9763 // Upper bound variable, initialized with last iteration number.
9764 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
9765 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
9766 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
9767 /*DirectInit*/ false);
9768
9769 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
9770 // This will be used to implement clause 'lastprivate'.
9771 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
9772 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
9773 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
9774 SemaRef.AddInitializerToDecl(ILDecl,
9775 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9776 /*DirectInit*/ false);
9777
9778 // Stride variable returned by runtime (we initialize it to 1 by default).
9779 VarDecl *STDecl =
9780 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
9781 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
9782 SemaRef.AddInitializerToDecl(STDecl,
9783 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
9784 /*DirectInit*/ false);
9785
9786 // Build expression: UB = min(UB, LastIteration)
9787 // It is necessary for CodeGen of directives with static scheduling.
9788 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
9789 UB.get(), LastIteration.get());
9790 ExprResult CondOp = SemaRef.ActOnConditionalOp(
9791 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
9792 LastIteration.get(), UB.get());
9793 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
9794 CondOp.get());
9795 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false);
9796
9797 // If we have a combined directive that combines 'distribute', 'for' or
9798 // 'simd' we need to be able to access the bounds of the schedule of the
9799 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
9800 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
9801 if (isOpenMPLoopBoundSharingDirective(DKind)) {
9802 // Lower bound variable, initialized with zero.
9803 VarDecl *CombLBDecl =
9804 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
9805 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
9806 SemaRef.AddInitializerToDecl(
9807 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9808 /*DirectInit*/ false);
9809
9810 // Upper bound variable, initialized with last iteration number.
9811 VarDecl *CombUBDecl =
9812 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
9813 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
9814 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
9815 /*DirectInit*/ false);
9816
9817 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
9818 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
9819 ExprResult CombCondOp =
9820 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
9821 LastIteration.get(), CombUB.get());
9822 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
9823 CombCondOp.get());
9824 CombEUB =
9825 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false);
9826
9827 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
9828 // We expect to have at least 2 more parameters than the 'parallel'
9829 // directive does - the lower and upper bounds of the previous schedule.
9830 assert(CD->getNumParams() >= 4 &&
9831 "Unexpected number of parameters in loop combined directive");
9832
9833 // Set the proper type for the bounds given what we learned from the
9834 // enclosed loops.
9835 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
9836 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
9837
9838 // Previous lower and upper bounds are obtained from the region
9839 // parameters.
9840 PrevLB =
9841 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
9842 PrevUB =
9843 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
9844 }
9845 }
9846
9847 // Build the iteration variable and its initialization before loop.
9848 ExprResult IV;
9849 ExprResult Init, CombInit;
9850 {
9851 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
9852 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
9853 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
9854 isOpenMPGenericLoopDirective(DKind) ||
9855 isOpenMPTaskLoopDirective(DKind) ||
9856 isOpenMPDistributeDirective(DKind) ||
9857 isOpenMPLoopTransformationDirective(DKind))
9858 ? LB.get()
9859 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
9860 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
9861 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false);
9862
9863 if (isOpenMPLoopBoundSharingDirective(DKind)) {
9864 Expr *CombRHS =
9865 (isOpenMPWorksharingDirective(DKind) ||
9866 isOpenMPGenericLoopDirective(DKind) ||
9867 isOpenMPTaskLoopDirective(DKind) ||
9868 isOpenMPDistributeDirective(DKind))
9869 ? CombLB.get()
9870 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
9871 CombInit =
9872 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
9873 CombInit =
9874 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false);
9875 }
9876 }
9877
9878 bool UseStrictCompare =
9879 RealVType->hasUnsignedIntegerRepresentation() &&
9880 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
9881 return LIS.IsStrictCompare;
9882 });
9883 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
9884 // unsigned IV)) for worksharing loops.
9885 SourceLocation CondLoc = AStmt->getBeginLoc();
9886 Expr *BoundUB = UB.get();
9887 if (UseStrictCompare) {
9888 BoundUB =
9889 SemaRef
9890 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
9891 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
9892 .get();
9893 BoundUB =
9894 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue*/ false).get();
9895 }
9896 ExprResult Cond =
9897 (isOpenMPWorksharingDirective(DKind) ||
9898 isOpenMPGenericLoopDirective(DKind) ||
9899 isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind) ||
9900 isOpenMPLoopTransformationDirective(DKind))
9901 ? SemaRef.BuildBinOp(CurScope, CondLoc,
9902 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
9903 BoundUB)
9904 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
9905 NumIterations.get());
9906 ExprResult CombDistCond;
9907 if (isOpenMPLoopBoundSharingDirective(DKind)) {
9908 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
9909 NumIterations.get());
9910 }
9911
9912 ExprResult CombCond;
9913 if (isOpenMPLoopBoundSharingDirective(DKind)) {
9914 Expr *BoundCombUB = CombUB.get();
9915 if (UseStrictCompare) {
9916 BoundCombUB =
9917 SemaRef
9918 .BuildBinOp(
9919 CurScope, CondLoc, BO_Add, BoundCombUB,
9920 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
9921 .get();
9922 BoundCombUB =
9923 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue*/ false)
9924 .get();
9925 }
9926 CombCond =
9927 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
9928 IV.get(), BoundCombUB);
9929 }
9930 // Loop increment (IV = IV + 1)
9931 SourceLocation IncLoc = AStmt->getBeginLoc();
9932 ExprResult Inc =
9933 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
9934 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
9935 if (!Inc.isUsable())
9936 return 0;
9937 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
9938 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false);
9939 if (!Inc.isUsable())
9940 return 0;
9941
9942 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
9943 // Used for directives with static scheduling.
9944 // In combined construct, add combined version that use CombLB and CombUB
9945 // base variables for the update
9946 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
9947 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
9948 isOpenMPGenericLoopDirective(DKind) ||
9949 isOpenMPDistributeDirective(DKind) ||
9950 isOpenMPLoopTransformationDirective(DKind)) {
9951 // LB + ST
9952 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
9953 if (!NextLB.isUsable())
9954 return 0;
9955 // LB = LB + ST
9956 NextLB =
9957 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
9958 NextLB =
9959 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false);
9960 if (!NextLB.isUsable())
9961 return 0;
9962 // UB + ST
9963 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
9964 if (!NextUB.isUsable())
9965 return 0;
9966 // UB = UB + ST
9967 NextUB =
9968 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
9969 NextUB =
9970 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false);
9971 if (!NextUB.isUsable())
9972 return 0;
9973 if (isOpenMPLoopBoundSharingDirective(DKind)) {
9974 CombNextLB =
9975 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
9976 if (!NextLB.isUsable())
9977 return 0;
9978 // LB = LB + ST
9979 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
9980 CombNextLB.get());
9981 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
9982 /*DiscardedValue*/ false);
9983 if (!CombNextLB.isUsable())
9984 return 0;
9985 // UB + ST
9986 CombNextUB =
9987 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
9988 if (!CombNextUB.isUsable())
9989 return 0;
9990 // UB = UB + ST
9991 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
9992 CombNextUB.get());
9993 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
9994 /*DiscardedValue*/ false);
9995 if (!CombNextUB.isUsable())
9996 return 0;
9997 }
9998 }
9999
10000 // Create increment expression for distribute loop when combined in a same
10001 // directive with for as IV = IV + ST; ensure upper bound expression based
10002 // on PrevUB instead of NumIterations - used to implement 'for' when found
10003 // in combination with 'distribute', like in 'distribute parallel for'
10004 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10005 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10006 if (isOpenMPLoopBoundSharingDirective(DKind)) {
10007 DistCond = SemaRef.BuildBinOp(
10008 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10009 assert(DistCond.isUsable() && "distribute cond expr was not built");
10010
10011 DistInc =
10012 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10013 assert(DistInc.isUsable() && "distribute inc expr was not built");
10014 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10015 DistInc.get());
10016 DistInc =
10017 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false);
10018 assert(DistInc.isUsable() && "distribute inc expr was not built");
10019
10020 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10021 // construct
10022 ExprResult NewPrevUB = PrevUB;
10023 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10024 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10025 PrevUB.get()->getType())) {
10026 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10027 DistEUBLoc,
10028 SemaRef.Context.getTrivialTypeSourceInfo(UB.get()->getType()),
10029 DistEUBLoc, NewPrevUB.get());
10030 if (!NewPrevUB.isUsable())
10031 return 0;
10032 }
10033 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10034 UB.get(), NewPrevUB.get());
10035 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10036 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10037 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10038 CondOp.get());
10039 PrevEUB =
10040 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false);
10041
10042 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10043 // parallel for is in combination with a distribute directive with
10044 // schedule(static, 1)
10045 Expr *BoundPrevUB = PrevUB.get();
10046 if (UseStrictCompare) {
10047 BoundPrevUB =
10048 SemaRef
10049 .BuildBinOp(
10050 CurScope, CondLoc, BO_Add, BoundPrevUB,
10051 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10052 .get();
10053 BoundPrevUB =
10054 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue*/ false)
10055 .get();
10056 }
10057 ParForInDistCond =
10058 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10059 IV.get(), BoundPrevUB);
10060 }
10061
10062 // Build updates and final values of the loop counters.
10063 bool HasErrors = false;
10064 Built.Counters.resize(NestedLoopCount);
10065 Built.Inits.resize(NestedLoopCount);
10066 Built.Updates.resize(NestedLoopCount);
10067 Built.Finals.resize(NestedLoopCount);
10068 Built.DependentCounters.resize(NestedLoopCount);
10069 Built.DependentInits.resize(NestedLoopCount);
10070 Built.FinalsConditions.resize(NestedLoopCount);
10071 {
10072 // We implement the following algorithm for obtaining the
10073 // original loop iteration variable values based on the
10074 // value of the collapsed loop iteration variable IV.
10075 //
10076 // Let n+1 be the number of collapsed loops in the nest.
10077 // Iteration variables (I0, I1, .... In)
10078 // Iteration counts (N0, N1, ... Nn)
10079 //
10080 // Acc = IV;
10081 //
10082 // To compute Ik for loop k, 0 <= k <= n, generate:
10083 // Prod = N(k+1) * N(k+2) * ... * Nn;
10084 // Ik = Acc / Prod;
10085 // Acc -= Ik * Prod;
10086 //
10087 ExprResult Acc = IV;
10088 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10089 LoopIterationSpace &IS = IterSpaces[Cnt];
10090 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10091 ExprResult Iter;
10092
10093 // Compute prod
10094 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10095 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10096 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10097 IterSpaces[K].NumIterations);
10098
10099 // Iter = Acc / Prod
10100 // If there is at least one more inner loop to avoid
10101 // multiplication by 1.
10102 if (Cnt + 1 < NestedLoopCount)
10103 Iter =
10104 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10105 else
10106 Iter = Acc;
10107 if (!Iter.isUsable()) {
10108 HasErrors = true;
10109 break;
10110 }
10111
10112 // Update Acc:
10113 // Acc -= Iter * Prod
10114 // Check if there is at least one more inner loop to avoid
10115 // multiplication by 1.
10116 if (Cnt + 1 < NestedLoopCount)
10117 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10118 Prod.get());
10119 else
10120 Prod = Iter;
10121 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10122
10123 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10124 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10125 DeclRefExpr *CounterVar = buildDeclRefExpr(
10126 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10127 /*RefersToCapture=*/true);
10128 ExprResult Init =
10129 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10130 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10131 if (!Init.isUsable()) {
10132 HasErrors = true;
10133 break;
10134 }
10135 ExprResult Update = buildCounterUpdate(
10136 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10137 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10138 if (!Update.isUsable()) {
10139 HasErrors = true;
10140 break;
10141 }
10142
10143 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10144 ExprResult Final =
10145 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10146 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10147 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10148 if (!Final.isUsable()) {
10149 HasErrors = true;
10150 break;
10151 }
10152
10153 if (!Update.isUsable() || !Final.isUsable()) {
10154 HasErrors = true;
10155 break;
10156 }
10157 // Save results
10158 Built.Counters[Cnt] = IS.CounterVar;
10159 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10160 Built.Inits[Cnt] = Init.get();
10161 Built.Updates[Cnt] = Update.get();
10162 Built.Finals[Cnt] = Final.get();
10163 Built.DependentCounters[Cnt] = nullptr;
10164 Built.DependentInits[Cnt] = nullptr;
10165 Built.FinalsConditions[Cnt] = nullptr;
10166 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10167 Built.DependentCounters[Cnt] =
10168 Built.Counters[NestedLoopCount - 1 - IS.LoopDependentIdx];
10169 Built.DependentInits[Cnt] =
10170 Built.Inits[NestedLoopCount - 1 - IS.LoopDependentIdx];
10171 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10172 }
10173 }
10174 }
10175
10176 if (HasErrors)
10177 return 0;
10178
10179 // Save results
10180 Built.IterationVarRef = IV.get();
10181 Built.LastIteration = LastIteration.get();
10182 Built.NumIterations = NumIterations.get();
10183 Built.CalcLastIteration = SemaRef
10184 .ActOnFinishFullExpr(CalcLastIteration.get(),
10185 /*DiscardedValue=*/false)
10186 .get();
10187 Built.PreCond = PreCond.get();
10188 Built.PreInits = buildPreInits(C, Captures);
10189 Built.Cond = Cond.get();
10190 Built.Init = Init.get();
10191 Built.Inc = Inc.get();
10192 Built.LB = LB.get();
10193 Built.UB = UB.get();
10194 Built.IL = IL.get();
10195 Built.ST = ST.get();
10196 Built.EUB = EUB.get();
10197 Built.NLB = NextLB.get();
10198 Built.NUB = NextUB.get();
10199 Built.PrevLB = PrevLB.get();
10200 Built.PrevUB = PrevUB.get();
10201 Built.DistInc = DistInc.get();
10202 Built.PrevEUB = PrevEUB.get();
10203 Built.DistCombinedFields.LB = CombLB.get();
10204 Built.DistCombinedFields.UB = CombUB.get();
10205 Built.DistCombinedFields.EUB = CombEUB.get();
10206 Built.DistCombinedFields.Init = CombInit.get();
10207 Built.DistCombinedFields.Cond = CombCond.get();
10208 Built.DistCombinedFields.NLB = CombNextLB.get();
10209 Built.DistCombinedFields.NUB = CombNextUB.get();
10210 Built.DistCombinedFields.DistCond = CombDistCond.get();
10211 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10212
10213 return NestedLoopCount;
10214 }
10215
getCollapseNumberExpr(ArrayRef<OMPClause * > Clauses)10216 static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {
10217 auto CollapseClauses =
10218 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10219 if (CollapseClauses.begin() != CollapseClauses.end())
10220 return (*CollapseClauses.begin())->getNumForLoops();
10221 return nullptr;
10222 }
10223
getOrderedNumberExpr(ArrayRef<OMPClause * > Clauses)10224 static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) {
10225 auto OrderedClauses =
10226 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10227 if (OrderedClauses.begin() != OrderedClauses.end())
10228 return (*OrderedClauses.begin())->getNumForLoops();
10229 return nullptr;
10230 }
10231
checkSimdlenSafelenSpecified(Sema & S,const ArrayRef<OMPClause * > Clauses)10232 static bool checkSimdlenSafelenSpecified(Sema &S,
10233 const ArrayRef<OMPClause *> Clauses) {
10234 const OMPSafelenClause *Safelen = nullptr;
10235 const OMPSimdlenClause *Simdlen = nullptr;
10236
10237 for (const OMPClause *Clause : Clauses) {
10238 if (Clause->getClauseKind() == OMPC_safelen)
10239 Safelen = cast<OMPSafelenClause>(Clause);
10240 else if (Clause->getClauseKind() == OMPC_simdlen)
10241 Simdlen = cast<OMPSimdlenClause>(Clause);
10242 if (Safelen && Simdlen)
10243 break;
10244 }
10245
10246 if (Simdlen && Safelen) {
10247 const Expr *SimdlenLength = Simdlen->getSimdlen();
10248 const Expr *SafelenLength = Safelen->getSafelen();
10249 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10250 SimdlenLength->isInstantiationDependent() ||
10251 SimdlenLength->containsUnexpandedParameterPack())
10252 return false;
10253 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10254 SafelenLength->isInstantiationDependent() ||
10255 SafelenLength->containsUnexpandedParameterPack())
10256 return false;
10257 Expr::EvalResult SimdlenResult, SafelenResult;
10258 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10259 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10260 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10261 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10262 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10263 // If both simdlen and safelen clauses are specified, the value of the
10264 // simdlen parameter must be less than or equal to the value of the safelen
10265 // parameter.
10266 if (SimdlenRes > SafelenRes) {
10267 S.Diag(SimdlenLength->getExprLoc(),
10268 diag::err_omp_wrong_simdlen_safelen_values)
10269 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10270 return true;
10271 }
10272 }
10273 return false;
10274 }
10275
10276 StmtResult
ActOnOpenMPSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10277 Sema::ActOnOpenMPSimdDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
10278 SourceLocation StartLoc, SourceLocation EndLoc,
10279 VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10280 if (!AStmt)
10281 return StmtError();
10282
10283 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10284 OMPLoopBasedDirective::HelperExprs B;
10285 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10286 // define the nested loops number.
10287 unsigned NestedLoopCount = checkOpenMPLoop(
10288 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10289 AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
10290 if (NestedLoopCount == 0)
10291 return StmtError();
10292
10293 assert((CurContext->isDependentContext() || B.builtAll()) &&
10294 "omp simd loop exprs were not built");
10295
10296 if (!CurContext->isDependentContext()) {
10297 // Finalize the clauses that need pre-built expressions for CodeGen.
10298 for (OMPClause *C : Clauses) {
10299 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10300 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10301 B.NumIterations, *this, CurScope,
10302 DSAStack))
10303 return StmtError();
10304 }
10305 }
10306
10307 if (checkSimdlenSafelenSpecified(*this, Clauses))
10308 return StmtError();
10309
10310 setFunctionHasBranchProtectedScope();
10311 return OMPSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
10312 Clauses, AStmt, B);
10313 }
10314
10315 StmtResult
ActOnOpenMPForDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10316 Sema::ActOnOpenMPForDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
10317 SourceLocation StartLoc, SourceLocation EndLoc,
10318 VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10319 if (!AStmt)
10320 return StmtError();
10321
10322 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10323 OMPLoopBasedDirective::HelperExprs B;
10324 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10325 // define the nested loops number.
10326 unsigned NestedLoopCount = checkOpenMPLoop(
10327 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10328 AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
10329 if (NestedLoopCount == 0)
10330 return StmtError();
10331
10332 assert((CurContext->isDependentContext() || B.builtAll()) &&
10333 "omp for loop exprs were not built");
10334
10335 if (!CurContext->isDependentContext()) {
10336 // Finalize the clauses that need pre-built expressions for CodeGen.
10337 for (OMPClause *C : Clauses) {
10338 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10339 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10340 B.NumIterations, *this, CurScope,
10341 DSAStack))
10342 return StmtError();
10343 }
10344 }
10345
10346 setFunctionHasBranchProtectedScope();
10347 return OMPForDirective::Create(
10348 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10349 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10350 }
10351
ActOnOpenMPForSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10352 StmtResult Sema::ActOnOpenMPForSimdDirective(
10353 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10354 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10355 if (!AStmt)
10356 return StmtError();
10357
10358 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10359 OMPLoopBasedDirective::HelperExprs B;
10360 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10361 // define the nested loops number.
10362 unsigned NestedLoopCount =
10363 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10364 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
10365 VarsWithImplicitDSA, B);
10366 if (NestedLoopCount == 0)
10367 return StmtError();
10368
10369 assert((CurContext->isDependentContext() || B.builtAll()) &&
10370 "omp for simd loop exprs were not built");
10371
10372 if (!CurContext->isDependentContext()) {
10373 // Finalize the clauses that need pre-built expressions for CodeGen.
10374 for (OMPClause *C : Clauses) {
10375 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10376 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10377 B.NumIterations, *this, CurScope,
10378 DSAStack))
10379 return StmtError();
10380 }
10381 }
10382
10383 if (checkSimdlenSafelenSpecified(*this, Clauses))
10384 return StmtError();
10385
10386 setFunctionHasBranchProtectedScope();
10387 return OMPForSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
10388 Clauses, AStmt, B);
10389 }
10390
ActOnOpenMPSectionsDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10391 StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
10392 Stmt *AStmt,
10393 SourceLocation StartLoc,
10394 SourceLocation EndLoc) {
10395 if (!AStmt)
10396 return StmtError();
10397
10398 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10399 auto BaseStmt = AStmt;
10400 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10401 BaseStmt = CS->getCapturedStmt();
10402 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10403 auto S = C->children();
10404 if (S.begin() == S.end())
10405 return StmtError();
10406 // All associated statements must be '#pragma omp section' except for
10407 // the first one.
10408 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10409 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10410 if (SectionStmt)
10411 Diag(SectionStmt->getBeginLoc(),
10412 diag::err_omp_sections_substmt_not_section);
10413 return StmtError();
10414 }
10415 cast<OMPSectionDirective>(SectionStmt)
10416 ->setHasCancel(DSAStack->isCancelRegion());
10417 }
10418 } else {
10419 Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt);
10420 return StmtError();
10421 }
10422
10423 setFunctionHasBranchProtectedScope();
10424
10425 return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
10426 DSAStack->getTaskgroupReductionRef(),
10427 DSAStack->isCancelRegion());
10428 }
10429
ActOnOpenMPSectionDirective(Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10430 StmtResult Sema::ActOnOpenMPSectionDirective(Stmt *AStmt,
10431 SourceLocation StartLoc,
10432 SourceLocation EndLoc) {
10433 if (!AStmt)
10434 return StmtError();
10435
10436 setFunctionHasBranchProtectedScope();
10437 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10438
10439 return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt,
10440 DSAStack->isCancelRegion());
10441 }
10442
getDirectCallExpr(Expr * E)10443 static Expr *getDirectCallExpr(Expr *E) {
10444 E = E->IgnoreParenCasts()->IgnoreImplicit();
10445 if (auto *CE = dyn_cast<CallExpr>(E))
10446 if (CE->getDirectCallee())
10447 return E;
10448 return nullptr;
10449 }
10450
ActOnOpenMPDispatchDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10451 StmtResult Sema::ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses,
10452 Stmt *AStmt,
10453 SourceLocation StartLoc,
10454 SourceLocation EndLoc) {
10455 if (!AStmt)
10456 return StmtError();
10457
10458 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10459
10460 // 5.1 OpenMP
10461 // expression-stmt : an expression statement with one of the following forms:
10462 // expression = target-call ( [expression-list] );
10463 // target-call ( [expression-list] );
10464
10465 SourceLocation TargetCallLoc;
10466
10467 if (!CurContext->isDependentContext()) {
10468 Expr *TargetCall = nullptr;
10469
10470 auto *E = dyn_cast<Expr>(S);
10471 if (!E) {
10472 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10473 return StmtError();
10474 }
10475
10476 E = E->IgnoreParenCasts()->IgnoreImplicit();
10477
10478 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10479 if (BO->getOpcode() == BO_Assign)
10480 TargetCall = getDirectCallExpr(BO->getRHS());
10481 } else {
10482 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10483 if (COCE->getOperator() == OO_Equal)
10484 TargetCall = getDirectCallExpr(COCE->getArg(1));
10485 if (!TargetCall)
10486 TargetCall = getDirectCallExpr(E);
10487 }
10488 if (!TargetCall) {
10489 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10490 return StmtError();
10491 }
10492 TargetCallLoc = TargetCall->getExprLoc();
10493 }
10494
10495 setFunctionHasBranchProtectedScope();
10496
10497 return OMPDispatchDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
10498 TargetCallLoc);
10499 }
10500
checkGenericLoopLastprivate(Sema & S,ArrayRef<OMPClause * > Clauses,OpenMPDirectiveKind K,DSAStackTy * Stack)10501 static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses,
10502 OpenMPDirectiveKind K,
10503 DSAStackTy *Stack) {
10504 bool ErrorFound = false;
10505 for (OMPClause *C : Clauses) {
10506 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10507 for (Expr *RefExpr : LPC->varlists()) {
10508 SourceLocation ELoc;
10509 SourceRange ERange;
10510 Expr *SimpleRefExpr = RefExpr;
10511 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10512 if (ValueDecl *D = Res.first) {
10513 auto &&Info = Stack->isLoopControlVariable(D);
10514 if (!Info.first) {
10515 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10516 << getOpenMPDirectiveName(K);
10517 ErrorFound = true;
10518 }
10519 }
10520 }
10521 }
10522 }
10523 return ErrorFound;
10524 }
10525
ActOnOpenMPGenericLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10526 StmtResult Sema::ActOnOpenMPGenericLoopDirective(
10527 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10528 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10529 if (!AStmt)
10530 return StmtError();
10531
10532 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10533 // A list item may not appear in a lastprivate clause unless it is the
10534 // loop iteration variable of a loop that is associated with the construct.
10535 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_loop, DSAStack))
10536 return StmtError();
10537
10538 auto *CS = cast<CapturedStmt>(AStmt);
10539 // 1.2.2 OpenMP Language Terminology
10540 // Structured block - An executable statement with a single entry at the
10541 // top and a single exit at the bottom.
10542 // The point of exit cannot be a branch out of the structured block.
10543 // longjmp() and throw() must not violate the entry/exit criteria.
10544 CS->getCapturedDecl()->setNothrow();
10545
10546 OMPLoopDirective::HelperExprs B;
10547 // In presence of clause 'collapse', it will define the nested loops number.
10548 unsigned NestedLoopCount = checkOpenMPLoop(
10549 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10550 AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
10551 if (NestedLoopCount == 0)
10552 return StmtError();
10553
10554 assert((CurContext->isDependentContext() || B.builtAll()) &&
10555 "omp loop exprs were not built");
10556
10557 setFunctionHasBranchProtectedScope();
10558 return OMPGenericLoopDirective::Create(Context, StartLoc, EndLoc,
10559 NestedLoopCount, Clauses, AStmt, B);
10560 }
10561
ActOnOpenMPTeamsGenericLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10562 StmtResult Sema::ActOnOpenMPTeamsGenericLoopDirective(
10563 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10564 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10565 if (!AStmt)
10566 return StmtError();
10567
10568 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10569 // A list item may not appear in a lastprivate clause unless it is the
10570 // loop iteration variable of a loop that is associated with the construct.
10571 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_teams_loop, DSAStack))
10572 return StmtError();
10573
10574 auto *CS = cast<CapturedStmt>(AStmt);
10575 // 1.2.2 OpenMP Language Terminology
10576 // Structured block - An executable statement with a single entry at the
10577 // top and a single exit at the bottom.
10578 // The point of exit cannot be a branch out of the structured block.
10579 // longjmp() and throw() must not violate the entry/exit criteria.
10580 CS->getCapturedDecl()->setNothrow();
10581 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_loop);
10582 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10583 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10584 // 1.2.2 OpenMP Language Terminology
10585 // Structured block - An executable statement with a single entry at the
10586 // top and a single exit at the bottom.
10587 // The point of exit cannot be a branch out of the structured block.
10588 // longjmp() and throw() must not violate the entry/exit criteria.
10589 CS->getCapturedDecl()->setNothrow();
10590 }
10591
10592 OMPLoopDirective::HelperExprs B;
10593 // In presence of clause 'collapse', it will define the nested loops number.
10594 unsigned NestedLoopCount =
10595 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10596 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10597 VarsWithImplicitDSA, B);
10598 if (NestedLoopCount == 0)
10599 return StmtError();
10600
10601 assert((CurContext->isDependentContext() || B.builtAll()) &&
10602 "omp loop exprs were not built");
10603
10604 setFunctionHasBranchProtectedScope();
10605 DSAStack->setParentTeamsRegionLoc(StartLoc);
10606
10607 return OMPTeamsGenericLoopDirective::Create(
10608 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10609 }
10610
ActOnOpenMPTargetTeamsGenericLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10611 StmtResult Sema::ActOnOpenMPTargetTeamsGenericLoopDirective(
10612 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10613 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10614 if (!AStmt)
10615 return StmtError();
10616
10617 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10618 // A list item may not appear in a lastprivate clause unless it is the
10619 // loop iteration variable of a loop that is associated with the construct.
10620 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_target_teams_loop,
10621 DSAStack))
10622 return StmtError();
10623
10624 auto *CS = cast<CapturedStmt>(AStmt);
10625 // 1.2.2 OpenMP Language Terminology
10626 // Structured block - An executable statement with a single entry at the
10627 // top and a single exit at the bottom.
10628 // The point of exit cannot be a branch out of the structured block.
10629 // longjmp() and throw() must not violate the entry/exit criteria.
10630 CS->getCapturedDecl()->setNothrow();
10631 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams_loop);
10632 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10633 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10634 // 1.2.2 OpenMP Language Terminology
10635 // Structured block - An executable statement with a single entry at the
10636 // top and a single exit at the bottom.
10637 // The point of exit cannot be a branch out of the structured block.
10638 // longjmp() and throw() must not violate the entry/exit criteria.
10639 CS->getCapturedDecl()->setNothrow();
10640 }
10641
10642 OMPLoopDirective::HelperExprs B;
10643 // In presence of clause 'collapse', it will define the nested loops number.
10644 unsigned NestedLoopCount =
10645 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10646 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10647 VarsWithImplicitDSA, B);
10648 if (NestedLoopCount == 0)
10649 return StmtError();
10650
10651 assert((CurContext->isDependentContext() || B.builtAll()) &&
10652 "omp loop exprs were not built");
10653
10654 setFunctionHasBranchProtectedScope();
10655
10656 return OMPTargetTeamsGenericLoopDirective::Create(
10657 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10658 }
10659
ActOnOpenMPParallelGenericLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10660 StmtResult Sema::ActOnOpenMPParallelGenericLoopDirective(
10661 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10662 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10663 if (!AStmt)
10664 return StmtError();
10665
10666 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10667 // A list item may not appear in a lastprivate clause unless it is the
10668 // loop iteration variable of a loop that is associated with the construct.
10669 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_parallel_loop, DSAStack))
10670 return StmtError();
10671
10672 auto *CS = cast<CapturedStmt>(AStmt);
10673 // 1.2.2 OpenMP Language Terminology
10674 // Structured block - An executable statement with a single entry at the
10675 // top and a single exit at the bottom.
10676 // The point of exit cannot be a branch out of the structured block.
10677 // longjmp() and throw() must not violate the entry/exit criteria.
10678 CS->getCapturedDecl()->setNothrow();
10679 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_parallel_loop);
10680 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10681 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10682 // 1.2.2 OpenMP Language Terminology
10683 // Structured block - An executable statement with a single entry at the
10684 // top and a single exit at the bottom.
10685 // The point of exit cannot be a branch out of the structured block.
10686 // longjmp() and throw() must not violate the entry/exit criteria.
10687 CS->getCapturedDecl()->setNothrow();
10688 }
10689
10690 OMPLoopDirective::HelperExprs B;
10691 // In presence of clause 'collapse', it will define the nested loops number.
10692 unsigned NestedLoopCount =
10693 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
10694 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10695 VarsWithImplicitDSA, B);
10696 if (NestedLoopCount == 0)
10697 return StmtError();
10698
10699 assert((CurContext->isDependentContext() || B.builtAll()) &&
10700 "omp loop exprs were not built");
10701
10702 setFunctionHasBranchProtectedScope();
10703
10704 return OMPParallelGenericLoopDirective::Create(
10705 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10706 }
10707
ActOnOpenMPTargetParallelGenericLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10708 StmtResult Sema::ActOnOpenMPTargetParallelGenericLoopDirective(
10709 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10710 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10711 if (!AStmt)
10712 return StmtError();
10713
10714 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10715 // A list item may not appear in a lastprivate clause unless it is the
10716 // loop iteration variable of a loop that is associated with the construct.
10717 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_target_parallel_loop,
10718 DSAStack))
10719 return StmtError();
10720
10721 auto *CS = cast<CapturedStmt>(AStmt);
10722 // 1.2.2 OpenMP Language Terminology
10723 // Structured block - An executable statement with a single entry at the
10724 // top and a single exit at the bottom.
10725 // The point of exit cannot be a branch out of the structured block.
10726 // longjmp() and throw() must not violate the entry/exit criteria.
10727 CS->getCapturedDecl()->setNothrow();
10728 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_loop);
10729 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10730 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10731 // 1.2.2 OpenMP Language Terminology
10732 // Structured block - An executable statement with a single entry at the
10733 // top and a single exit at the bottom.
10734 // The point of exit cannot be a branch out of the structured block.
10735 // longjmp() and throw() must not violate the entry/exit criteria.
10736 CS->getCapturedDecl()->setNothrow();
10737 }
10738
10739 OMPLoopDirective::HelperExprs B;
10740 // In presence of clause 'collapse', it will define the nested loops number.
10741 unsigned NestedLoopCount =
10742 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
10743 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10744 VarsWithImplicitDSA, B);
10745 if (NestedLoopCount == 0)
10746 return StmtError();
10747
10748 assert((CurContext->isDependentContext() || B.builtAll()) &&
10749 "omp loop exprs were not built");
10750
10751 setFunctionHasBranchProtectedScope();
10752
10753 return OMPTargetParallelGenericLoopDirective::Create(
10754 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10755 }
10756
ActOnOpenMPSingleDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10757 StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
10758 Stmt *AStmt,
10759 SourceLocation StartLoc,
10760 SourceLocation EndLoc) {
10761 if (!AStmt)
10762 return StmtError();
10763
10764 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10765
10766 setFunctionHasBranchProtectedScope();
10767
10768 // OpenMP [2.7.3, single Construct, Restrictions]
10769 // The copyprivate clause must not be used with the nowait clause.
10770 const OMPClause *Nowait = nullptr;
10771 const OMPClause *Copyprivate = nullptr;
10772 for (const OMPClause *Clause : Clauses) {
10773 if (Clause->getClauseKind() == OMPC_nowait)
10774 Nowait = Clause;
10775 else if (Clause->getClauseKind() == OMPC_copyprivate)
10776 Copyprivate = Clause;
10777 if (Copyprivate && Nowait) {
10778 Diag(Copyprivate->getBeginLoc(),
10779 diag::err_omp_single_copyprivate_with_nowait);
10780 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
10781 return StmtError();
10782 }
10783 }
10784
10785 return OMPSingleDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
10786 }
10787
ActOnOpenMPMasterDirective(Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10788 StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt,
10789 SourceLocation StartLoc,
10790 SourceLocation EndLoc) {
10791 if (!AStmt)
10792 return StmtError();
10793
10794 setFunctionHasBranchProtectedScope();
10795
10796 return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt);
10797 }
10798
ActOnOpenMPMaskedDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10799 StmtResult Sema::ActOnOpenMPMaskedDirective(ArrayRef<OMPClause *> Clauses,
10800 Stmt *AStmt,
10801 SourceLocation StartLoc,
10802 SourceLocation EndLoc) {
10803 if (!AStmt)
10804 return StmtError();
10805
10806 setFunctionHasBranchProtectedScope();
10807
10808 return OMPMaskedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
10809 }
10810
ActOnOpenMPCriticalDirective(const DeclarationNameInfo & DirName,ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10811 StmtResult Sema::ActOnOpenMPCriticalDirective(
10812 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
10813 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
10814 if (!AStmt)
10815 return StmtError();
10816
10817 bool ErrorFound = false;
10818 llvm::APSInt Hint;
10819 SourceLocation HintLoc;
10820 bool DependentHint = false;
10821 for (const OMPClause *C : Clauses) {
10822 if (C->getClauseKind() == OMPC_hint) {
10823 if (!DirName.getName()) {
10824 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
10825 ErrorFound = true;
10826 }
10827 Expr *E = cast<OMPHintClause>(C)->getHint();
10828 if (E->isTypeDependent() || E->isValueDependent() ||
10829 E->isInstantiationDependent()) {
10830 DependentHint = true;
10831 } else {
10832 Hint = E->EvaluateKnownConstInt(Context);
10833 HintLoc = C->getBeginLoc();
10834 }
10835 }
10836 }
10837 if (ErrorFound)
10838 return StmtError();
10839 const auto Pair = DSAStack->getCriticalWithHint(DirName);
10840 if (Pair.first && DirName.getName() && !DependentHint) {
10841 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
10842 Diag(StartLoc, diag::err_omp_critical_with_hint);
10843 if (HintLoc.isValid())
10844 Diag(HintLoc, diag::note_omp_critical_hint_here)
10845 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
10846 else
10847 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
10848 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
10849 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
10850 << 1
10851 << toString(C->getHint()->EvaluateKnownConstInt(Context),
10852 /*Radix=*/10, /*Signed=*/false);
10853 } else {
10854 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
10855 }
10856 }
10857 }
10858
10859 setFunctionHasBranchProtectedScope();
10860
10861 auto *Dir = OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc,
10862 Clauses, AStmt);
10863 if (!Pair.first && DirName.getName() && !DependentHint)
10864 DSAStack->addCriticalWithHint(Dir, Hint);
10865 return Dir;
10866 }
10867
ActOnOpenMPParallelForDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10868 StmtResult Sema::ActOnOpenMPParallelForDirective(
10869 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10870 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10871 if (!AStmt)
10872 return StmtError();
10873
10874 auto *CS = cast<CapturedStmt>(AStmt);
10875 // 1.2.2 OpenMP Language Terminology
10876 // Structured block - An executable statement with a single entry at the
10877 // top and a single exit at the bottom.
10878 // The point of exit cannot be a branch out of the structured block.
10879 // longjmp() and throw() must not violate the entry/exit criteria.
10880 CS->getCapturedDecl()->setNothrow();
10881
10882 OMPLoopBasedDirective::HelperExprs B;
10883 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10884 // define the nested loops number.
10885 unsigned NestedLoopCount =
10886 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
10887 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
10888 VarsWithImplicitDSA, B);
10889 if (NestedLoopCount == 0)
10890 return StmtError();
10891
10892 assert((CurContext->isDependentContext() || B.builtAll()) &&
10893 "omp parallel for loop exprs were not built");
10894
10895 if (!CurContext->isDependentContext()) {
10896 // Finalize the clauses that need pre-built expressions for CodeGen.
10897 for (OMPClause *C : Clauses) {
10898 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10899 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10900 B.NumIterations, *this, CurScope,
10901 DSAStack))
10902 return StmtError();
10903 }
10904 }
10905
10906 setFunctionHasBranchProtectedScope();
10907 return OMPParallelForDirective::Create(
10908 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10909 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10910 }
10911
ActOnOpenMPParallelForSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)10912 StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
10913 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10914 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10915 if (!AStmt)
10916 return StmtError();
10917
10918 auto *CS = cast<CapturedStmt>(AStmt);
10919 // 1.2.2 OpenMP Language Terminology
10920 // Structured block - An executable statement with a single entry at the
10921 // top and a single exit at the bottom.
10922 // The point of exit cannot be a branch out of the structured block.
10923 // longjmp() and throw() must not violate the entry/exit criteria.
10924 CS->getCapturedDecl()->setNothrow();
10925
10926 OMPLoopBasedDirective::HelperExprs B;
10927 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10928 // define the nested loops number.
10929 unsigned NestedLoopCount =
10930 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
10931 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
10932 VarsWithImplicitDSA, B);
10933 if (NestedLoopCount == 0)
10934 return StmtError();
10935
10936 if (!CurContext->isDependentContext()) {
10937 // Finalize the clauses that need pre-built expressions for CodeGen.
10938 for (OMPClause *C : Clauses) {
10939 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10940 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10941 B.NumIterations, *this, CurScope,
10942 DSAStack))
10943 return StmtError();
10944 }
10945 }
10946
10947 if (checkSimdlenSafelenSpecified(*this, Clauses))
10948 return StmtError();
10949
10950 setFunctionHasBranchProtectedScope();
10951 return OMPParallelForSimdDirective::Create(
10952 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10953 }
10954
10955 StmtResult
ActOnOpenMPParallelMasterDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10956 Sema::ActOnOpenMPParallelMasterDirective(ArrayRef<OMPClause *> Clauses,
10957 Stmt *AStmt, SourceLocation StartLoc,
10958 SourceLocation EndLoc) {
10959 if (!AStmt)
10960 return StmtError();
10961
10962 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10963 auto *CS = cast<CapturedStmt>(AStmt);
10964 // 1.2.2 OpenMP Language Terminology
10965 // Structured block - An executable statement with a single entry at the
10966 // top and a single exit at the bottom.
10967 // The point of exit cannot be a branch out of the structured block.
10968 // longjmp() and throw() must not violate the entry/exit criteria.
10969 CS->getCapturedDecl()->setNothrow();
10970
10971 setFunctionHasBranchProtectedScope();
10972
10973 return OMPParallelMasterDirective::Create(
10974 Context, StartLoc, EndLoc, Clauses, AStmt,
10975 DSAStack->getTaskgroupReductionRef());
10976 }
10977
10978 StmtResult
ActOnOpenMPParallelMaskedDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)10979 Sema::ActOnOpenMPParallelMaskedDirective(ArrayRef<OMPClause *> Clauses,
10980 Stmt *AStmt, SourceLocation StartLoc,
10981 SourceLocation EndLoc) {
10982 if (!AStmt)
10983 return StmtError();
10984
10985 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10986 auto *CS = cast<CapturedStmt>(AStmt);
10987 // 1.2.2 OpenMP Language Terminology
10988 // Structured block - An executable statement with a single entry at the
10989 // top and a single exit at the bottom.
10990 // The point of exit cannot be a branch out of the structured block.
10991 // longjmp() and throw() must not violate the entry/exit criteria.
10992 CS->getCapturedDecl()->setNothrow();
10993
10994 setFunctionHasBranchProtectedScope();
10995
10996 return OMPParallelMaskedDirective::Create(
10997 Context, StartLoc, EndLoc, Clauses, AStmt,
10998 DSAStack->getTaskgroupReductionRef());
10999 }
11000
11001 StmtResult
ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)11002 Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
11003 Stmt *AStmt, SourceLocation StartLoc,
11004 SourceLocation EndLoc) {
11005 if (!AStmt)
11006 return StmtError();
11007
11008 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11009 auto BaseStmt = AStmt;
11010 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
11011 BaseStmt = CS->getCapturedStmt();
11012 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
11013 auto S = C->children();
11014 if (S.begin() == S.end())
11015 return StmtError();
11016 // All associated statements must be '#pragma omp section' except for
11017 // the first one.
11018 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
11019 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
11020 if (SectionStmt)
11021 Diag(SectionStmt->getBeginLoc(),
11022 diag::err_omp_parallel_sections_substmt_not_section);
11023 return StmtError();
11024 }
11025 cast<OMPSectionDirective>(SectionStmt)
11026 ->setHasCancel(DSAStack->isCancelRegion());
11027 }
11028 } else {
11029 Diag(AStmt->getBeginLoc(),
11030 diag::err_omp_parallel_sections_not_compound_stmt);
11031 return StmtError();
11032 }
11033
11034 setFunctionHasBranchProtectedScope();
11035
11036 return OMPParallelSectionsDirective::Create(
11037 Context, StartLoc, EndLoc, Clauses, AStmt,
11038 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11039 }
11040
11041 /// Find and diagnose mutually exclusive clause kinds.
checkMutuallyExclusiveClauses(Sema & S,ArrayRef<OMPClause * > Clauses,ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses)11042 static bool checkMutuallyExclusiveClauses(
11043 Sema &S, ArrayRef<OMPClause *> Clauses,
11044 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11045 const OMPClause *PrevClause = nullptr;
11046 bool ErrorFound = false;
11047 for (const OMPClause *C : Clauses) {
11048 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
11049 if (!PrevClause) {
11050 PrevClause = C;
11051 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11052 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11053 << getOpenMPClauseName(C->getClauseKind())
11054 << getOpenMPClauseName(PrevClause->getClauseKind());
11055 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
11056 << getOpenMPClauseName(PrevClause->getClauseKind());
11057 ErrorFound = true;
11058 }
11059 }
11060 }
11061 return ErrorFound;
11062 }
11063
ActOnOpenMPTaskDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)11064 StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
11065 Stmt *AStmt, SourceLocation StartLoc,
11066 SourceLocation EndLoc) {
11067 if (!AStmt)
11068 return StmtError();
11069
11070 // OpenMP 5.0, 2.10.1 task Construct
11071 // If a detach clause appears on the directive, then a mergeable clause cannot
11072 // appear on the same directive.
11073 if (checkMutuallyExclusiveClauses(*this, Clauses,
11074 {OMPC_detach, OMPC_mergeable}))
11075 return StmtError();
11076
11077 auto *CS = cast<CapturedStmt>(AStmt);
11078 // 1.2.2 OpenMP Language Terminology
11079 // Structured block - An executable statement with a single entry at the
11080 // top and a single exit at the bottom.
11081 // The point of exit cannot be a branch out of the structured block.
11082 // longjmp() and throw() must not violate the entry/exit criteria.
11083 CS->getCapturedDecl()->setNothrow();
11084
11085 setFunctionHasBranchProtectedScope();
11086
11087 return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
11088 DSAStack->isCancelRegion());
11089 }
11090
ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,SourceLocation EndLoc)11091 StmtResult Sema::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
11092 SourceLocation EndLoc) {
11093 return OMPTaskyieldDirective::Create(Context, StartLoc, EndLoc);
11094 }
11095
ActOnOpenMPBarrierDirective(SourceLocation StartLoc,SourceLocation EndLoc)11096 StmtResult Sema::ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
11097 SourceLocation EndLoc) {
11098 return OMPBarrierDirective::Create(Context, StartLoc, EndLoc);
11099 }
11100
ActOnOpenMPErrorDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc,bool InExContext)11101 StmtResult Sema::ActOnOpenMPErrorDirective(ArrayRef<OMPClause *> Clauses,
11102 SourceLocation StartLoc,
11103 SourceLocation EndLoc,
11104 bool InExContext) {
11105 const OMPAtClause *AtC =
11106 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11107
11108 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11109 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11110 return StmtError();
11111 }
11112
11113 const OMPSeverityClause *SeverityC =
11114 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11115 const OMPMessageClause *MessageC =
11116 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11117 Expr *ME = MessageC ? MessageC->getMessageString() : nullptr;
11118
11119 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11120 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11121 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11122 << (ME ? cast<StringLiteral>(ME)->getString() : "WARNING");
11123 else
11124 Diag(StartLoc, diag::err_diagnose_if_succeeded)
11125 << (ME ? cast<StringLiteral>(ME)->getString() : "ERROR");
11126 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11127 return StmtError();
11128 }
11129 return OMPErrorDirective::Create(Context, StartLoc, EndLoc, Clauses);
11130 }
11131
ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc)11132 StmtResult Sema::ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause *> Clauses,
11133 SourceLocation StartLoc,
11134 SourceLocation EndLoc) {
11135 const OMPNowaitClause *NowaitC =
11136 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11137 bool HasDependC =
11138 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11139 .empty();
11140 if (NowaitC && !HasDependC) {
11141 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11142 return StmtError();
11143 }
11144
11145 return OMPTaskwaitDirective::Create(Context, StartLoc, EndLoc, Clauses);
11146 }
11147
ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)11148 StmtResult Sema::ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
11149 Stmt *AStmt,
11150 SourceLocation StartLoc,
11151 SourceLocation EndLoc) {
11152 if (!AStmt)
11153 return StmtError();
11154
11155 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11156
11157 setFunctionHasBranchProtectedScope();
11158
11159 return OMPTaskgroupDirective::Create(Context, StartLoc, EndLoc, Clauses,
11160 AStmt,
11161 DSAStack->getTaskgroupReductionRef());
11162 }
11163
ActOnOpenMPFlushDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc)11164 StmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
11165 SourceLocation StartLoc,
11166 SourceLocation EndLoc) {
11167 OMPFlushClause *FC = nullptr;
11168 OMPClause *OrderClause = nullptr;
11169 for (OMPClause *C : Clauses) {
11170 if (C->getClauseKind() == OMPC_flush)
11171 FC = cast<OMPFlushClause>(C);
11172 else
11173 OrderClause = C;
11174 }
11175 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11176 SourceLocation MemOrderLoc;
11177 for (const OMPClause *C : Clauses) {
11178 if (C->getClauseKind() == OMPC_acq_rel ||
11179 C->getClauseKind() == OMPC_acquire ||
11180 C->getClauseKind() == OMPC_release) {
11181 if (MemOrderKind != OMPC_unknown) {
11182 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11183 << getOpenMPDirectiveName(OMPD_flush) << 1
11184 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11185 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11186 << getOpenMPClauseName(MemOrderKind);
11187 } else {
11188 MemOrderKind = C->getClauseKind();
11189 MemOrderLoc = C->getBeginLoc();
11190 }
11191 }
11192 }
11193 if (FC && OrderClause) {
11194 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11195 << getOpenMPClauseName(OrderClause->getClauseKind());
11196 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11197 << getOpenMPClauseName(OrderClause->getClauseKind());
11198 return StmtError();
11199 }
11200 return OMPFlushDirective::Create(Context, StartLoc, EndLoc, Clauses);
11201 }
11202
ActOnOpenMPDepobjDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc)11203 StmtResult Sema::ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses,
11204 SourceLocation StartLoc,
11205 SourceLocation EndLoc) {
11206 if (Clauses.empty()) {
11207 Diag(StartLoc, diag::err_omp_depobj_expected);
11208 return StmtError();
11209 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11210 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11211 return StmtError();
11212 }
11213 // Only depobj expression and another single clause is allowed.
11214 if (Clauses.size() > 2) {
11215 Diag(Clauses[2]->getBeginLoc(),
11216 diag::err_omp_depobj_single_clause_expected);
11217 return StmtError();
11218 } else if (Clauses.size() < 1) {
11219 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11220 return StmtError();
11221 }
11222 return OMPDepobjDirective::Create(Context, StartLoc, EndLoc, Clauses);
11223 }
11224
ActOnOpenMPScanDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc)11225 StmtResult Sema::ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses,
11226 SourceLocation StartLoc,
11227 SourceLocation EndLoc) {
11228 // Check that exactly one clause is specified.
11229 if (Clauses.size() != 1) {
11230 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11231 diag::err_omp_scan_single_clause_expected);
11232 return StmtError();
11233 }
11234 // Check that scan directive is used in the scopeof the OpenMP loop body.
11235 if (Scope *S = DSAStack->getCurScope()) {
11236 Scope *ParentS = S->getParent();
11237 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11238 !ParentS->getBreakParent()->isOpenMPLoopScope())
11239 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11240 << getOpenMPDirectiveName(OMPD_scan) << 5);
11241 }
11242 // Check that only one instance of scan directives is used in the same outer
11243 // region.
11244 if (DSAStack->doesParentHasScanDirective()) {
11245 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11246 Diag(DSAStack->getParentScanDirectiveLoc(),
11247 diag::note_omp_previous_directive)
11248 << "scan";
11249 return StmtError();
11250 }
11251 DSAStack->setParentHasScanDirective(StartLoc);
11252 return OMPScanDirective::Create(Context, StartLoc, EndLoc, Clauses);
11253 }
11254
ActOnOpenMPOrderedDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)11255 StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
11256 Stmt *AStmt,
11257 SourceLocation StartLoc,
11258 SourceLocation EndLoc) {
11259 const OMPClause *DependFound = nullptr;
11260 const OMPClause *DependSourceClause = nullptr;
11261 const OMPClause *DependSinkClause = nullptr;
11262 bool ErrorFound = false;
11263 const OMPThreadsClause *TC = nullptr;
11264 const OMPSIMDClause *SC = nullptr;
11265 for (const OMPClause *C : Clauses) {
11266 if (auto *DC = dyn_cast<OMPDependClause>(C)) {
11267 DependFound = C;
11268 if (DC->getDependencyKind() == OMPC_DEPEND_source) {
11269 if (DependSourceClause) {
11270 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11271 << getOpenMPDirectiveName(OMPD_ordered)
11272 << getOpenMPClauseName(OMPC_depend) << 2;
11273 ErrorFound = true;
11274 } else {
11275 DependSourceClause = C;
11276 }
11277 if (DependSinkClause) {
11278 Diag(C->getBeginLoc(), diag::err_omp_depend_sink_source_not_allowed)
11279 << 0;
11280 ErrorFound = true;
11281 }
11282 } else if (DC->getDependencyKind() == OMPC_DEPEND_sink) {
11283 if (DependSourceClause) {
11284 Diag(C->getBeginLoc(), diag::err_omp_depend_sink_source_not_allowed)
11285 << 1;
11286 ErrorFound = true;
11287 }
11288 DependSinkClause = C;
11289 }
11290 } else if (C->getClauseKind() == OMPC_threads) {
11291 TC = cast<OMPThreadsClause>(C);
11292 } else if (C->getClauseKind() == OMPC_simd) {
11293 SC = cast<OMPSIMDClause>(C);
11294 }
11295 }
11296 if (!ErrorFound && !SC &&
11297 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11298 // OpenMP [2.8.1,simd Construct, Restrictions]
11299 // An ordered construct with the simd clause is the only OpenMP construct
11300 // that can appear in the simd region.
11301 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11302 << (LangOpts.OpenMP >= 50 ? 1 : 0);
11303 ErrorFound = true;
11304 } else if (DependFound && (TC || SC)) {
11305 Diag(DependFound->getBeginLoc(), diag::err_omp_depend_clause_thread_simd)
11306 << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
11307 ErrorFound = true;
11308 } else if (DependFound && !DSAStack->getParentOrderedRegionParam().first) {
11309 Diag(DependFound->getBeginLoc(),
11310 diag::err_omp_ordered_directive_without_param);
11311 ErrorFound = true;
11312 } else if (TC || Clauses.empty()) {
11313 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11314 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11315 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11316 << (TC != nullptr);
11317 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11318 ErrorFound = true;
11319 }
11320 }
11321 if ((!AStmt && !DependFound) || ErrorFound)
11322 return StmtError();
11323
11324 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11325 // During execution of an iteration of a worksharing-loop or a loop nest
11326 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11327 // must not execute more than one ordered region corresponding to an ordered
11328 // construct without a depend clause.
11329 if (!DependFound) {
11330 if (DSAStack->doesParentHasOrderedDirective()) {
11331 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11332 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11333 diag::note_omp_previous_directive)
11334 << "ordered";
11335 return StmtError();
11336 }
11337 DSAStack->setParentHasOrderedDirective(StartLoc);
11338 }
11339
11340 if (AStmt) {
11341 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11342
11343 setFunctionHasBranchProtectedScope();
11344 }
11345
11346 return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
11347 }
11348
11349 namespace {
11350 /// Helper class for checking expression in 'omp atomic [update]'
11351 /// construct.
11352 class OpenMPAtomicUpdateChecker {
11353 /// Error results for atomic update expressions.
11354 enum ExprAnalysisErrorCode {
11355 /// A statement is not an expression statement.
11356 NotAnExpression,
11357 /// Expression is not builtin binary or unary operation.
11358 NotABinaryOrUnaryExpression,
11359 /// Unary operation is not post-/pre- increment/decrement operation.
11360 NotAnUnaryIncDecExpression,
11361 /// An expression is not of scalar type.
11362 NotAScalarType,
11363 /// A binary operation is not an assignment operation.
11364 NotAnAssignmentOp,
11365 /// RHS part of the binary operation is not a binary expression.
11366 NotABinaryExpression,
11367 /// RHS part is not additive/multiplicative/shift/biwise binary
11368 /// expression.
11369 NotABinaryOperator,
11370 /// RHS binary operation does not have reference to the updated LHS
11371 /// part.
11372 NotAnUpdateExpression,
11373 /// No errors is found.
11374 NoError
11375 };
11376 /// Reference to Sema.
11377 Sema &SemaRef;
11378 /// A location for note diagnostics (when error is found).
11379 SourceLocation NoteLoc;
11380 /// 'x' lvalue part of the source atomic expression.
11381 Expr *X;
11382 /// 'expr' rvalue part of the source atomic expression.
11383 Expr *E;
11384 /// Helper expression of the form
11385 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11386 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11387 Expr *UpdateExpr;
11388 /// Is 'x' a LHS in a RHS part of full update expression. It is
11389 /// important for non-associative operations.
11390 bool IsXLHSInRHSPart;
11391 BinaryOperatorKind Op;
11392 SourceLocation OpLoc;
11393 /// true if the source expression is a postfix unary operation, false
11394 /// if it is a prefix unary operation.
11395 bool IsPostfixUpdate;
11396
11397 public:
OpenMPAtomicUpdateChecker(Sema & SemaRef)11398 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11399 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11400 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11401 /// Check specified statement that it is suitable for 'atomic update'
11402 /// constructs and extract 'x', 'expr' and Operation from the original
11403 /// expression. If DiagId and NoteId == 0, then only check is performed
11404 /// without error notification.
11405 /// \param DiagId Diagnostic which should be emitted if error is found.
11406 /// \param NoteId Diagnostic note for the main error message.
11407 /// \return true if statement is not an update expression, false otherwise.
11408 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11409 /// Return the 'x' lvalue part of the source atomic expression.
getX() const11410 Expr *getX() const { return X; }
11411 /// Return the 'expr' rvalue part of the source atomic expression.
getExpr() const11412 Expr *getExpr() const { return E; }
11413 /// Return the update expression used in calculation of the updated
11414 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11415 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
getUpdateExpr() const11416 Expr *getUpdateExpr() const { return UpdateExpr; }
11417 /// Return true if 'x' is LHS in RHS part of full update expression,
11418 /// false otherwise.
isXLHSInRHSPart() const11419 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11420
11421 /// true if the source expression is a postfix unary operation, false
11422 /// if it is a prefix unary operation.
isPostfixUpdate() const11423 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11424
11425 private:
11426 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11427 unsigned NoteId = 0);
11428 };
11429
checkBinaryOperation(BinaryOperator * AtomicBinOp,unsigned DiagId,unsigned NoteId)11430 bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11431 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11432 ExprAnalysisErrorCode ErrorFound = NoError;
11433 SourceLocation ErrorLoc, NoteLoc;
11434 SourceRange ErrorRange, NoteRange;
11435 // Allowed constructs are:
11436 // x = x binop expr;
11437 // x = expr binop x;
11438 if (AtomicBinOp->getOpcode() == BO_Assign) {
11439 X = AtomicBinOp->getLHS();
11440 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11441 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11442 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11443 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11444 AtomicInnerBinOp->isBitwiseOp()) {
11445 Op = AtomicInnerBinOp->getOpcode();
11446 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11447 Expr *LHS = AtomicInnerBinOp->getLHS();
11448 Expr *RHS = AtomicInnerBinOp->getRHS();
11449 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11450 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11451 /*Canonical=*/true);
11452 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11453 /*Canonical=*/true);
11454 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11455 /*Canonical=*/true);
11456 if (XId == LHSId) {
11457 E = RHS;
11458 IsXLHSInRHSPart = true;
11459 } else if (XId == RHSId) {
11460 E = LHS;
11461 IsXLHSInRHSPart = false;
11462 } else {
11463 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11464 ErrorRange = AtomicInnerBinOp->getSourceRange();
11465 NoteLoc = X->getExprLoc();
11466 NoteRange = X->getSourceRange();
11467 ErrorFound = NotAnUpdateExpression;
11468 }
11469 } else {
11470 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11471 ErrorRange = AtomicInnerBinOp->getSourceRange();
11472 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11473 NoteRange = SourceRange(NoteLoc, NoteLoc);
11474 ErrorFound = NotABinaryOperator;
11475 }
11476 } else {
11477 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11478 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11479 ErrorFound = NotABinaryExpression;
11480 }
11481 } else {
11482 ErrorLoc = AtomicBinOp->getExprLoc();
11483 ErrorRange = AtomicBinOp->getSourceRange();
11484 NoteLoc = AtomicBinOp->getOperatorLoc();
11485 NoteRange = SourceRange(NoteLoc, NoteLoc);
11486 ErrorFound = NotAnAssignmentOp;
11487 }
11488 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11489 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11490 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11491 return true;
11492 }
11493 if (SemaRef.CurContext->isDependentContext())
11494 E = X = UpdateExpr = nullptr;
11495 return ErrorFound != NoError;
11496 }
11497
checkStatement(Stmt * S,unsigned DiagId,unsigned NoteId)11498 bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11499 unsigned NoteId) {
11500 ExprAnalysisErrorCode ErrorFound = NoError;
11501 SourceLocation ErrorLoc, NoteLoc;
11502 SourceRange ErrorRange, NoteRange;
11503 // Allowed constructs are:
11504 // x++;
11505 // x--;
11506 // ++x;
11507 // --x;
11508 // x binop= expr;
11509 // x = x binop expr;
11510 // x = expr binop x;
11511 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11512 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11513 if (AtomicBody->getType()->isScalarType() ||
11514 AtomicBody->isInstantiationDependent()) {
11515 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11516 AtomicBody->IgnoreParenImpCasts())) {
11517 // Check for Compound Assignment Operation
11518 Op = BinaryOperator::getOpForCompoundAssignment(
11519 AtomicCompAssignOp->getOpcode());
11520 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11521 E = AtomicCompAssignOp->getRHS();
11522 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11523 IsXLHSInRHSPart = true;
11524 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11525 AtomicBody->IgnoreParenImpCasts())) {
11526 // Check for Binary Operation
11527 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11528 return true;
11529 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11530 AtomicBody->IgnoreParenImpCasts())) {
11531 // Check for Unary Operation
11532 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11533 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11534 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11535 OpLoc = AtomicUnaryOp->getOperatorLoc();
11536 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11537 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11538 IsXLHSInRHSPart = true;
11539 } else {
11540 ErrorFound = NotAnUnaryIncDecExpression;
11541 ErrorLoc = AtomicUnaryOp->getExprLoc();
11542 ErrorRange = AtomicUnaryOp->getSourceRange();
11543 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11544 NoteRange = SourceRange(NoteLoc, NoteLoc);
11545 }
11546 } else if (!AtomicBody->isInstantiationDependent()) {
11547 ErrorFound = NotABinaryOrUnaryExpression;
11548 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11549 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11550 }
11551 } else {
11552 ErrorFound = NotAScalarType;
11553 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11554 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11555 }
11556 } else {
11557 ErrorFound = NotAnExpression;
11558 NoteLoc = ErrorLoc = S->getBeginLoc();
11559 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11560 }
11561 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11562 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11563 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11564 return true;
11565 }
11566 if (SemaRef.CurContext->isDependentContext())
11567 E = X = UpdateExpr = nullptr;
11568 if (ErrorFound == NoError && E && X) {
11569 // Build an update expression of form 'OpaqueValueExpr(x) binop
11570 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11571 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11572 auto *OVEX = new (SemaRef.getASTContext())
11573 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11574 auto *OVEExpr = new (SemaRef.getASTContext())
11575 OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_PRValue);
11576 ExprResult Update =
11577 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11578 IsXLHSInRHSPart ? OVEExpr : OVEX);
11579 if (Update.isInvalid())
11580 return true;
11581 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11582 Sema::AA_Casting);
11583 if (Update.isInvalid())
11584 return true;
11585 UpdateExpr = Update.get();
11586 }
11587 return ErrorFound != NoError;
11588 }
11589
11590 /// Get the node id of the fixed point of an expression \a S.
getNodeId(ASTContext & Context,const Expr * S)11591 llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11592 llvm::FoldingSetNodeID Id;
11593 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11594 return Id;
11595 }
11596
11597 /// Check if two expressions are same.
checkIfTwoExprsAreSame(ASTContext & Context,const Expr * LHS,const Expr * RHS)11598 bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11599 const Expr *RHS) {
11600 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11601 }
11602
11603 class OpenMPAtomicCompareChecker {
11604 public:
11605 /// All kinds of errors that can occur in `atomic compare`
11606 enum ErrorTy {
11607 /// Empty compound statement.
11608 NoStmt = 0,
11609 /// More than one statement in a compound statement.
11610 MoreThanOneStmt,
11611 /// Not an assignment binary operator.
11612 NotAnAssignment,
11613 /// Not a conditional operator.
11614 NotCondOp,
11615 /// Wrong false expr. According to the spec, 'x' should be at the false
11616 /// expression of a conditional expression.
11617 WrongFalseExpr,
11618 /// The condition of a conditional expression is not a binary operator.
11619 NotABinaryOp,
11620 /// Invalid binary operator (not <, >, or ==).
11621 InvalidBinaryOp,
11622 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11623 InvalidComparison,
11624 /// X is not a lvalue.
11625 XNotLValue,
11626 /// Not a scalar.
11627 NotScalar,
11628 /// Not an integer.
11629 NotInteger,
11630 /// 'else' statement is not expected.
11631 UnexpectedElse,
11632 /// Not an equality operator.
11633 NotEQ,
11634 /// Invalid assignment (not v == x).
11635 InvalidAssignment,
11636 /// Not if statement
11637 NotIfStmt,
11638 /// More than two statements in a compund statement.
11639 MoreThanTwoStmts,
11640 /// Not a compound statement.
11641 NotCompoundStmt,
11642 /// No else statement.
11643 NoElse,
11644 /// Not 'if (r)'.
11645 InvalidCondition,
11646 /// No error.
11647 NoError,
11648 };
11649
11650 struct ErrorInfoTy {
11651 ErrorTy Error;
11652 SourceLocation ErrorLoc;
11653 SourceRange ErrorRange;
11654 SourceLocation NoteLoc;
11655 SourceRange NoteRange;
11656 };
11657
OpenMPAtomicCompareChecker(Sema & S)11658 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11659
11660 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11661 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11662
getX() const11663 Expr *getX() const { return X; }
getE() const11664 Expr *getE() const { return E; }
getD() const11665 Expr *getD() const { return D; }
getCond() const11666 Expr *getCond() const { return C; }
isXBinopExpr() const11667 bool isXBinopExpr() const { return IsXBinopExpr; }
11668
11669 protected:
11670 /// Reference to ASTContext
11671 ASTContext &ContextRef;
11672 /// 'x' lvalue part of the source atomic expression.
11673 Expr *X = nullptr;
11674 /// 'expr' or 'e' rvalue part of the source atomic expression.
11675 Expr *E = nullptr;
11676 /// 'd' rvalue part of the source atomic expression.
11677 Expr *D = nullptr;
11678 /// 'cond' part of the source atomic expression. It is in one of the following
11679 /// forms:
11680 /// expr ordop x
11681 /// x ordop expr
11682 /// x == e
11683 /// e == x
11684 Expr *C = nullptr;
11685 /// True if the cond expr is in the form of 'x ordop expr'.
11686 bool IsXBinopExpr = true;
11687
11688 /// Check if it is a valid conditional update statement (cond-update-stmt).
11689 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11690
11691 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11692 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11693
11694 /// Check if all captured values have right type.
11695 bool checkType(ErrorInfoTy &ErrorInfo) const;
11696
CheckValue(const Expr * E,ErrorInfoTy & ErrorInfo,bool ShouldBeLValue,bool ShouldBeInteger=false)11697 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11698 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11699 if (E->isInstantiationDependent())
11700 return true;
11701
11702 if (ShouldBeLValue && !E->isLValue()) {
11703 ErrorInfo.Error = ErrorTy::XNotLValue;
11704 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11705 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11706 return false;
11707 }
11708
11709 QualType QTy = E->getType();
11710 if (!QTy->isScalarType()) {
11711 ErrorInfo.Error = ErrorTy::NotScalar;
11712 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11713 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11714 return false;
11715 }
11716 if (ShouldBeInteger && !QTy->isIntegerType()) {
11717 ErrorInfo.Error = ErrorTy::NotInteger;
11718 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11719 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11720 return false;
11721 }
11722
11723 return true;
11724 }
11725 };
11726
checkCondUpdateStmt(IfStmt * S,ErrorInfoTy & ErrorInfo)11727 bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11728 ErrorInfoTy &ErrorInfo) {
11729 auto *Then = S->getThen();
11730 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11731 if (CS->body_empty()) {
11732 ErrorInfo.Error = ErrorTy::NoStmt;
11733 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11734 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11735 return false;
11736 }
11737 if (CS->size() > 1) {
11738 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11739 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11740 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11741 return false;
11742 }
11743 Then = CS->body_front();
11744 }
11745
11746 auto *BO = dyn_cast<BinaryOperator>(Then);
11747 if (!BO) {
11748 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11749 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11750 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11751 return false;
11752 }
11753 if (BO->getOpcode() != BO_Assign) {
11754 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11755 ErrorInfo.ErrorLoc = BO->getExprLoc();
11756 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11757 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11758 return false;
11759 }
11760
11761 X = BO->getLHS();
11762
11763 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11764 if (!Cond) {
11765 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11766 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11767 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11768 return false;
11769 }
11770
11771 switch (Cond->getOpcode()) {
11772 case BO_EQ: {
11773 C = Cond;
11774 D = BO->getRHS();
11775 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11776 E = Cond->getRHS();
11777 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11778 E = Cond->getLHS();
11779 } else {
11780 ErrorInfo.Error = ErrorTy::InvalidComparison;
11781 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11782 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11783 return false;
11784 }
11785 break;
11786 }
11787 case BO_LT:
11788 case BO_GT: {
11789 E = BO->getRHS();
11790 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
11791 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
11792 C = Cond;
11793 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
11794 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11795 C = Cond;
11796 IsXBinopExpr = false;
11797 } else {
11798 ErrorInfo.Error = ErrorTy::InvalidComparison;
11799 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11800 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11801 return false;
11802 }
11803 break;
11804 }
11805 default:
11806 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11807 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11808 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11809 return false;
11810 }
11811
11812 if (S->getElse()) {
11813 ErrorInfo.Error = ErrorTy::UnexpectedElse;
11814 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
11815 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
11816 return false;
11817 }
11818
11819 return true;
11820 }
11821
checkCondExprStmt(Stmt * S,ErrorInfoTy & ErrorInfo)11822 bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
11823 ErrorInfoTy &ErrorInfo) {
11824 auto *BO = dyn_cast<BinaryOperator>(S);
11825 if (!BO) {
11826 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11827 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11828 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11829 return false;
11830 }
11831 if (BO->getOpcode() != BO_Assign) {
11832 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11833 ErrorInfo.ErrorLoc = BO->getExprLoc();
11834 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11835 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11836 return false;
11837 }
11838
11839 X = BO->getLHS();
11840
11841 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
11842 if (!CO) {
11843 ErrorInfo.Error = ErrorTy::NotCondOp;
11844 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
11845 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
11846 return false;
11847 }
11848
11849 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
11850 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
11851 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
11852 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11853 CO->getFalseExpr()->getSourceRange();
11854 return false;
11855 }
11856
11857 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
11858 if (!Cond) {
11859 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11860 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11861 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11862 CO->getCond()->getSourceRange();
11863 return false;
11864 }
11865
11866 switch (Cond->getOpcode()) {
11867 case BO_EQ: {
11868 C = Cond;
11869 D = CO->getTrueExpr();
11870 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11871 E = Cond->getRHS();
11872 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11873 E = Cond->getLHS();
11874 } else {
11875 ErrorInfo.Error = ErrorTy::InvalidComparison;
11876 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11877 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11878 return false;
11879 }
11880 break;
11881 }
11882 case BO_LT:
11883 case BO_GT: {
11884 E = CO->getTrueExpr();
11885 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
11886 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
11887 C = Cond;
11888 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
11889 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11890 C = Cond;
11891 IsXBinopExpr = false;
11892 } else {
11893 ErrorInfo.Error = ErrorTy::InvalidComparison;
11894 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11895 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11896 return false;
11897 }
11898 break;
11899 }
11900 default:
11901 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11902 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11903 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11904 return false;
11905 }
11906
11907 return true;
11908 }
11909
checkType(ErrorInfoTy & ErrorInfo) const11910 bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
11911 // 'x' and 'e' cannot be nullptr
11912 assert(X && E && "X and E cannot be nullptr");
11913
11914 if (!CheckValue(X, ErrorInfo, true))
11915 return false;
11916
11917 if (!CheckValue(E, ErrorInfo, false))
11918 return false;
11919
11920 if (D && !CheckValue(D, ErrorInfo, false))
11921 return false;
11922
11923 return true;
11924 }
11925
checkStmt(Stmt * S,OpenMPAtomicCompareChecker::ErrorInfoTy & ErrorInfo)11926 bool OpenMPAtomicCompareChecker::checkStmt(
11927 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
11928 auto *CS = dyn_cast<CompoundStmt>(S);
11929 if (CS) {
11930 if (CS->body_empty()) {
11931 ErrorInfo.Error = ErrorTy::NoStmt;
11932 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11933 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11934 return false;
11935 }
11936
11937 if (CS->size() != 1) {
11938 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11939 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11940 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11941 return false;
11942 }
11943 S = CS->body_front();
11944 }
11945
11946 auto Res = false;
11947
11948 if (auto *IS = dyn_cast<IfStmt>(S)) {
11949 // Check if the statement is in one of the following forms
11950 // (cond-update-stmt):
11951 // if (expr ordop x) { x = expr; }
11952 // if (x ordop expr) { x = expr; }
11953 // if (x == e) { x = d; }
11954 Res = checkCondUpdateStmt(IS, ErrorInfo);
11955 } else {
11956 // Check if the statement is in one of the following forms (cond-expr-stmt):
11957 // x = expr ordop x ? expr : x;
11958 // x = x ordop expr ? expr : x;
11959 // x = x == e ? d : x;
11960 Res = checkCondExprStmt(S, ErrorInfo);
11961 }
11962
11963 if (!Res)
11964 return false;
11965
11966 return checkType(ErrorInfo);
11967 }
11968
11969 class OpenMPAtomicCompareCaptureChecker final
11970 : public OpenMPAtomicCompareChecker {
11971 public:
OpenMPAtomicCompareCaptureChecker(Sema & S)11972 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
11973
getV() const11974 Expr *getV() const { return V; }
getR() const11975 Expr *getR() const { return R; }
isFailOnly() const11976 bool isFailOnly() const { return IsFailOnly; }
isPostfixUpdate() const11977 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11978
11979 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
11980 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11981
11982 private:
11983 bool checkType(ErrorInfoTy &ErrorInfo);
11984
11985 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
11986 // form of 'conditional-update-capture-atomic' structured block on the v5.2
11987 // spec p.p. 82:
11988 // (1) { v = x; cond-update-stmt }
11989 // (2) { cond-update-stmt v = x; }
11990 // (3) if(x == e) { x = d; } else { v = x; }
11991 // (4) { r = x == e; if(r) { x = d; } }
11992 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
11993
11994 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
11995 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
11996
11997 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
11998 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
11999 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12000
12001 /// 'v' lvalue part of the source atomic expression.
12002 Expr *V = nullptr;
12003 /// 'r' lvalue part of the source atomic expression.
12004 Expr *R = nullptr;
12005 /// If 'v' is only updated when the comparison fails.
12006 bool IsFailOnly = false;
12007 /// If original value of 'x' must be stored in 'v', not an updated one.
12008 bool IsPostfixUpdate = false;
12009 };
12010
checkType(ErrorInfoTy & ErrorInfo)12011 bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12012 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12013 return false;
12014
12015 if (V && !CheckValue(V, ErrorInfo, true))
12016 return false;
12017
12018 if (R && !CheckValue(R, ErrorInfo, true, true))
12019 return false;
12020
12021 return true;
12022 }
12023
checkForm3(IfStmt * S,ErrorInfoTy & ErrorInfo)12024 bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12025 ErrorInfoTy &ErrorInfo) {
12026 IsFailOnly = true;
12027
12028 auto *Then = S->getThen();
12029 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12030 if (CS->body_empty()) {
12031 ErrorInfo.Error = ErrorTy::NoStmt;
12032 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12033 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12034 return false;
12035 }
12036 if (CS->size() > 1) {
12037 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12038 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12039 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12040 return false;
12041 }
12042 Then = CS->body_front();
12043 }
12044
12045 auto *BO = dyn_cast<BinaryOperator>(Then);
12046 if (!BO) {
12047 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12048 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12049 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12050 return false;
12051 }
12052 if (BO->getOpcode() != BO_Assign) {
12053 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12054 ErrorInfo.ErrorLoc = BO->getExprLoc();
12055 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12056 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12057 return false;
12058 }
12059
12060 X = BO->getLHS();
12061 D = BO->getRHS();
12062
12063 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12064 if (!Cond) {
12065 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12066 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12067 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12068 return false;
12069 }
12070 if (Cond->getOpcode() != BO_EQ) {
12071 ErrorInfo.Error = ErrorTy::NotEQ;
12072 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12073 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12074 return false;
12075 }
12076
12077 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12078 E = Cond->getRHS();
12079 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12080 E = Cond->getLHS();
12081 } else {
12082 ErrorInfo.Error = ErrorTy::InvalidComparison;
12083 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12084 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12085 return false;
12086 }
12087
12088 C = Cond;
12089
12090 if (!S->getElse()) {
12091 ErrorInfo.Error = ErrorTy::NoElse;
12092 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12093 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12094 return false;
12095 }
12096
12097 auto *Else = S->getElse();
12098 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12099 if (CS->body_empty()) {
12100 ErrorInfo.Error = ErrorTy::NoStmt;
12101 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12102 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12103 return false;
12104 }
12105 if (CS->size() > 1) {
12106 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12107 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12108 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12109 return false;
12110 }
12111 Else = CS->body_front();
12112 }
12113
12114 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12115 if (!ElseBO) {
12116 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12117 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12118 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12119 return false;
12120 }
12121 if (ElseBO->getOpcode() != BO_Assign) {
12122 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12123 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12124 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12125 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12126 return false;
12127 }
12128
12129 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12130 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12131 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12132 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12133 ElseBO->getRHS()->getSourceRange();
12134 return false;
12135 }
12136
12137 V = ElseBO->getLHS();
12138
12139 return checkType(ErrorInfo);
12140 }
12141
checkForm45(Stmt * S,ErrorInfoTy & ErrorInfo)12142 bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12143 ErrorInfoTy &ErrorInfo) {
12144 // We don't check here as they should be already done before call this
12145 // function.
12146 auto *CS = cast<CompoundStmt>(S);
12147 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12148 auto *S1 = cast<BinaryOperator>(CS->body_front());
12149 auto *S2 = cast<IfStmt>(CS->body_back());
12150 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12151
12152 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12153 ErrorInfo.Error = ErrorTy::InvalidCondition;
12154 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12155 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12156 return false;
12157 }
12158
12159 R = S1->getLHS();
12160
12161 auto *Then = S2->getThen();
12162 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12163 if (ThenCS->body_empty()) {
12164 ErrorInfo.Error = ErrorTy::NoStmt;
12165 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12166 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12167 return false;
12168 }
12169 if (ThenCS->size() > 1) {
12170 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12171 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12172 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12173 return false;
12174 }
12175 Then = ThenCS->body_front();
12176 }
12177
12178 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12179 if (!ThenBO) {
12180 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12181 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12182 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12183 return false;
12184 }
12185 if (ThenBO->getOpcode() != BO_Assign) {
12186 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12187 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12188 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12189 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12190 return false;
12191 }
12192
12193 X = ThenBO->getLHS();
12194 D = ThenBO->getRHS();
12195
12196 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12197 if (BO->getOpcode() != BO_EQ) {
12198 ErrorInfo.Error = ErrorTy::NotEQ;
12199 ErrorInfo.ErrorLoc = BO->getExprLoc();
12200 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12201 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12202 return false;
12203 }
12204
12205 C = BO;
12206
12207 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12208 E = BO->getRHS();
12209 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12210 E = BO->getLHS();
12211 } else {
12212 ErrorInfo.Error = ErrorTy::InvalidComparison;
12213 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12214 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12215 return false;
12216 }
12217
12218 if (S2->getElse()) {
12219 IsFailOnly = true;
12220
12221 auto *Else = S2->getElse();
12222 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12223 if (ElseCS->body_empty()) {
12224 ErrorInfo.Error = ErrorTy::NoStmt;
12225 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12226 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12227 return false;
12228 }
12229 if (ElseCS->size() > 1) {
12230 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12231 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12232 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12233 return false;
12234 }
12235 Else = ElseCS->body_front();
12236 }
12237
12238 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12239 if (!ElseBO) {
12240 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12241 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12242 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12243 return false;
12244 }
12245 if (ElseBO->getOpcode() != BO_Assign) {
12246 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12247 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12248 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12249 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12250 return false;
12251 }
12252 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12253 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12254 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12255 ErrorInfo.NoteLoc = X->getExprLoc();
12256 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12257 ErrorInfo.NoteRange = X->getSourceRange();
12258 return false;
12259 }
12260
12261 V = ElseBO->getLHS();
12262 }
12263
12264 return checkType(ErrorInfo);
12265 }
12266
checkStmt(Stmt * S,ErrorInfoTy & ErrorInfo)12267 bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12268 ErrorInfoTy &ErrorInfo) {
12269 // if(x == e) { x = d; } else { v = x; }
12270 if (auto *IS = dyn_cast<IfStmt>(S))
12271 return checkForm3(IS, ErrorInfo);
12272
12273 auto *CS = dyn_cast<CompoundStmt>(S);
12274 if (!CS) {
12275 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12276 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12277 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12278 return false;
12279 }
12280 if (CS->body_empty()) {
12281 ErrorInfo.Error = ErrorTy::NoStmt;
12282 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12283 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12284 return false;
12285 }
12286
12287 // { if(x == e) { x = d; } else { v = x; } }
12288 if (CS->size() == 1) {
12289 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12290 if (!IS) {
12291 ErrorInfo.Error = ErrorTy::NotIfStmt;
12292 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12293 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12294 CS->body_front()->getSourceRange();
12295 return false;
12296 }
12297
12298 return checkForm3(IS, ErrorInfo);
12299 } else if (CS->size() == 2) {
12300 auto *S1 = CS->body_front();
12301 auto *S2 = CS->body_back();
12302
12303 Stmt *UpdateStmt = nullptr;
12304 Stmt *CondUpdateStmt = nullptr;
12305 Stmt *CondExprStmt = nullptr;
12306
12307 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12308 // It could be one of the following cases:
12309 // { v = x; cond-update-stmt }
12310 // { v = x; cond-expr-stmt }
12311 // { cond-expr-stmt; v = x; }
12312 // form 45
12313 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12314 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12315 // check if form 45
12316 if (isa<IfStmt>(S2))
12317 return checkForm45(CS, ErrorInfo);
12318 // { cond-expr-stmt; v = x; }
12319 CondExprStmt = S1;
12320 UpdateStmt = S2;
12321 } else {
12322 IsPostfixUpdate = true;
12323 UpdateStmt = S1;
12324 if (isa<IfStmt>(S2)) {
12325 // { v = x; cond-update-stmt }
12326 CondUpdateStmt = S2;
12327 } else {
12328 // { v = x; cond-expr-stmt }
12329 CondExprStmt = S2;
12330 }
12331 }
12332 } else {
12333 // { cond-update-stmt v = x; }
12334 UpdateStmt = S2;
12335 CondUpdateStmt = S1;
12336 }
12337
12338 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12339 auto *IS = dyn_cast<IfStmt>(CUS);
12340 if (!IS) {
12341 ErrorInfo.Error = ErrorTy::NotIfStmt;
12342 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12343 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12344 return false;
12345 }
12346
12347 return checkCondUpdateStmt(IS, ErrorInfo);
12348 };
12349
12350 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12351 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12352 auto *BO = dyn_cast<BinaryOperator>(US);
12353 if (!BO) {
12354 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12355 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12356 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12357 return false;
12358 }
12359 if (BO->getOpcode() != BO_Assign) {
12360 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12361 ErrorInfo.ErrorLoc = BO->getExprLoc();
12362 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12363 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12364 return false;
12365 }
12366 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12367 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12368 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12369 ErrorInfo.NoteLoc = this->X->getExprLoc();
12370 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12371 ErrorInfo.NoteRange = this->X->getSourceRange();
12372 return false;
12373 }
12374
12375 this->V = BO->getLHS();
12376
12377 return true;
12378 };
12379
12380 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12381 return false;
12382 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12383 return false;
12384 if (!CheckUpdateStmt(UpdateStmt))
12385 return false;
12386 } else {
12387 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12388 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12389 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12390 return false;
12391 }
12392
12393 return checkType(ErrorInfo);
12394 }
12395 } // namespace
12396
ActOnOpenMPAtomicDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)12397 StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
12398 Stmt *AStmt,
12399 SourceLocation StartLoc,
12400 SourceLocation EndLoc) {
12401 // Register location of the first atomic directive.
12402 DSAStack->addAtomicDirectiveLoc(StartLoc);
12403 if (!AStmt)
12404 return StmtError();
12405
12406 // 1.2.2 OpenMP Language Terminology
12407 // Structured block - An executable statement with a single entry at the
12408 // top and a single exit at the bottom.
12409 // The point of exit cannot be a branch out of the structured block.
12410 // longjmp() and throw() must not violate the entry/exit criteria.
12411 OpenMPClauseKind AtomicKind = OMPC_unknown;
12412 SourceLocation AtomicKindLoc;
12413 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12414 SourceLocation MemOrderLoc;
12415 bool MutexClauseEncountered = false;
12416 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12417 for (const OMPClause *C : Clauses) {
12418 switch (C->getClauseKind()) {
12419 case OMPC_read:
12420 case OMPC_write:
12421 case OMPC_update:
12422 MutexClauseEncountered = true;
12423 [[fallthrough]];
12424 case OMPC_capture:
12425 case OMPC_compare: {
12426 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12427 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12428 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12429 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12430 << getOpenMPClauseName(AtomicKind);
12431 } else {
12432 AtomicKind = C->getClauseKind();
12433 AtomicKindLoc = C->getBeginLoc();
12434 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12435 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12436 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12437 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12438 << getOpenMPClauseName(AtomicKind);
12439 }
12440 }
12441 break;
12442 }
12443 case OMPC_seq_cst:
12444 case OMPC_acq_rel:
12445 case OMPC_acquire:
12446 case OMPC_release:
12447 case OMPC_relaxed: {
12448 if (MemOrderKind != OMPC_unknown) {
12449 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12450 << getOpenMPDirectiveName(OMPD_atomic) << 0
12451 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12452 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12453 << getOpenMPClauseName(MemOrderKind);
12454 } else {
12455 MemOrderKind = C->getClauseKind();
12456 MemOrderLoc = C->getBeginLoc();
12457 }
12458 break;
12459 }
12460 // The following clauses are allowed, but we don't need to do anything here.
12461 case OMPC_hint:
12462 break;
12463 default:
12464 llvm_unreachable("unknown clause is encountered");
12465 }
12466 }
12467 bool IsCompareCapture = false;
12468 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12469 EncounteredAtomicKinds.contains(OMPC_capture)) {
12470 IsCompareCapture = true;
12471 AtomicKind = OMPC_compare;
12472 }
12473 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12474 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12475 // release.
12476 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12477 // acquire.
12478 // If atomic-clause is update or not present then memory-order-clause must not
12479 // be acq_rel or acquire.
12480 if ((AtomicKind == OMPC_read &&
12481 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12482 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12483 AtomicKind == OMPC_unknown) &&
12484 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12485 SourceLocation Loc = AtomicKindLoc;
12486 if (AtomicKind == OMPC_unknown)
12487 Loc = StartLoc;
12488 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12489 << getOpenMPClauseName(AtomicKind)
12490 << (AtomicKind == OMPC_unknown ? 1 : 0)
12491 << getOpenMPClauseName(MemOrderKind);
12492 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12493 << getOpenMPClauseName(MemOrderKind);
12494 }
12495
12496 Stmt *Body = AStmt;
12497 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12498 Body = EWC->getSubExpr();
12499
12500 Expr *X = nullptr;
12501 Expr *V = nullptr;
12502 Expr *E = nullptr;
12503 Expr *UE = nullptr;
12504 Expr *D = nullptr;
12505 Expr *CE = nullptr;
12506 Expr *R = nullptr;
12507 bool IsXLHSInRHSPart = false;
12508 bool IsPostfixUpdate = false;
12509 bool IsFailOnly = false;
12510 // OpenMP [2.12.6, atomic Construct]
12511 // In the next expressions:
12512 // * x and v (as applicable) are both l-value expressions with scalar type.
12513 // * During the execution of an atomic region, multiple syntactic
12514 // occurrences of x must designate the same storage location.
12515 // * Neither of v and expr (as applicable) may access the storage location
12516 // designated by x.
12517 // * Neither of x and expr (as applicable) may access the storage location
12518 // designated by v.
12519 // * expr is an expression with scalar type.
12520 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12521 // * binop, binop=, ++, and -- are not overloaded operators.
12522 // * The expression x binop expr must be numerically equivalent to x binop
12523 // (expr). This requirement is satisfied if the operators in expr have
12524 // precedence greater than binop, or by using parentheses around expr or
12525 // subexpressions of expr.
12526 // * The expression expr binop x must be numerically equivalent to (expr)
12527 // binop x. This requirement is satisfied if the operators in expr have
12528 // precedence equal to or greater than binop, or by using parentheses around
12529 // expr or subexpressions of expr.
12530 // * For forms that allow multiple occurrences of x, the number of times
12531 // that x is evaluated is unspecified.
12532 if (AtomicKind == OMPC_read) {
12533 enum {
12534 NotAnExpression,
12535 NotAnAssignmentOp,
12536 NotAScalarType,
12537 NotAnLValue,
12538 NoError
12539 } ErrorFound = NoError;
12540 SourceLocation ErrorLoc, NoteLoc;
12541 SourceRange ErrorRange, NoteRange;
12542 // If clause is read:
12543 // v = x;
12544 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12545 const auto *AtomicBinOp =
12546 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12547 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12548 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12549 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12550 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12551 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12552 if (!X->isLValue() || !V->isLValue()) {
12553 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12554 ErrorFound = NotAnLValue;
12555 ErrorLoc = AtomicBinOp->getExprLoc();
12556 ErrorRange = AtomicBinOp->getSourceRange();
12557 NoteLoc = NotLValueExpr->getExprLoc();
12558 NoteRange = NotLValueExpr->getSourceRange();
12559 }
12560 } else if (!X->isInstantiationDependent() ||
12561 !V->isInstantiationDependent()) {
12562 const Expr *NotScalarExpr =
12563 (X->isInstantiationDependent() || X->getType()->isScalarType())
12564 ? V
12565 : X;
12566 ErrorFound = NotAScalarType;
12567 ErrorLoc = AtomicBinOp->getExprLoc();
12568 ErrorRange = AtomicBinOp->getSourceRange();
12569 NoteLoc = NotScalarExpr->getExprLoc();
12570 NoteRange = NotScalarExpr->getSourceRange();
12571 }
12572 } else if (!AtomicBody->isInstantiationDependent()) {
12573 ErrorFound = NotAnAssignmentOp;
12574 ErrorLoc = AtomicBody->getExprLoc();
12575 ErrorRange = AtomicBody->getSourceRange();
12576 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12577 : AtomicBody->getExprLoc();
12578 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12579 : AtomicBody->getSourceRange();
12580 }
12581 } else {
12582 ErrorFound = NotAnExpression;
12583 NoteLoc = ErrorLoc = Body->getBeginLoc();
12584 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12585 }
12586 if (ErrorFound != NoError) {
12587 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12588 << ErrorRange;
12589 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12590 << ErrorFound << NoteRange;
12591 return StmtError();
12592 }
12593 if (CurContext->isDependentContext())
12594 V = X = nullptr;
12595 } else if (AtomicKind == OMPC_write) {
12596 enum {
12597 NotAnExpression,
12598 NotAnAssignmentOp,
12599 NotAScalarType,
12600 NotAnLValue,
12601 NoError
12602 } ErrorFound = NoError;
12603 SourceLocation ErrorLoc, NoteLoc;
12604 SourceRange ErrorRange, NoteRange;
12605 // If clause is write:
12606 // x = expr;
12607 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12608 const auto *AtomicBinOp =
12609 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12610 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12611 X = AtomicBinOp->getLHS();
12612 E = AtomicBinOp->getRHS();
12613 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12614 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
12615 if (!X->isLValue()) {
12616 ErrorFound = NotAnLValue;
12617 ErrorLoc = AtomicBinOp->getExprLoc();
12618 ErrorRange = AtomicBinOp->getSourceRange();
12619 NoteLoc = X->getExprLoc();
12620 NoteRange = X->getSourceRange();
12621 }
12622 } else if (!X->isInstantiationDependent() ||
12623 !E->isInstantiationDependent()) {
12624 const Expr *NotScalarExpr =
12625 (X->isInstantiationDependent() || X->getType()->isScalarType())
12626 ? E
12627 : X;
12628 ErrorFound = NotAScalarType;
12629 ErrorLoc = AtomicBinOp->getExprLoc();
12630 ErrorRange = AtomicBinOp->getSourceRange();
12631 NoteLoc = NotScalarExpr->getExprLoc();
12632 NoteRange = NotScalarExpr->getSourceRange();
12633 }
12634 } else if (!AtomicBody->isInstantiationDependent()) {
12635 ErrorFound = NotAnAssignmentOp;
12636 ErrorLoc = AtomicBody->getExprLoc();
12637 ErrorRange = AtomicBody->getSourceRange();
12638 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12639 : AtomicBody->getExprLoc();
12640 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12641 : AtomicBody->getSourceRange();
12642 }
12643 } else {
12644 ErrorFound = NotAnExpression;
12645 NoteLoc = ErrorLoc = Body->getBeginLoc();
12646 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12647 }
12648 if (ErrorFound != NoError) {
12649 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12650 << ErrorRange;
12651 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12652 << ErrorFound << NoteRange;
12653 return StmtError();
12654 }
12655 if (CurContext->isDependentContext())
12656 E = X = nullptr;
12657 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12658 // If clause is update:
12659 // x++;
12660 // x--;
12661 // ++x;
12662 // --x;
12663 // x binop= expr;
12664 // x = x binop expr;
12665 // x = expr binop x;
12666 OpenMPAtomicUpdateChecker Checker(*this);
12667 if (Checker.checkStatement(
12668 Body,
12669 (AtomicKind == OMPC_update)
12670 ? diag::err_omp_atomic_update_not_expression_statement
12671 : diag::err_omp_atomic_not_expression_statement,
12672 diag::note_omp_atomic_update))
12673 return StmtError();
12674 if (!CurContext->isDependentContext()) {
12675 E = Checker.getExpr();
12676 X = Checker.getX();
12677 UE = Checker.getUpdateExpr();
12678 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12679 }
12680 } else if (AtomicKind == OMPC_capture) {
12681 enum {
12682 NotAnAssignmentOp,
12683 NotACompoundStatement,
12684 NotTwoSubstatements,
12685 NotASpecificExpression,
12686 NoError
12687 } ErrorFound = NoError;
12688 SourceLocation ErrorLoc, NoteLoc;
12689 SourceRange ErrorRange, NoteRange;
12690 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12691 // If clause is a capture:
12692 // v = x++;
12693 // v = x--;
12694 // v = ++x;
12695 // v = --x;
12696 // v = x binop= expr;
12697 // v = x = x binop expr;
12698 // v = x = expr binop x;
12699 const auto *AtomicBinOp =
12700 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12701 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12702 V = AtomicBinOp->getLHS();
12703 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12704 OpenMPAtomicUpdateChecker Checker(*this);
12705 if (Checker.checkStatement(
12706 Body, diag::err_omp_atomic_capture_not_expression_statement,
12707 diag::note_omp_atomic_update))
12708 return StmtError();
12709 E = Checker.getExpr();
12710 X = Checker.getX();
12711 UE = Checker.getUpdateExpr();
12712 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12713 IsPostfixUpdate = Checker.isPostfixUpdate();
12714 } else if (!AtomicBody->isInstantiationDependent()) {
12715 ErrorLoc = AtomicBody->getExprLoc();
12716 ErrorRange = AtomicBody->getSourceRange();
12717 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12718 : AtomicBody->getExprLoc();
12719 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12720 : AtomicBody->getSourceRange();
12721 ErrorFound = NotAnAssignmentOp;
12722 }
12723 if (ErrorFound != NoError) {
12724 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12725 << ErrorRange;
12726 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12727 return StmtError();
12728 }
12729 if (CurContext->isDependentContext())
12730 UE = V = E = X = nullptr;
12731 } else {
12732 // If clause is a capture:
12733 // { v = x; x = expr; }
12734 // { v = x; x++; }
12735 // { v = x; x--; }
12736 // { v = x; ++x; }
12737 // { v = x; --x; }
12738 // { v = x; x binop= expr; }
12739 // { v = x; x = x binop expr; }
12740 // { v = x; x = expr binop x; }
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 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
12749 // Check that this is { expr1; expr2; }
12750 if (CS->size() == 2) {
12751 Stmt *First = CS->body_front();
12752 Stmt *Second = CS->body_back();
12753 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
12754 First = EWC->getSubExpr()->IgnoreParenImpCasts();
12755 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
12756 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
12757 // Need to find what subexpression is 'v' and what is 'x'.
12758 OpenMPAtomicUpdateChecker Checker(*this);
12759 bool IsUpdateExprFound = !Checker.checkStatement(Second);
12760 BinaryOperator *BinOp = nullptr;
12761 if (IsUpdateExprFound) {
12762 BinOp = dyn_cast<BinaryOperator>(First);
12763 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12764 }
12765 if (IsUpdateExprFound && !CurContext->isDependentContext()) {
12766 // { v = x; x++; }
12767 // { v = x; x--; }
12768 // { v = x; ++x; }
12769 // { v = x; --x; }
12770 // { v = x; x binop= expr; }
12771 // { v = x; x = x binop expr; }
12772 // { v = x; x = expr binop x; }
12773 // Check that the first expression has form v = x.
12774 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12775 llvm::FoldingSetNodeID XId, PossibleXId;
12776 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12777 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12778 IsUpdateExprFound = XId == PossibleXId;
12779 if (IsUpdateExprFound) {
12780 V = BinOp->getLHS();
12781 X = Checker.getX();
12782 E = Checker.getExpr();
12783 UE = Checker.getUpdateExpr();
12784 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12785 IsPostfixUpdate = true;
12786 }
12787 }
12788 if (!IsUpdateExprFound) {
12789 IsUpdateExprFound = !Checker.checkStatement(First);
12790 BinOp = nullptr;
12791 if (IsUpdateExprFound) {
12792 BinOp = dyn_cast<BinaryOperator>(Second);
12793 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12794 }
12795 if (IsUpdateExprFound && !CurContext->isDependentContext()) {
12796 // { x++; v = x; }
12797 // { x--; v = x; }
12798 // { ++x; v = x; }
12799 // { --x; v = x; }
12800 // { x binop= expr; v = x; }
12801 // { x = x binop expr; v = x; }
12802 // { x = expr binop x; v = x; }
12803 // Check that the second expression has form v = x.
12804 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12805 llvm::FoldingSetNodeID XId, PossibleXId;
12806 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12807 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12808 IsUpdateExprFound = XId == PossibleXId;
12809 if (IsUpdateExprFound) {
12810 V = BinOp->getLHS();
12811 X = Checker.getX();
12812 E = Checker.getExpr();
12813 UE = Checker.getUpdateExpr();
12814 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12815 IsPostfixUpdate = false;
12816 }
12817 }
12818 }
12819 if (!IsUpdateExprFound) {
12820 // { v = x; x = expr; }
12821 auto *FirstExpr = dyn_cast<Expr>(First);
12822 auto *SecondExpr = dyn_cast<Expr>(Second);
12823 if (!FirstExpr || !SecondExpr ||
12824 !(FirstExpr->isInstantiationDependent() ||
12825 SecondExpr->isInstantiationDependent())) {
12826 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
12827 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
12828 ErrorFound = NotAnAssignmentOp;
12829 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
12830 : First->getBeginLoc();
12831 NoteRange = ErrorRange = FirstBinOp
12832 ? FirstBinOp->getSourceRange()
12833 : SourceRange(ErrorLoc, ErrorLoc);
12834 } else {
12835 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
12836 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
12837 ErrorFound = NotAnAssignmentOp;
12838 NoteLoc = ErrorLoc = SecondBinOp
12839 ? SecondBinOp->getOperatorLoc()
12840 : Second->getBeginLoc();
12841 NoteRange = ErrorRange =
12842 SecondBinOp ? SecondBinOp->getSourceRange()
12843 : SourceRange(ErrorLoc, ErrorLoc);
12844 } else {
12845 Expr *PossibleXRHSInFirst =
12846 FirstBinOp->getRHS()->IgnoreParenImpCasts();
12847 Expr *PossibleXLHSInSecond =
12848 SecondBinOp->getLHS()->IgnoreParenImpCasts();
12849 llvm::FoldingSetNodeID X1Id, X2Id;
12850 PossibleXRHSInFirst->Profile(X1Id, Context,
12851 /*Canonical=*/true);
12852 PossibleXLHSInSecond->Profile(X2Id, Context,
12853 /*Canonical=*/true);
12854 IsUpdateExprFound = X1Id == X2Id;
12855 if (IsUpdateExprFound) {
12856 V = FirstBinOp->getLHS();
12857 X = SecondBinOp->getLHS();
12858 E = SecondBinOp->getRHS();
12859 UE = nullptr;
12860 IsXLHSInRHSPart = false;
12861 IsPostfixUpdate = true;
12862 } else {
12863 ErrorFound = NotASpecificExpression;
12864 ErrorLoc = FirstBinOp->getExprLoc();
12865 ErrorRange = FirstBinOp->getSourceRange();
12866 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
12867 NoteRange = SecondBinOp->getRHS()->getSourceRange();
12868 }
12869 }
12870 }
12871 }
12872 }
12873 } else {
12874 NoteLoc = ErrorLoc = Body->getBeginLoc();
12875 NoteRange = ErrorRange =
12876 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12877 ErrorFound = NotTwoSubstatements;
12878 }
12879 } else {
12880 NoteLoc = ErrorLoc = Body->getBeginLoc();
12881 NoteRange = ErrorRange =
12882 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12883 ErrorFound = NotACompoundStatement;
12884 }
12885 }
12886 if (ErrorFound != NoError) {
12887 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
12888 << ErrorRange;
12889 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12890 return StmtError();
12891 }
12892 if (CurContext->isDependentContext())
12893 UE = V = E = X = nullptr;
12894 } else if (AtomicKind == OMPC_compare) {
12895 if (IsCompareCapture) {
12896 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
12897 OpenMPAtomicCompareCaptureChecker Checker(*this);
12898 if (!Checker.checkStmt(Body, ErrorInfo)) {
12899 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
12900 << ErrorInfo.ErrorRange;
12901 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12902 << ErrorInfo.Error << ErrorInfo.NoteRange;
12903 return StmtError();
12904 }
12905 X = Checker.getX();
12906 E = Checker.getE();
12907 D = Checker.getD();
12908 CE = Checker.getCond();
12909 V = Checker.getV();
12910 R = Checker.getR();
12911 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12912 IsXLHSInRHSPart = Checker.isXBinopExpr();
12913 IsFailOnly = Checker.isFailOnly();
12914 IsPostfixUpdate = Checker.isPostfixUpdate();
12915 } else {
12916 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
12917 OpenMPAtomicCompareChecker Checker(*this);
12918 if (!Checker.checkStmt(Body, ErrorInfo)) {
12919 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
12920 << ErrorInfo.ErrorRange;
12921 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12922 << ErrorInfo.Error << ErrorInfo.NoteRange;
12923 return StmtError();
12924 }
12925 X = Checker.getX();
12926 E = Checker.getE();
12927 D = Checker.getD();
12928 CE = Checker.getCond();
12929 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12930 IsXLHSInRHSPart = Checker.isXBinopExpr();
12931 }
12932 }
12933
12934 setFunctionHasBranchProtectedScope();
12935
12936 return OMPAtomicDirective::Create(
12937 Context, StartLoc, EndLoc, Clauses, AStmt,
12938 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
12939 }
12940
ActOnOpenMPTargetDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)12941 StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
12942 Stmt *AStmt,
12943 SourceLocation StartLoc,
12944 SourceLocation EndLoc) {
12945 if (!AStmt)
12946 return StmtError();
12947
12948 auto *CS = cast<CapturedStmt>(AStmt);
12949 // 1.2.2 OpenMP Language Terminology
12950 // Structured block - An executable statement with a single entry at the
12951 // top and a single exit at the bottom.
12952 // The point of exit cannot be a branch out of the structured block.
12953 // longjmp() and throw() must not violate the entry/exit criteria.
12954 CS->getCapturedDecl()->setNothrow();
12955 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target);
12956 ThisCaptureLevel > 1; --ThisCaptureLevel) {
12957 CS = cast<CapturedStmt>(CS->getCapturedStmt());
12958 // 1.2.2 OpenMP Language Terminology
12959 // Structured block - An executable statement with a single entry at the
12960 // top and a single exit at the bottom.
12961 // The point of exit cannot be a branch out of the structured block.
12962 // longjmp() and throw() must not violate the entry/exit criteria.
12963 CS->getCapturedDecl()->setNothrow();
12964 }
12965
12966 // OpenMP [2.16, Nesting of Regions]
12967 // If specified, a teams construct must be contained within a target
12968 // construct. That target construct must contain no statements or directives
12969 // outside of the teams construct.
12970 if (DSAStack->hasInnerTeamsRegion()) {
12971 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
12972 bool OMPTeamsFound = true;
12973 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
12974 auto I = CS->body_begin();
12975 while (I != CS->body_end()) {
12976 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
12977 if (!OED || !isOpenMPTeamsDirective(OED->getDirectiveKind()) ||
12978 OMPTeamsFound) {
12979
12980 OMPTeamsFound = false;
12981 break;
12982 }
12983 ++I;
12984 }
12985 assert(I != CS->body_end() && "Not found statement");
12986 S = *I;
12987 } else {
12988 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
12989 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
12990 }
12991 if (!OMPTeamsFound) {
12992 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
12993 Diag(DSAStack->getInnerTeamsRegionLoc(),
12994 diag::note_omp_nested_teams_construct_here);
12995 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
12996 << isa<OMPExecutableDirective>(S);
12997 return StmtError();
12998 }
12999 }
13000
13001 setFunctionHasBranchProtectedScope();
13002
13003 return OMPTargetDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
13004 }
13005
13006 StmtResult
ActOnOpenMPTargetParallelDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)13007 Sema::ActOnOpenMPTargetParallelDirective(ArrayRef<OMPClause *> Clauses,
13008 Stmt *AStmt, SourceLocation StartLoc,
13009 SourceLocation EndLoc) {
13010 if (!AStmt)
13011 return StmtError();
13012
13013 auto *CS = cast<CapturedStmt>(AStmt);
13014 // 1.2.2 OpenMP Language Terminology
13015 // Structured block - An executable statement with a single entry at the
13016 // top and a single exit at the bottom.
13017 // The point of exit cannot be a branch out of the structured block.
13018 // longjmp() and throw() must not violate the entry/exit criteria.
13019 CS->getCapturedDecl()->setNothrow();
13020 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel);
13021 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13022 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13023 // 1.2.2 OpenMP Language Terminology
13024 // Structured block - An executable statement with a single entry at the
13025 // top and a single exit at the bottom.
13026 // The point of exit cannot be a branch out of the structured block.
13027 // longjmp() and throw() must not violate the entry/exit criteria.
13028 CS->getCapturedDecl()->setNothrow();
13029 }
13030
13031 setFunctionHasBranchProtectedScope();
13032
13033 return OMPTargetParallelDirective::Create(
13034 Context, StartLoc, EndLoc, Clauses, AStmt,
13035 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13036 }
13037
ActOnOpenMPTargetParallelForDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13038 StmtResult Sema::ActOnOpenMPTargetParallelForDirective(
13039 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13040 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13041 if (!AStmt)
13042 return StmtError();
13043
13044 auto *CS = cast<CapturedStmt>(AStmt);
13045 // 1.2.2 OpenMP Language Terminology
13046 // Structured block - An executable statement with a single entry at the
13047 // top and a single exit at the bottom.
13048 // The point of exit cannot be a branch out of the structured block.
13049 // longjmp() and throw() must not violate the entry/exit criteria.
13050 CS->getCapturedDecl()->setNothrow();
13051 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for);
13052 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13053 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13054 // 1.2.2 OpenMP Language Terminology
13055 // Structured block - An executable statement with a single entry at the
13056 // top and a single exit at the bottom.
13057 // The point of exit cannot be a branch out of the structured block.
13058 // longjmp() and throw() must not violate the entry/exit criteria.
13059 CS->getCapturedDecl()->setNothrow();
13060 }
13061
13062 OMPLoopBasedDirective::HelperExprs B;
13063 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13064 // define the nested loops number.
13065 unsigned NestedLoopCount =
13066 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13067 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
13068 VarsWithImplicitDSA, B);
13069 if (NestedLoopCount == 0)
13070 return StmtError();
13071
13072 assert((CurContext->isDependentContext() || B.builtAll()) &&
13073 "omp target parallel for loop exprs were not built");
13074
13075 if (!CurContext->isDependentContext()) {
13076 // Finalize the clauses that need pre-built expressions for CodeGen.
13077 for (OMPClause *C : Clauses) {
13078 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13079 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13080 B.NumIterations, *this, CurScope,
13081 DSAStack))
13082 return StmtError();
13083 }
13084 }
13085
13086 setFunctionHasBranchProtectedScope();
13087 return OMPTargetParallelForDirective::Create(
13088 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13089 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13090 }
13091
13092 /// Check for existence of a map clause in the list of clauses.
hasClauses(ArrayRef<OMPClause * > Clauses,const OpenMPClauseKind K)13093 static bool hasClauses(ArrayRef<OMPClause *> Clauses,
13094 const OpenMPClauseKind K) {
13095 return llvm::any_of(
13096 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13097 }
13098
13099 template <typename... Params>
hasClauses(ArrayRef<OMPClause * > Clauses,const OpenMPClauseKind K,const Params...ClauseTypes)13100 static bool hasClauses(ArrayRef<OMPClause *> Clauses, const OpenMPClauseKind K,
13101 const Params... ClauseTypes) {
13102 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13103 }
13104
13105 /// Check if the variables in the mapping clause are externally visible.
isClauseMappable(ArrayRef<OMPClause * > Clauses)13106 static bool isClauseMappable(ArrayRef<OMPClause *> Clauses) {
13107 for (const OMPClause *C : Clauses) {
13108 if (auto *TC = dyn_cast<OMPToClause>(C))
13109 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13110 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13111 (VD->isExternallyVisible() &&
13112 VD->getVisibility() != HiddenVisibility);
13113 });
13114 else if (auto *FC = dyn_cast<OMPFromClause>(C))
13115 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13116 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13117 (VD->isExternallyVisible() &&
13118 VD->getVisibility() != HiddenVisibility);
13119 });
13120 }
13121
13122 return true;
13123 }
13124
ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)13125 StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
13126 Stmt *AStmt,
13127 SourceLocation StartLoc,
13128 SourceLocation EndLoc) {
13129 if (!AStmt)
13130 return StmtError();
13131
13132 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13133
13134 // OpenMP [2.12.2, target data Construct, Restrictions]
13135 // At least one map, use_device_addr or use_device_ptr clause must appear on
13136 // the directive.
13137 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13138 (LangOpts.OpenMP < 50 || !hasClauses(Clauses, OMPC_use_device_addr))) {
13139 StringRef Expected;
13140 if (LangOpts.OpenMP < 50)
13141 Expected = "'map' or 'use_device_ptr'";
13142 else
13143 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13144 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13145 << Expected << getOpenMPDirectiveName(OMPD_target_data);
13146 return StmtError();
13147 }
13148
13149 setFunctionHasBranchProtectedScope();
13150
13151 return OMPTargetDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13152 AStmt);
13153 }
13154
13155 StmtResult
ActOnOpenMPTargetEnterDataDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc,Stmt * AStmt)13156 Sema::ActOnOpenMPTargetEnterDataDirective(ArrayRef<OMPClause *> Clauses,
13157 SourceLocation StartLoc,
13158 SourceLocation EndLoc, Stmt *AStmt) {
13159 if (!AStmt)
13160 return StmtError();
13161
13162 auto *CS = cast<CapturedStmt>(AStmt);
13163 // 1.2.2 OpenMP Language Terminology
13164 // Structured block - An executable statement with a single entry at the
13165 // top and a single exit at the bottom.
13166 // The point of exit cannot be a branch out of the structured block.
13167 // longjmp() and throw() must not violate the entry/exit criteria.
13168 CS->getCapturedDecl()->setNothrow();
13169 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_enter_data);
13170 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13171 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13172 // 1.2.2 OpenMP Language Terminology
13173 // Structured block - An executable statement with a single entry at the
13174 // top and a single exit at the bottom.
13175 // The point of exit cannot be a branch out of the structured block.
13176 // longjmp() and throw() must not violate the entry/exit criteria.
13177 CS->getCapturedDecl()->setNothrow();
13178 }
13179
13180 // OpenMP [2.10.2, Restrictions, p. 99]
13181 // At least one map clause must appear on the directive.
13182 if (!hasClauses(Clauses, OMPC_map)) {
13183 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13184 << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
13185 return StmtError();
13186 }
13187
13188 return OMPTargetEnterDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13189 AStmt);
13190 }
13191
13192 StmtResult
ActOnOpenMPTargetExitDataDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc,Stmt * AStmt)13193 Sema::ActOnOpenMPTargetExitDataDirective(ArrayRef<OMPClause *> Clauses,
13194 SourceLocation StartLoc,
13195 SourceLocation EndLoc, Stmt *AStmt) {
13196 if (!AStmt)
13197 return StmtError();
13198
13199 auto *CS = cast<CapturedStmt>(AStmt);
13200 // 1.2.2 OpenMP Language Terminology
13201 // Structured block - An executable statement with a single entry at the
13202 // top and a single exit at the bottom.
13203 // The point of exit cannot be a branch out of the structured block.
13204 // longjmp() and throw() must not violate the entry/exit criteria.
13205 CS->getCapturedDecl()->setNothrow();
13206 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_exit_data);
13207 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13208 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13209 // 1.2.2 OpenMP Language Terminology
13210 // Structured block - An executable statement with a single entry at the
13211 // top and a single exit at the bottom.
13212 // The point of exit cannot be a branch out of the structured block.
13213 // longjmp() and throw() must not violate the entry/exit criteria.
13214 CS->getCapturedDecl()->setNothrow();
13215 }
13216
13217 // OpenMP [2.10.3, Restrictions, p. 102]
13218 // At least one map clause must appear on the directive.
13219 if (!hasClauses(Clauses, OMPC_map)) {
13220 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13221 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
13222 return StmtError();
13223 }
13224
13225 return OMPTargetExitDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13226 AStmt);
13227 }
13228
ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc,Stmt * AStmt)13229 StmtResult Sema::ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause *> Clauses,
13230 SourceLocation StartLoc,
13231 SourceLocation EndLoc,
13232 Stmt *AStmt) {
13233 if (!AStmt)
13234 return StmtError();
13235
13236 auto *CS = cast<CapturedStmt>(AStmt);
13237 // 1.2.2 OpenMP Language Terminology
13238 // Structured block - An executable statement with a single entry at the
13239 // top and a single exit at the bottom.
13240 // The point of exit cannot be a branch out of the structured block.
13241 // longjmp() and throw() must not violate the entry/exit criteria.
13242 CS->getCapturedDecl()->setNothrow();
13243 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_update);
13244 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13245 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13246 // 1.2.2 OpenMP Language Terminology
13247 // Structured block - An executable statement with a single entry at the
13248 // top and a single exit at the bottom.
13249 // The point of exit cannot be a branch out of the structured block.
13250 // longjmp() and throw() must not violate the entry/exit criteria.
13251 CS->getCapturedDecl()->setNothrow();
13252 }
13253
13254 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13255 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13256 return StmtError();
13257 }
13258
13259 if (!isClauseMappable(Clauses)) {
13260 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13261 return StmtError();
13262 }
13263
13264 return OMPTargetUpdateDirective::Create(Context, StartLoc, EndLoc, Clauses,
13265 AStmt);
13266 }
13267
ActOnOpenMPTeamsDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)13268 StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
13269 Stmt *AStmt, SourceLocation StartLoc,
13270 SourceLocation EndLoc) {
13271 if (!AStmt)
13272 return StmtError();
13273
13274 auto *CS = cast<CapturedStmt>(AStmt);
13275 // 1.2.2 OpenMP Language Terminology
13276 // Structured block - An executable statement with a single entry at the
13277 // top and a single exit at the bottom.
13278 // The point of exit cannot be a branch out of the structured block.
13279 // longjmp() and throw() must not violate the entry/exit criteria.
13280 CS->getCapturedDecl()->setNothrow();
13281
13282 setFunctionHasBranchProtectedScope();
13283
13284 DSAStack->setParentTeamsRegionLoc(StartLoc);
13285
13286 return OMPTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
13287 }
13288
13289 StmtResult
ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc,SourceLocation EndLoc,OpenMPDirectiveKind CancelRegion)13290 Sema::ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc,
13291 SourceLocation EndLoc,
13292 OpenMPDirectiveKind CancelRegion) {
13293 if (DSAStack->isParentNowaitRegion()) {
13294 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13295 return StmtError();
13296 }
13297 if (DSAStack->isParentOrderedRegion()) {
13298 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13299 return StmtError();
13300 }
13301 return OMPCancellationPointDirective::Create(Context, StartLoc, EndLoc,
13302 CancelRegion);
13303 }
13304
ActOnOpenMPCancelDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc,OpenMPDirectiveKind CancelRegion)13305 StmtResult Sema::ActOnOpenMPCancelDirective(ArrayRef<OMPClause *> Clauses,
13306 SourceLocation StartLoc,
13307 SourceLocation EndLoc,
13308 OpenMPDirectiveKind CancelRegion) {
13309 if (DSAStack->isParentNowaitRegion()) {
13310 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13311 return StmtError();
13312 }
13313 if (DSAStack->isParentOrderedRegion()) {
13314 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13315 return StmtError();
13316 }
13317 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13318 return OMPCancelDirective::Create(Context, StartLoc, EndLoc, Clauses,
13319 CancelRegion);
13320 }
13321
checkReductionClauseWithNogroup(Sema & S,ArrayRef<OMPClause * > Clauses)13322 static bool checkReductionClauseWithNogroup(Sema &S,
13323 ArrayRef<OMPClause *> Clauses) {
13324 const OMPClause *ReductionClause = nullptr;
13325 const OMPClause *NogroupClause = nullptr;
13326 for (const OMPClause *C : Clauses) {
13327 if (C->getClauseKind() == OMPC_reduction) {
13328 ReductionClause = C;
13329 if (NogroupClause)
13330 break;
13331 continue;
13332 }
13333 if (C->getClauseKind() == OMPC_nogroup) {
13334 NogroupClause = C;
13335 if (ReductionClause)
13336 break;
13337 continue;
13338 }
13339 }
13340 if (ReductionClause && NogroupClause) {
13341 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13342 << SourceRange(NogroupClause->getBeginLoc(),
13343 NogroupClause->getEndLoc());
13344 return true;
13345 }
13346 return false;
13347 }
13348
ActOnOpenMPTaskLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13349 StmtResult Sema::ActOnOpenMPTaskLoopDirective(
13350 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13351 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13352 if (!AStmt)
13353 return StmtError();
13354
13355 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13356 OMPLoopBasedDirective::HelperExprs B;
13357 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13358 // define the nested loops number.
13359 unsigned NestedLoopCount =
13360 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13361 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13362 VarsWithImplicitDSA, B);
13363 if (NestedLoopCount == 0)
13364 return StmtError();
13365
13366 assert((CurContext->isDependentContext() || B.builtAll()) &&
13367 "omp for loop exprs were not built");
13368
13369 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13370 // The grainsize clause and num_tasks clause are mutually exclusive and may
13371 // not appear on the same taskloop directive.
13372 if (checkMutuallyExclusiveClauses(*this, Clauses,
13373 {OMPC_grainsize, OMPC_num_tasks}))
13374 return StmtError();
13375 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13376 // If a reduction clause is present on the taskloop directive, the nogroup
13377 // clause must not be specified.
13378 if (checkReductionClauseWithNogroup(*this, Clauses))
13379 return StmtError();
13380
13381 setFunctionHasBranchProtectedScope();
13382 return OMPTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13383 NestedLoopCount, Clauses, AStmt, B,
13384 DSAStack->isCancelRegion());
13385 }
13386
ActOnOpenMPTaskLoopSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13387 StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective(
13388 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13389 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13390 if (!AStmt)
13391 return StmtError();
13392
13393 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13394 OMPLoopBasedDirective::HelperExprs B;
13395 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13396 // define the nested loops number.
13397 unsigned NestedLoopCount =
13398 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13399 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13400 VarsWithImplicitDSA, B);
13401 if (NestedLoopCount == 0)
13402 return StmtError();
13403
13404 assert((CurContext->isDependentContext() || B.builtAll()) &&
13405 "omp for loop exprs were not built");
13406
13407 if (!CurContext->isDependentContext()) {
13408 // Finalize the clauses that need pre-built expressions for CodeGen.
13409 for (OMPClause *C : Clauses) {
13410 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13411 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13412 B.NumIterations, *this, CurScope,
13413 DSAStack))
13414 return StmtError();
13415 }
13416 }
13417
13418 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13419 // The grainsize clause and num_tasks clause are mutually exclusive and may
13420 // not appear on the same taskloop directive.
13421 if (checkMutuallyExclusiveClauses(*this, Clauses,
13422 {OMPC_grainsize, OMPC_num_tasks}))
13423 return StmtError();
13424 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13425 // If a reduction clause is present on the taskloop directive, the nogroup
13426 // clause must not be specified.
13427 if (checkReductionClauseWithNogroup(*this, Clauses))
13428 return StmtError();
13429 if (checkSimdlenSafelenSpecified(*this, Clauses))
13430 return StmtError();
13431
13432 setFunctionHasBranchProtectedScope();
13433 return OMPTaskLoopSimdDirective::Create(Context, StartLoc, EndLoc,
13434 NestedLoopCount, Clauses, AStmt, B);
13435 }
13436
ActOnOpenMPMasterTaskLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13437 StmtResult Sema::ActOnOpenMPMasterTaskLoopDirective(
13438 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13439 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13440 if (!AStmt)
13441 return StmtError();
13442
13443 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13444 OMPLoopBasedDirective::HelperExprs B;
13445 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13446 // define the nested loops number.
13447 unsigned NestedLoopCount =
13448 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13449 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13450 VarsWithImplicitDSA, B);
13451 if (NestedLoopCount == 0)
13452 return StmtError();
13453
13454 assert((CurContext->isDependentContext() || B.builtAll()) &&
13455 "omp for loop exprs were not built");
13456
13457 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13458 // The grainsize clause and num_tasks clause are mutually exclusive and may
13459 // not appear on the same taskloop directive.
13460 if (checkMutuallyExclusiveClauses(*this, Clauses,
13461 {OMPC_grainsize, OMPC_num_tasks}))
13462 return StmtError();
13463 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13464 // If a reduction clause is present on the taskloop directive, the nogroup
13465 // clause must not be specified.
13466 if (checkReductionClauseWithNogroup(*this, Clauses))
13467 return StmtError();
13468
13469 setFunctionHasBranchProtectedScope();
13470 return OMPMasterTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13471 NestedLoopCount, Clauses, AStmt, B,
13472 DSAStack->isCancelRegion());
13473 }
13474
ActOnOpenMPMaskedTaskLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13475 StmtResult Sema::ActOnOpenMPMaskedTaskLoopDirective(
13476 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13477 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13478 if (!AStmt)
13479 return StmtError();
13480
13481 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13482 OMPLoopBasedDirective::HelperExprs B;
13483 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13484 // define the nested loops number.
13485 unsigned NestedLoopCount =
13486 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13487 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13488 VarsWithImplicitDSA, B);
13489 if (NestedLoopCount == 0)
13490 return StmtError();
13491
13492 assert((CurContext->isDependentContext() || B.builtAll()) &&
13493 "omp for loop exprs were not built");
13494
13495 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13496 // The grainsize clause and num_tasks clause are mutually exclusive and may
13497 // not appear on the same taskloop directive.
13498 if (checkMutuallyExclusiveClauses(*this, Clauses,
13499 {OMPC_grainsize, OMPC_num_tasks}))
13500 return StmtError();
13501 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13502 // If a reduction clause is present on the taskloop directive, the nogroup
13503 // clause must not be specified.
13504 if (checkReductionClauseWithNogroup(*this, Clauses))
13505 return StmtError();
13506
13507 setFunctionHasBranchProtectedScope();
13508 return OMPMaskedTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13509 NestedLoopCount, Clauses, AStmt, B,
13510 DSAStack->isCancelRegion());
13511 }
13512
ActOnOpenMPMasterTaskLoopSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13513 StmtResult Sema::ActOnOpenMPMasterTaskLoopSimdDirective(
13514 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13515 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13516 if (!AStmt)
13517 return StmtError();
13518
13519 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
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 =
13524 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13525 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13526 VarsWithImplicitDSA, B);
13527 if (NestedLoopCount == 0)
13528 return StmtError();
13529
13530 assert((CurContext->isDependentContext() || B.builtAll()) &&
13531 "omp for loop exprs were not built");
13532
13533 if (!CurContext->isDependentContext()) {
13534 // Finalize the clauses that need pre-built expressions for CodeGen.
13535 for (OMPClause *C : Clauses) {
13536 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13537 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13538 B.NumIterations, *this, CurScope,
13539 DSAStack))
13540 return StmtError();
13541 }
13542 }
13543
13544 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13545 // The grainsize clause and num_tasks clause are mutually exclusive and may
13546 // not appear on the same taskloop directive.
13547 if (checkMutuallyExclusiveClauses(*this, Clauses,
13548 {OMPC_grainsize, OMPC_num_tasks}))
13549 return StmtError();
13550 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13551 // If a reduction clause is present on the taskloop directive, the nogroup
13552 // clause must not be specified.
13553 if (checkReductionClauseWithNogroup(*this, Clauses))
13554 return StmtError();
13555 if (checkSimdlenSafelenSpecified(*this, Clauses))
13556 return StmtError();
13557
13558 setFunctionHasBranchProtectedScope();
13559 return OMPMasterTaskLoopSimdDirective::Create(
13560 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13561 }
13562
ActOnOpenMPMaskedTaskLoopSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13563 StmtResult Sema::ActOnOpenMPMaskedTaskLoopSimdDirective(
13564 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13565 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13566 if (!AStmt)
13567 return StmtError();
13568
13569 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13570 OMPLoopBasedDirective::HelperExprs B;
13571 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13572 // define the nested loops number.
13573 unsigned NestedLoopCount =
13574 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13575 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13576 VarsWithImplicitDSA, B);
13577 if (NestedLoopCount == 0)
13578 return StmtError();
13579
13580 assert((CurContext->isDependentContext() || B.builtAll()) &&
13581 "omp for loop exprs were not built");
13582
13583 if (!CurContext->isDependentContext()) {
13584 // Finalize the clauses that need pre-built expressions for CodeGen.
13585 for (OMPClause *C : Clauses) {
13586 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13587 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13588 B.NumIterations, *this, CurScope,
13589 DSAStack))
13590 return StmtError();
13591 }
13592 }
13593
13594 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13595 // The grainsize clause and num_tasks clause are mutually exclusive and may
13596 // not appear on the same taskloop directive.
13597 if (checkMutuallyExclusiveClauses(*this, Clauses,
13598 {OMPC_grainsize, OMPC_num_tasks}))
13599 return StmtError();
13600 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13601 // If a reduction clause is present on the taskloop directive, the nogroup
13602 // clause must not be specified.
13603 if (checkReductionClauseWithNogroup(*this, Clauses))
13604 return StmtError();
13605 if (checkSimdlenSafelenSpecified(*this, Clauses))
13606 return StmtError();
13607
13608 setFunctionHasBranchProtectedScope();
13609 return OMPMaskedTaskLoopSimdDirective::Create(
13610 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13611 }
13612
ActOnOpenMPParallelMasterTaskLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13613 StmtResult Sema::ActOnOpenMPParallelMasterTaskLoopDirective(
13614 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13615 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13616 if (!AStmt)
13617 return StmtError();
13618
13619 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13620 auto *CS = cast<CapturedStmt>(AStmt);
13621 // 1.2.2 OpenMP Language Terminology
13622 // Structured block - An executable statement with a single entry at the
13623 // top and a single exit at the bottom.
13624 // The point of exit cannot be a branch out of the structured block.
13625 // longjmp() and throw() must not violate the entry/exit criteria.
13626 CS->getCapturedDecl()->setNothrow();
13627 for (int ThisCaptureLevel =
13628 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop);
13629 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13630 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13631 // 1.2.2 OpenMP Language Terminology
13632 // Structured block - An executable statement with a single entry at the
13633 // top and a single exit at the bottom.
13634 // The point of exit cannot be a branch out of the structured block.
13635 // longjmp() and throw() must not violate the entry/exit criteria.
13636 CS->getCapturedDecl()->setNothrow();
13637 }
13638
13639 OMPLoopBasedDirective::HelperExprs B;
13640 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13641 // define the nested loops number.
13642 unsigned NestedLoopCount = checkOpenMPLoop(
13643 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13644 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13645 VarsWithImplicitDSA, B);
13646 if (NestedLoopCount == 0)
13647 return StmtError();
13648
13649 assert((CurContext->isDependentContext() || B.builtAll()) &&
13650 "omp for loop exprs were not built");
13651
13652 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13653 // The grainsize clause and num_tasks clause are mutually exclusive and may
13654 // not appear on the same taskloop directive.
13655 if (checkMutuallyExclusiveClauses(*this, Clauses,
13656 {OMPC_grainsize, OMPC_num_tasks}))
13657 return StmtError();
13658 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13659 // If a reduction clause is present on the taskloop directive, the nogroup
13660 // clause must not be specified.
13661 if (checkReductionClauseWithNogroup(*this, Clauses))
13662 return StmtError();
13663
13664 setFunctionHasBranchProtectedScope();
13665 return OMPParallelMasterTaskLoopDirective::Create(
13666 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13667 DSAStack->isCancelRegion());
13668 }
13669
ActOnOpenMPParallelMaskedTaskLoopDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13670 StmtResult Sema::ActOnOpenMPParallelMaskedTaskLoopDirective(
13671 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13672 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13673 if (!AStmt)
13674 return StmtError();
13675
13676 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13677 auto *CS = cast<CapturedStmt>(AStmt);
13678 // 1.2.2 OpenMP Language Terminology
13679 // Structured block - An executable statement with a single entry at the
13680 // top and a single exit at the bottom.
13681 // The point of exit cannot be a branch out of the structured block.
13682 // longjmp() and throw() must not violate the entry/exit criteria.
13683 CS->getCapturedDecl()->setNothrow();
13684 for (int ThisCaptureLevel =
13685 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop);
13686 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13687 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13688 // 1.2.2 OpenMP Language Terminology
13689 // Structured block - An executable statement with a single entry at the
13690 // top and a single exit at the bottom.
13691 // The point of exit cannot be a branch out of the structured block.
13692 // longjmp() and throw() must not violate the entry/exit criteria.
13693 CS->getCapturedDecl()->setNothrow();
13694 }
13695
13696 OMPLoopBasedDirective::HelperExprs B;
13697 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13698 // define the nested loops number.
13699 unsigned NestedLoopCount = checkOpenMPLoop(
13700 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13701 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13702 VarsWithImplicitDSA, B);
13703 if (NestedLoopCount == 0)
13704 return StmtError();
13705
13706 assert((CurContext->isDependentContext() || B.builtAll()) &&
13707 "omp for loop exprs were not built");
13708
13709 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13710 // The grainsize clause and num_tasks clause are mutually exclusive and may
13711 // not appear on the same taskloop directive.
13712 if (checkMutuallyExclusiveClauses(*this, Clauses,
13713 {OMPC_grainsize, OMPC_num_tasks}))
13714 return StmtError();
13715 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13716 // If a reduction clause is present on the taskloop directive, the nogroup
13717 // clause must not be specified.
13718 if (checkReductionClauseWithNogroup(*this, Clauses))
13719 return StmtError();
13720
13721 setFunctionHasBranchProtectedScope();
13722 return OMPParallelMaskedTaskLoopDirective::Create(
13723 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13724 DSAStack->isCancelRegion());
13725 }
13726
ActOnOpenMPParallelMasterTaskLoopSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13727 StmtResult Sema::ActOnOpenMPParallelMasterTaskLoopSimdDirective(
13728 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13729 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13730 if (!AStmt)
13731 return StmtError();
13732
13733 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13734 auto *CS = cast<CapturedStmt>(AStmt);
13735 // 1.2.2 OpenMP Language Terminology
13736 // Structured block - An executable statement with a single entry at the
13737 // top and a single exit at the bottom.
13738 // The point of exit cannot be a branch out of the structured block.
13739 // longjmp() and throw() must not violate the entry/exit criteria.
13740 CS->getCapturedDecl()->setNothrow();
13741 for (int ThisCaptureLevel =
13742 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop_simd);
13743 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13744 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13745 // 1.2.2 OpenMP Language Terminology
13746 // Structured block - An executable statement with a single entry at the
13747 // top and a single exit at the bottom.
13748 // The point of exit cannot be a branch out of the structured block.
13749 // longjmp() and throw() must not violate the entry/exit criteria.
13750 CS->getCapturedDecl()->setNothrow();
13751 }
13752
13753 OMPLoopBasedDirective::HelperExprs B;
13754 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13755 // define the nested loops number.
13756 unsigned NestedLoopCount = checkOpenMPLoop(
13757 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13758 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13759 VarsWithImplicitDSA, B);
13760 if (NestedLoopCount == 0)
13761 return StmtError();
13762
13763 assert((CurContext->isDependentContext() || B.builtAll()) &&
13764 "omp for loop exprs were not built");
13765
13766 if (!CurContext->isDependentContext()) {
13767 // Finalize the clauses that need pre-built expressions for CodeGen.
13768 for (OMPClause *C : Clauses) {
13769 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13770 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13771 B.NumIterations, *this, CurScope,
13772 DSAStack))
13773 return StmtError();
13774 }
13775 }
13776
13777 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13778 // The grainsize clause and num_tasks clause are mutually exclusive and may
13779 // not appear on the same taskloop directive.
13780 if (checkMutuallyExclusiveClauses(*this, Clauses,
13781 {OMPC_grainsize, OMPC_num_tasks}))
13782 return StmtError();
13783 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13784 // If a reduction clause is present on the taskloop directive, the nogroup
13785 // clause must not be specified.
13786 if (checkReductionClauseWithNogroup(*this, Clauses))
13787 return StmtError();
13788 if (checkSimdlenSafelenSpecified(*this, Clauses))
13789 return StmtError();
13790
13791 setFunctionHasBranchProtectedScope();
13792 return OMPParallelMasterTaskLoopSimdDirective::Create(
13793 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13794 }
13795
ActOnOpenMPParallelMaskedTaskLoopSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13796 StmtResult Sema::ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
13797 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13798 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13799 if (!AStmt)
13800 return StmtError();
13801
13802 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13803 auto *CS = cast<CapturedStmt>(AStmt);
13804 // 1.2.2 OpenMP Language Terminology
13805 // Structured block - An executable statement with a single entry at the
13806 // top and a single exit at the bottom.
13807 // The point of exit cannot be a branch out of the structured block.
13808 // longjmp() and throw() must not violate the entry/exit criteria.
13809 CS->getCapturedDecl()->setNothrow();
13810 for (int ThisCaptureLevel =
13811 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop_simd);
13812 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13813 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13814 // 1.2.2 OpenMP Language Terminology
13815 // Structured block - An executable statement with a single entry at the
13816 // top and a single exit at the bottom.
13817 // The point of exit cannot be a branch out of the structured block.
13818 // longjmp() and throw() must not violate the entry/exit criteria.
13819 CS->getCapturedDecl()->setNothrow();
13820 }
13821
13822 OMPLoopBasedDirective::HelperExprs B;
13823 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13824 // define the nested loops number.
13825 unsigned NestedLoopCount = checkOpenMPLoop(
13826 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13827 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13828 VarsWithImplicitDSA, B);
13829 if (NestedLoopCount == 0)
13830 return StmtError();
13831
13832 assert((CurContext->isDependentContext() || B.builtAll()) &&
13833 "omp for loop exprs were not built");
13834
13835 if (!CurContext->isDependentContext()) {
13836 // Finalize the clauses that need pre-built expressions for CodeGen.
13837 for (OMPClause *C : Clauses) {
13838 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13839 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13840 B.NumIterations, *this, CurScope,
13841 DSAStack))
13842 return StmtError();
13843 }
13844 }
13845
13846 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13847 // The grainsize clause and num_tasks clause are mutually exclusive and may
13848 // not appear on the same taskloop directive.
13849 if (checkMutuallyExclusiveClauses(*this, Clauses,
13850 {OMPC_grainsize, OMPC_num_tasks}))
13851 return StmtError();
13852 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13853 // If a reduction clause is present on the taskloop directive, the nogroup
13854 // clause must not be specified.
13855 if (checkReductionClauseWithNogroup(*this, Clauses))
13856 return StmtError();
13857 if (checkSimdlenSafelenSpecified(*this, Clauses))
13858 return StmtError();
13859
13860 setFunctionHasBranchProtectedScope();
13861 return OMPParallelMaskedTaskLoopSimdDirective::Create(
13862 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13863 }
13864
ActOnOpenMPDistributeDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13865 StmtResult Sema::ActOnOpenMPDistributeDirective(
13866 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13867 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13868 if (!AStmt)
13869 return StmtError();
13870
13871 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13872 OMPLoopBasedDirective::HelperExprs B;
13873 // In presence of clause 'collapse' with number of loops, it will
13874 // define the nested loops number.
13875 unsigned NestedLoopCount =
13876 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
13877 nullptr /*ordered not a clause on distribute*/, AStmt,
13878 *this, *DSAStack, VarsWithImplicitDSA, B);
13879 if (NestedLoopCount == 0)
13880 return StmtError();
13881
13882 assert((CurContext->isDependentContext() || B.builtAll()) &&
13883 "omp for loop exprs were not built");
13884
13885 setFunctionHasBranchProtectedScope();
13886 return OMPDistributeDirective::Create(Context, StartLoc, EndLoc,
13887 NestedLoopCount, Clauses, AStmt, B);
13888 }
13889
ActOnOpenMPDistributeParallelForDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13890 StmtResult Sema::ActOnOpenMPDistributeParallelForDirective(
13891 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13892 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13893 if (!AStmt)
13894 return StmtError();
13895
13896 auto *CS = cast<CapturedStmt>(AStmt);
13897 // 1.2.2 OpenMP Language Terminology
13898 // Structured block - An executable statement with a single entry at the
13899 // top and a single exit at the bottom.
13900 // The point of exit cannot be a branch out of the structured block.
13901 // longjmp() and throw() must not violate the entry/exit criteria.
13902 CS->getCapturedDecl()->setNothrow();
13903 for (int ThisCaptureLevel =
13904 getOpenMPCaptureLevels(OMPD_distribute_parallel_for);
13905 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13906 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13907 // 1.2.2 OpenMP Language Terminology
13908 // Structured block - An executable statement with a single entry at the
13909 // top and a single exit at the bottom.
13910 // The point of exit cannot be a branch out of the structured block.
13911 // longjmp() and throw() must not violate the entry/exit criteria.
13912 CS->getCapturedDecl()->setNothrow();
13913 }
13914
13915 OMPLoopBasedDirective::HelperExprs B;
13916 // In presence of clause 'collapse' with number of loops, it will
13917 // define the nested loops number.
13918 unsigned NestedLoopCount = checkOpenMPLoop(
13919 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13920 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
13921 VarsWithImplicitDSA, B);
13922 if (NestedLoopCount == 0)
13923 return StmtError();
13924
13925 assert((CurContext->isDependentContext() || B.builtAll()) &&
13926 "omp for loop exprs were not built");
13927
13928 setFunctionHasBranchProtectedScope();
13929 return OMPDistributeParallelForDirective::Create(
13930 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13931 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13932 }
13933
ActOnOpenMPDistributeParallelForSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13934 StmtResult Sema::ActOnOpenMPDistributeParallelForSimdDirective(
13935 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13936 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13937 if (!AStmt)
13938 return StmtError();
13939
13940 auto *CS = cast<CapturedStmt>(AStmt);
13941 // 1.2.2 OpenMP Language Terminology
13942 // Structured block - An executable statement with a single entry at the
13943 // top and a single exit at the bottom.
13944 // The point of exit cannot be a branch out of the structured block.
13945 // longjmp() and throw() must not violate the entry/exit criteria.
13946 CS->getCapturedDecl()->setNothrow();
13947 for (int ThisCaptureLevel =
13948 getOpenMPCaptureLevels(OMPD_distribute_parallel_for_simd);
13949 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13950 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13951 // 1.2.2 OpenMP Language Terminology
13952 // Structured block - An executable statement with a single entry at the
13953 // top and a single exit at the bottom.
13954 // The point of exit cannot be a branch out of the structured block.
13955 // longjmp() and throw() must not violate the entry/exit criteria.
13956 CS->getCapturedDecl()->setNothrow();
13957 }
13958
13959 OMPLoopBasedDirective::HelperExprs B;
13960 // In presence of clause 'collapse' with number of loops, it will
13961 // define the nested loops number.
13962 unsigned NestedLoopCount = checkOpenMPLoop(
13963 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13964 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
13965 VarsWithImplicitDSA, B);
13966 if (NestedLoopCount == 0)
13967 return StmtError();
13968
13969 assert((CurContext->isDependentContext() || B.builtAll()) &&
13970 "omp for loop exprs were not built");
13971
13972 if (!CurContext->isDependentContext()) {
13973 // Finalize the clauses that need pre-built expressions for CodeGen.
13974 for (OMPClause *C : Clauses) {
13975 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13976 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13977 B.NumIterations, *this, CurScope,
13978 DSAStack))
13979 return StmtError();
13980 }
13981 }
13982
13983 if (checkSimdlenSafelenSpecified(*this, Clauses))
13984 return StmtError();
13985
13986 setFunctionHasBranchProtectedScope();
13987 return OMPDistributeParallelForSimdDirective::Create(
13988 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13989 }
13990
ActOnOpenMPDistributeSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)13991 StmtResult Sema::ActOnOpenMPDistributeSimdDirective(
13992 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13993 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13994 if (!AStmt)
13995 return StmtError();
13996
13997 auto *CS = cast<CapturedStmt>(AStmt);
13998 // 1.2.2 OpenMP Language Terminology
13999 // Structured block - An executable statement with a single entry at the
14000 // top and a single exit at the bottom.
14001 // The point of exit cannot be a branch out of the structured block.
14002 // longjmp() and throw() must not violate the entry/exit criteria.
14003 CS->getCapturedDecl()->setNothrow();
14004 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_distribute_simd);
14005 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14006 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14007 // 1.2.2 OpenMP Language Terminology
14008 // Structured block - An executable statement with a single entry at the
14009 // top and a single exit at the bottom.
14010 // The point of exit cannot be a branch out of the structured block.
14011 // longjmp() and throw() must not violate the entry/exit criteria.
14012 CS->getCapturedDecl()->setNothrow();
14013 }
14014
14015 OMPLoopBasedDirective::HelperExprs B;
14016 // In presence of clause 'collapse' with number of loops, it will
14017 // define the nested loops number.
14018 unsigned NestedLoopCount =
14019 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
14020 nullptr /*ordered not a clause on distribute*/, CS, *this,
14021 *DSAStack, VarsWithImplicitDSA, B);
14022 if (NestedLoopCount == 0)
14023 return StmtError();
14024
14025 assert((CurContext->isDependentContext() || B.builtAll()) &&
14026 "omp for loop exprs were not built");
14027
14028 if (!CurContext->isDependentContext()) {
14029 // Finalize the clauses that need pre-built expressions for CodeGen.
14030 for (OMPClause *C : Clauses) {
14031 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14032 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14033 B.NumIterations, *this, CurScope,
14034 DSAStack))
14035 return StmtError();
14036 }
14037 }
14038
14039 if (checkSimdlenSafelenSpecified(*this, Clauses))
14040 return StmtError();
14041
14042 setFunctionHasBranchProtectedScope();
14043 return OMPDistributeSimdDirective::Create(Context, StartLoc, EndLoc,
14044 NestedLoopCount, Clauses, AStmt, B);
14045 }
14046
ActOnOpenMPTargetParallelForSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)14047 StmtResult Sema::ActOnOpenMPTargetParallelForSimdDirective(
14048 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14049 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14050 if (!AStmt)
14051 return StmtError();
14052
14053 auto *CS = cast<CapturedStmt>(AStmt);
14054 // 1.2.2 OpenMP Language Terminology
14055 // Structured block - An executable statement with a single entry at the
14056 // top and a single exit at the bottom.
14057 // The point of exit cannot be a branch out of the structured block.
14058 // longjmp() and throw() must not violate the entry/exit criteria.
14059 CS->getCapturedDecl()->setNothrow();
14060 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for);
14061 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14062 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14063 // 1.2.2 OpenMP Language Terminology
14064 // Structured block - An executable statement with a single entry at the
14065 // top and a single exit at the bottom.
14066 // The point of exit cannot be a branch out of the structured block.
14067 // longjmp() and throw() must not violate the entry/exit criteria.
14068 CS->getCapturedDecl()->setNothrow();
14069 }
14070
14071 OMPLoopBasedDirective::HelperExprs B;
14072 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14073 // define the nested loops number.
14074 unsigned NestedLoopCount = checkOpenMPLoop(
14075 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
14076 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack, VarsWithImplicitDSA,
14077 B);
14078 if (NestedLoopCount == 0)
14079 return StmtError();
14080
14081 assert((CurContext->isDependentContext() || B.builtAll()) &&
14082 "omp target parallel for simd loop exprs were not built");
14083
14084 if (!CurContext->isDependentContext()) {
14085 // Finalize the clauses that need pre-built expressions for CodeGen.
14086 for (OMPClause *C : Clauses) {
14087 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14088 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14089 B.NumIterations, *this, CurScope,
14090 DSAStack))
14091 return StmtError();
14092 }
14093 }
14094 if (checkSimdlenSafelenSpecified(*this, Clauses))
14095 return StmtError();
14096
14097 setFunctionHasBranchProtectedScope();
14098 return OMPTargetParallelForSimdDirective::Create(
14099 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14100 }
14101
ActOnOpenMPTargetSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)14102 StmtResult Sema::ActOnOpenMPTargetSimdDirective(
14103 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14104 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14105 if (!AStmt)
14106 return StmtError();
14107
14108 auto *CS = cast<CapturedStmt>(AStmt);
14109 // 1.2.2 OpenMP Language Terminology
14110 // Structured block - An executable statement with a single entry at the
14111 // top and a single exit at the bottom.
14112 // The point of exit cannot be a branch out of the structured block.
14113 // longjmp() and throw() must not violate the entry/exit criteria.
14114 CS->getCapturedDecl()->setNothrow();
14115 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_simd);
14116 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14117 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14118 // 1.2.2 OpenMP Language Terminology
14119 // Structured block - An executable statement with a single entry at the
14120 // top and a single exit at the bottom.
14121 // The point of exit cannot be a branch out of the structured block.
14122 // longjmp() and throw() must not violate the entry/exit criteria.
14123 CS->getCapturedDecl()->setNothrow();
14124 }
14125
14126 OMPLoopBasedDirective::HelperExprs B;
14127 // In presence of clause 'collapse' with number of loops, it will define the
14128 // nested loops number.
14129 unsigned NestedLoopCount =
14130 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
14131 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
14132 VarsWithImplicitDSA, B);
14133 if (NestedLoopCount == 0)
14134 return StmtError();
14135
14136 assert((CurContext->isDependentContext() || B.builtAll()) &&
14137 "omp target simd loop exprs were not built");
14138
14139 if (!CurContext->isDependentContext()) {
14140 // Finalize the clauses that need pre-built expressions for CodeGen.
14141 for (OMPClause *C : Clauses) {
14142 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14143 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14144 B.NumIterations, *this, CurScope,
14145 DSAStack))
14146 return StmtError();
14147 }
14148 }
14149
14150 if (checkSimdlenSafelenSpecified(*this, Clauses))
14151 return StmtError();
14152
14153 setFunctionHasBranchProtectedScope();
14154 return OMPTargetSimdDirective::Create(Context, StartLoc, EndLoc,
14155 NestedLoopCount, Clauses, AStmt, B);
14156 }
14157
ActOnOpenMPTeamsDistributeDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)14158 StmtResult Sema::ActOnOpenMPTeamsDistributeDirective(
14159 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14160 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14161 if (!AStmt)
14162 return StmtError();
14163
14164 auto *CS = cast<CapturedStmt>(AStmt);
14165 // 1.2.2 OpenMP Language Terminology
14166 // Structured block - An executable statement with a single entry at the
14167 // top and a single exit at the bottom.
14168 // The point of exit cannot be a branch out of the structured block.
14169 // longjmp() and throw() must not violate the entry/exit criteria.
14170 CS->getCapturedDecl()->setNothrow();
14171 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_distribute);
14172 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14173 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14174 // 1.2.2 OpenMP Language Terminology
14175 // Structured block - An executable statement with a single entry at the
14176 // top and a single exit at the bottom.
14177 // The point of exit cannot be a branch out of the structured block.
14178 // longjmp() and throw() must not violate the entry/exit criteria.
14179 CS->getCapturedDecl()->setNothrow();
14180 }
14181
14182 OMPLoopBasedDirective::HelperExprs B;
14183 // In presence of clause 'collapse' with number of loops, it will
14184 // define the nested loops number.
14185 unsigned NestedLoopCount =
14186 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
14187 nullptr /*ordered not a clause on distribute*/, CS, *this,
14188 *DSAStack, VarsWithImplicitDSA, B);
14189 if (NestedLoopCount == 0)
14190 return StmtError();
14191
14192 assert((CurContext->isDependentContext() || B.builtAll()) &&
14193 "omp teams distribute loop exprs were not built");
14194
14195 setFunctionHasBranchProtectedScope();
14196
14197 DSAStack->setParentTeamsRegionLoc(StartLoc);
14198
14199 return OMPTeamsDistributeDirective::Create(
14200 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14201 }
14202
ActOnOpenMPTeamsDistributeSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)14203 StmtResult Sema::ActOnOpenMPTeamsDistributeSimdDirective(
14204 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14205 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14206 if (!AStmt)
14207 return StmtError();
14208
14209 auto *CS = cast<CapturedStmt>(AStmt);
14210 // 1.2.2 OpenMP Language Terminology
14211 // Structured block - An executable statement with a single entry at the
14212 // top and a single exit at the bottom.
14213 // The point of exit cannot be a branch out of the structured block.
14214 // longjmp() and throw() must not violate the entry/exit criteria.
14215 CS->getCapturedDecl()->setNothrow();
14216 for (int ThisCaptureLevel =
14217 getOpenMPCaptureLevels(OMPD_teams_distribute_simd);
14218 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14219 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14220 // 1.2.2 OpenMP Language Terminology
14221 // Structured block - An executable statement with a single entry at the
14222 // top and a single exit at the bottom.
14223 // The point of exit cannot be a branch out of the structured block.
14224 // longjmp() and throw() must not violate the entry/exit criteria.
14225 CS->getCapturedDecl()->setNothrow();
14226 }
14227
14228 OMPLoopBasedDirective::HelperExprs B;
14229 // In presence of clause 'collapse' with number of loops, it will
14230 // define the nested loops number.
14231 unsigned NestedLoopCount = checkOpenMPLoop(
14232 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14233 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14234 VarsWithImplicitDSA, B);
14235
14236 if (NestedLoopCount == 0)
14237 return StmtError();
14238
14239 assert((CurContext->isDependentContext() || B.builtAll()) &&
14240 "omp teams distribute simd loop exprs were not built");
14241
14242 if (!CurContext->isDependentContext()) {
14243 // Finalize the clauses that need pre-built expressions for CodeGen.
14244 for (OMPClause *C : Clauses) {
14245 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14246 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14247 B.NumIterations, *this, CurScope,
14248 DSAStack))
14249 return StmtError();
14250 }
14251 }
14252
14253 if (checkSimdlenSafelenSpecified(*this, Clauses))
14254 return StmtError();
14255
14256 setFunctionHasBranchProtectedScope();
14257
14258 DSAStack->setParentTeamsRegionLoc(StartLoc);
14259
14260 return OMPTeamsDistributeSimdDirective::Create(
14261 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14262 }
14263
ActOnOpenMPTeamsDistributeParallelForSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)14264 StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
14265 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14266 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14267 if (!AStmt)
14268 return StmtError();
14269
14270 auto *CS = cast<CapturedStmt>(AStmt);
14271 // 1.2.2 OpenMP Language Terminology
14272 // Structured block - An executable statement with a single entry at the
14273 // top and a single exit at the bottom.
14274 // The point of exit cannot be a branch out of the structured block.
14275 // longjmp() and throw() must not violate the entry/exit criteria.
14276 CS->getCapturedDecl()->setNothrow();
14277
14278 for (int ThisCaptureLevel =
14279 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for_simd);
14280 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14281 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14282 // 1.2.2 OpenMP Language Terminology
14283 // Structured block - An executable statement with a single entry at the
14284 // top and a single exit at the bottom.
14285 // The point of exit cannot be a branch out of the structured block.
14286 // longjmp() and throw() must not violate the entry/exit criteria.
14287 CS->getCapturedDecl()->setNothrow();
14288 }
14289
14290 OMPLoopBasedDirective::HelperExprs B;
14291 // In presence of clause 'collapse' with number of loops, it will
14292 // define the nested loops number.
14293 unsigned NestedLoopCount = checkOpenMPLoop(
14294 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14295 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14296 VarsWithImplicitDSA, B);
14297
14298 if (NestedLoopCount == 0)
14299 return StmtError();
14300
14301 assert((CurContext->isDependentContext() || B.builtAll()) &&
14302 "omp for loop exprs were not built");
14303
14304 if (!CurContext->isDependentContext()) {
14305 // Finalize the clauses that need pre-built expressions for CodeGen.
14306 for (OMPClause *C : Clauses) {
14307 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14308 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14309 B.NumIterations, *this, CurScope,
14310 DSAStack))
14311 return StmtError();
14312 }
14313 }
14314
14315 if (checkSimdlenSafelenSpecified(*this, Clauses))
14316 return StmtError();
14317
14318 setFunctionHasBranchProtectedScope();
14319
14320 DSAStack->setParentTeamsRegionLoc(StartLoc);
14321
14322 return OMPTeamsDistributeParallelForSimdDirective::Create(
14323 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14324 }
14325
ActOnOpenMPTeamsDistributeParallelForDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)14326 StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForDirective(
14327 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14328 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14329 if (!AStmt)
14330 return StmtError();
14331
14332 auto *CS = cast<CapturedStmt>(AStmt);
14333 // 1.2.2 OpenMP Language Terminology
14334 // Structured block - An executable statement with a single entry at the
14335 // top and a single exit at the bottom.
14336 // The point of exit cannot be a branch out of the structured block.
14337 // longjmp() and throw() must not violate the entry/exit criteria.
14338 CS->getCapturedDecl()->setNothrow();
14339
14340 for (int ThisCaptureLevel =
14341 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for);
14342 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14343 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14344 // 1.2.2 OpenMP Language Terminology
14345 // Structured block - An executable statement with a single entry at the
14346 // top and a single exit at the bottom.
14347 // The point of exit cannot be a branch out of the structured block.
14348 // longjmp() and throw() must not violate the entry/exit criteria.
14349 CS->getCapturedDecl()->setNothrow();
14350 }
14351
14352 OMPLoopBasedDirective::HelperExprs B;
14353 // In presence of clause 'collapse' with number of loops, it will
14354 // define the nested loops number.
14355 unsigned NestedLoopCount = checkOpenMPLoop(
14356 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14357 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14358 VarsWithImplicitDSA, B);
14359
14360 if (NestedLoopCount == 0)
14361 return StmtError();
14362
14363 assert((CurContext->isDependentContext() || B.builtAll()) &&
14364 "omp for loop exprs were not built");
14365
14366 setFunctionHasBranchProtectedScope();
14367
14368 DSAStack->setParentTeamsRegionLoc(StartLoc);
14369
14370 return OMPTeamsDistributeParallelForDirective::Create(
14371 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14372 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14373 }
14374
ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)14375 StmtResult Sema::ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause *> Clauses,
14376 Stmt *AStmt,
14377 SourceLocation StartLoc,
14378 SourceLocation EndLoc) {
14379 if (!AStmt)
14380 return StmtError();
14381
14382 auto *CS = cast<CapturedStmt>(AStmt);
14383 // 1.2.2 OpenMP Language Terminology
14384 // Structured block - An executable statement with a single entry at the
14385 // top and a single exit at the bottom.
14386 // The point of exit cannot be a branch out of the structured block.
14387 // longjmp() and throw() must not violate the entry/exit criteria.
14388 CS->getCapturedDecl()->setNothrow();
14389
14390 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams);
14391 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14392 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14393 // 1.2.2 OpenMP Language Terminology
14394 // Structured block - An executable statement with a single entry at the
14395 // top and a single exit at the bottom.
14396 // The point of exit cannot be a branch out of the structured block.
14397 // longjmp() and throw() must not violate the entry/exit criteria.
14398 CS->getCapturedDecl()->setNothrow();
14399 }
14400 setFunctionHasBranchProtectedScope();
14401
14402 return OMPTargetTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses,
14403 AStmt);
14404 }
14405
ActOnOpenMPTargetTeamsDistributeDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)14406 StmtResult Sema::ActOnOpenMPTargetTeamsDistributeDirective(
14407 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14408 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14409 if (!AStmt)
14410 return StmtError();
14411
14412 auto *CS = cast<CapturedStmt>(AStmt);
14413 // 1.2.2 OpenMP Language Terminology
14414 // Structured block - An executable statement with a single entry at the
14415 // top and a single exit at the bottom.
14416 // The point of exit cannot be a branch out of the structured block.
14417 // longjmp() and throw() must not violate the entry/exit criteria.
14418 CS->getCapturedDecl()->setNothrow();
14419 for (int ThisCaptureLevel =
14420 getOpenMPCaptureLevels(OMPD_target_teams_distribute);
14421 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14422 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14423 // 1.2.2 OpenMP Language Terminology
14424 // Structured block - An executable statement with a single entry at the
14425 // top and a single exit at the bottom.
14426 // The point of exit cannot be a branch out of the structured block.
14427 // longjmp() and throw() must not violate the entry/exit criteria.
14428 CS->getCapturedDecl()->setNothrow();
14429 }
14430
14431 OMPLoopBasedDirective::HelperExprs B;
14432 // In presence of clause 'collapse' with number of loops, it will
14433 // define the nested loops number.
14434 unsigned NestedLoopCount = checkOpenMPLoop(
14435 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14436 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14437 VarsWithImplicitDSA, B);
14438 if (NestedLoopCount == 0)
14439 return StmtError();
14440
14441 assert((CurContext->isDependentContext() || B.builtAll()) &&
14442 "omp target teams distribute loop exprs were not built");
14443
14444 setFunctionHasBranchProtectedScope();
14445 return OMPTargetTeamsDistributeDirective::Create(
14446 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14447 }
14448
ActOnOpenMPTargetTeamsDistributeParallelForDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)14449 StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
14450 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14451 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14452 if (!AStmt)
14453 return StmtError();
14454
14455 auto *CS = cast<CapturedStmt>(AStmt);
14456 // 1.2.2 OpenMP Language Terminology
14457 // Structured block - An executable statement with a single entry at the
14458 // top and a single exit at the bottom.
14459 // The point of exit cannot be a branch out of the structured block.
14460 // longjmp() and throw() must not violate the entry/exit criteria.
14461 CS->getCapturedDecl()->setNothrow();
14462 for (int ThisCaptureLevel =
14463 getOpenMPCaptureLevels(OMPD_target_teams_distribute_parallel_for);
14464 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14465 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14466 // 1.2.2 OpenMP Language Terminology
14467 // Structured block - An executable statement with a single entry at the
14468 // top and a single exit at the bottom.
14469 // The point of exit cannot be a branch out of the structured block.
14470 // longjmp() and throw() must not violate the entry/exit criteria.
14471 CS->getCapturedDecl()->setNothrow();
14472 }
14473
14474 OMPLoopBasedDirective::HelperExprs B;
14475 // In presence of clause 'collapse' with number of loops, it will
14476 // define the nested loops number.
14477 unsigned NestedLoopCount = checkOpenMPLoop(
14478 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14479 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14480 VarsWithImplicitDSA, B);
14481 if (NestedLoopCount == 0)
14482 return StmtError();
14483
14484 assert((CurContext->isDependentContext() || B.builtAll()) &&
14485 "omp target teams distribute parallel for loop exprs were not built");
14486
14487 if (!CurContext->isDependentContext()) {
14488 // Finalize the clauses that need pre-built expressions for CodeGen.
14489 for (OMPClause *C : Clauses) {
14490 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14491 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14492 B.NumIterations, *this, CurScope,
14493 DSAStack))
14494 return StmtError();
14495 }
14496 }
14497
14498 setFunctionHasBranchProtectedScope();
14499 return OMPTargetTeamsDistributeParallelForDirective::Create(
14500 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14501 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14502 }
14503
ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)14504 StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
14505 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14506 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14507 if (!AStmt)
14508 return StmtError();
14509
14510 auto *CS = cast<CapturedStmt>(AStmt);
14511 // 1.2.2 OpenMP Language Terminology
14512 // Structured block - An executable statement with a single entry at the
14513 // top and a single exit at the bottom.
14514 // The point of exit cannot be a branch out of the structured block.
14515 // longjmp() and throw() must not violate the entry/exit criteria.
14516 CS->getCapturedDecl()->setNothrow();
14517 for (int ThisCaptureLevel = getOpenMPCaptureLevels(
14518 OMPD_target_teams_distribute_parallel_for_simd);
14519 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14520 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14521 // 1.2.2 OpenMP Language Terminology
14522 // Structured block - An executable statement with a single entry at the
14523 // top and a single exit at the bottom.
14524 // The point of exit cannot be a branch out of the structured block.
14525 // longjmp() and throw() must not violate the entry/exit criteria.
14526 CS->getCapturedDecl()->setNothrow();
14527 }
14528
14529 OMPLoopBasedDirective::HelperExprs B;
14530 // In presence of clause 'collapse' with number of loops, it will
14531 // define the nested loops number.
14532 unsigned NestedLoopCount =
14533 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14534 getCollapseNumberExpr(Clauses),
14535 nullptr /*ordered not a clause on distribute*/, CS, *this,
14536 *DSAStack, VarsWithImplicitDSA, B);
14537 if (NestedLoopCount == 0)
14538 return StmtError();
14539
14540 assert((CurContext->isDependentContext() || B.builtAll()) &&
14541 "omp target teams distribute parallel for simd loop exprs were not "
14542 "built");
14543
14544 if (!CurContext->isDependentContext()) {
14545 // Finalize the clauses that need pre-built expressions for CodeGen.
14546 for (OMPClause *C : Clauses) {
14547 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14548 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14549 B.NumIterations, *this, CurScope,
14550 DSAStack))
14551 return StmtError();
14552 }
14553 }
14554
14555 if (checkSimdlenSafelenSpecified(*this, Clauses))
14556 return StmtError();
14557
14558 setFunctionHasBranchProtectedScope();
14559 return OMPTargetTeamsDistributeParallelForSimdDirective::Create(
14560 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14561 }
14562
ActOnOpenMPTargetTeamsDistributeSimdDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc,VarsWithInheritedDSAType & VarsWithImplicitDSA)14563 StmtResult Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective(
14564 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14565 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14566 if (!AStmt)
14567 return StmtError();
14568
14569 auto *CS = cast<CapturedStmt>(AStmt);
14570 // 1.2.2 OpenMP Language Terminology
14571 // Structured block - An executable statement with a single entry at the
14572 // top and a single exit at the bottom.
14573 // The point of exit cannot be a branch out of the structured block.
14574 // longjmp() and throw() must not violate the entry/exit criteria.
14575 CS->getCapturedDecl()->setNothrow();
14576 for (int ThisCaptureLevel =
14577 getOpenMPCaptureLevels(OMPD_target_teams_distribute_simd);
14578 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14579 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14580 // 1.2.2 OpenMP Language Terminology
14581 // Structured block - An executable statement with a single entry at the
14582 // top and a single exit at the bottom.
14583 // The point of exit cannot be a branch out of the structured block.
14584 // longjmp() and throw() must not violate the entry/exit criteria.
14585 CS->getCapturedDecl()->setNothrow();
14586 }
14587
14588 OMPLoopBasedDirective::HelperExprs B;
14589 // In presence of clause 'collapse' with number of loops, it will
14590 // define the nested loops number.
14591 unsigned NestedLoopCount = checkOpenMPLoop(
14592 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14593 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14594 VarsWithImplicitDSA, B);
14595 if (NestedLoopCount == 0)
14596 return StmtError();
14597
14598 assert((CurContext->isDependentContext() || B.builtAll()) &&
14599 "omp target teams distribute simd loop exprs were not built");
14600
14601 if (!CurContext->isDependentContext()) {
14602 // Finalize the clauses that need pre-built expressions for CodeGen.
14603 for (OMPClause *C : Clauses) {
14604 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14605 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14606 B.NumIterations, *this, CurScope,
14607 DSAStack))
14608 return StmtError();
14609 }
14610 }
14611
14612 if (checkSimdlenSafelenSpecified(*this, Clauses))
14613 return StmtError();
14614
14615 setFunctionHasBranchProtectedScope();
14616 return OMPTargetTeamsDistributeSimdDirective::Create(
14617 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14618 }
14619
checkTransformableLoopNest(OpenMPDirectiveKind Kind,Stmt * AStmt,int NumLoops,SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> & LoopHelpers,Stmt * & Body,SmallVectorImpl<SmallVector<llvm::PointerUnion<Stmt *,Decl * >,0>> & OriginalInits)14620 bool Sema::checkTransformableLoopNest(
14621 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14622 SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers,
14623 Stmt *&Body,
14624 SmallVectorImpl<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>>
14625 &OriginalInits) {
14626 OriginalInits.emplace_back();
14627 bool Result = OMPLoopBasedDirective::doForAllLoops(
14628 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14629 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14630 Stmt *CurStmt) {
14631 VarsWithInheritedDSAType TmpDSA;
14632 unsigned SingleNumLoops =
14633 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, *this, *DSAStack,
14634 TmpDSA, LoopHelpers[Cnt]);
14635 if (SingleNumLoops == 0)
14636 return true;
14637 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14638 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14639 OriginalInits.back().push_back(For->getInit());
14640 Body = For->getBody();
14641 } else {
14642 assert(isa<CXXForRangeStmt>(CurStmt) &&
14643 "Expected canonical for or range-based for loops.");
14644 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14645 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14646 Body = CXXFor->getBody();
14647 }
14648 OriginalInits.emplace_back();
14649 return false;
14650 },
14651 [&OriginalInits](OMPLoopBasedDirective *Transform) {
14652 Stmt *DependentPreInits;
14653 if (auto *Dir = dyn_cast<OMPTileDirective>(Transform))
14654 DependentPreInits = Dir->getPreInits();
14655 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
14656 DependentPreInits = Dir->getPreInits();
14657 else
14658 llvm_unreachable("Unhandled loop transformation");
14659 if (!DependentPreInits)
14660 return;
14661 llvm::append_range(OriginalInits.back(),
14662 cast<DeclStmt>(DependentPreInits)->getDeclGroup());
14663 });
14664 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14665 OriginalInits.pop_back();
14666 return Result;
14667 }
14668
ActOnOpenMPTileDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)14669 StmtResult Sema::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
14670 Stmt *AStmt, SourceLocation StartLoc,
14671 SourceLocation EndLoc) {
14672 auto SizesClauses =
14673 OMPExecutableDirective::getClausesOfKind<OMPSizesClause>(Clauses);
14674 if (SizesClauses.empty()) {
14675 // A missing 'sizes' clause is already reported by the parser.
14676 return StmtError();
14677 }
14678 const OMPSizesClause *SizesClause = *SizesClauses.begin();
14679 unsigned NumLoops = SizesClause->getNumSizes();
14680
14681 // Empty statement should only be possible if there already was an error.
14682 if (!AStmt)
14683 return StmtError();
14684
14685 // Verify and diagnose loop nest.
14686 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
14687 Stmt *Body = nullptr;
14688 SmallVector<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>, 4>
14689 OriginalInits;
14690 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14691 OriginalInits))
14692 return StmtError();
14693
14694 // Delay tiling to when template is completely instantiated.
14695 if (CurContext->isDependentContext())
14696 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14697 NumLoops, AStmt, nullptr, nullptr);
14698
14699 SmallVector<Decl *, 4> PreInits;
14700
14701 // Create iteration variables for the generated loops.
14702 SmallVector<VarDecl *, 4> FloorIndVars;
14703 SmallVector<VarDecl *, 4> TileIndVars;
14704 FloorIndVars.resize(NumLoops);
14705 TileIndVars.resize(NumLoops);
14706 for (unsigned I = 0; I < NumLoops; ++I) {
14707 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14708
14709 assert(LoopHelper.Counters.size() == 1 &&
14710 "Expect single-dimensional loop iteration space");
14711 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14712 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14713 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14714 QualType CntTy = IterVarRef->getType();
14715
14716 // Iteration variable for the floor (i.e. outer) loop.
14717 {
14718 std::string FloorCntName =
14719 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14720 VarDecl *FloorCntDecl =
14721 buildVarDecl(*this, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14722 FloorIndVars[I] = FloorCntDecl;
14723 }
14724
14725 // Iteration variable for the tile (i.e. inner) loop.
14726 {
14727 std::string TileCntName =
14728 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14729
14730 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14731 // used by the expressions to derive the original iteration variable's
14732 // value from the logical iteration number.
14733 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14734 TileCntDecl->setDeclName(&PP.getIdentifierTable().get(TileCntName));
14735 TileIndVars[I] = TileCntDecl;
14736 }
14737 for (auto &P : OriginalInits[I]) {
14738 if (auto *D = P.dyn_cast<Decl *>())
14739 PreInits.push_back(D);
14740 else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
14741 PreInits.append(PI->decl_begin(), PI->decl_end());
14742 }
14743 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
14744 PreInits.append(PI->decl_begin(), PI->decl_end());
14745 // Gather declarations for the data members used as counters.
14746 for (Expr *CounterRef : LoopHelper.Counters) {
14747 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14748 if (isa<OMPCapturedExprDecl>(CounterDecl))
14749 PreInits.push_back(CounterDecl);
14750 }
14751 }
14752
14753 // Once the original iteration values are set, append the innermost body.
14754 Stmt *Inner = Body;
14755
14756 // Create tile loops from the inside to the outside.
14757 for (int I = NumLoops - 1; I >= 0; --I) {
14758 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14759 Expr *NumIterations = LoopHelper.NumIterations;
14760 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14761 QualType CntTy = OrigCntVar->getType();
14762 Expr *DimTileSize = SizesClause->getSizesRefs()[I];
14763 Scope *CurScope = getCurScope();
14764
14765 // Commonly used variables.
14766 DeclRefExpr *TileIV = buildDeclRefExpr(*this, TileIndVars[I], CntTy,
14767 OrigCntVar->getExprLoc());
14768 DeclRefExpr *FloorIV = buildDeclRefExpr(*this, FloorIndVars[I], CntTy,
14769 OrigCntVar->getExprLoc());
14770
14771 // For init-statement: auto .tile.iv = .floor.iv
14772 AddInitializerToDecl(TileIndVars[I], DefaultLvalueConversion(FloorIV).get(),
14773 /*DirectInit=*/false);
14774 Decl *CounterDecl = TileIndVars[I];
14775 StmtResult InitStmt = new (Context)
14776 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14777 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14778 if (!InitStmt.isUsable())
14779 return StmtError();
14780
14781 // For cond-expression: .tile.iv < min(.floor.iv + DimTileSize,
14782 // NumIterations)
14783 ExprResult EndOfTile = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
14784 BO_Add, FloorIV, DimTileSize);
14785 if (!EndOfTile.isUsable())
14786 return StmtError();
14787 ExprResult IsPartialTile =
14788 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14789 NumIterations, EndOfTile.get());
14790 if (!IsPartialTile.isUsable())
14791 return StmtError();
14792 ExprResult MinTileAndIterSpace = ActOnConditionalOp(
14793 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14794 IsPartialTile.get(), NumIterations, EndOfTile.get());
14795 if (!MinTileAndIterSpace.isUsable())
14796 return StmtError();
14797 ExprResult CondExpr = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
14798 BO_LT, TileIV, MinTileAndIterSpace.get());
14799 if (!CondExpr.isUsable())
14800 return StmtError();
14801
14802 // For incr-statement: ++.tile.iv
14803 ExprResult IncrStmt =
14804 BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, TileIV);
14805 if (!IncrStmt.isUsable())
14806 return StmtError();
14807
14808 // Statements to set the original iteration variable's value from the
14809 // logical iteration number.
14810 // Generated for loop is:
14811 // Original_for_init;
14812 // for (auto .tile.iv = .floor.iv; .tile.iv < min(.floor.iv + DimTileSize,
14813 // NumIterations); ++.tile.iv) {
14814 // Original_Body;
14815 // Original_counter_update;
14816 // }
14817 // FIXME: If the innermost body is an loop itself, inserting these
14818 // statements stops it being recognized as a perfectly nested loop (e.g.
14819 // for applying tiling again). If this is the case, sink the expressions
14820 // further into the inner loop.
14821 SmallVector<Stmt *, 4> BodyParts;
14822 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14823 BodyParts.push_back(Inner);
14824 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
14825 Inner->getBeginLoc(), Inner->getEndLoc());
14826 Inner = new (Context)
14827 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14828 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14829 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14830 }
14831
14832 // Create floor loops from the inside to the outside.
14833 for (int I = NumLoops - 1; I >= 0; --I) {
14834 auto &LoopHelper = LoopHelpers[I];
14835 Expr *NumIterations = LoopHelper.NumIterations;
14836 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14837 QualType CntTy = OrigCntVar->getType();
14838 Expr *DimTileSize = SizesClause->getSizesRefs()[I];
14839 Scope *CurScope = getCurScope();
14840
14841 // Commonly used variables.
14842 DeclRefExpr *FloorIV = buildDeclRefExpr(*this, FloorIndVars[I], CntTy,
14843 OrigCntVar->getExprLoc());
14844
14845 // For init-statement: auto .floor.iv = 0
14846 AddInitializerToDecl(
14847 FloorIndVars[I],
14848 ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14849 /*DirectInit=*/false);
14850 Decl *CounterDecl = FloorIndVars[I];
14851 StmtResult InitStmt = new (Context)
14852 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14853 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14854 if (!InitStmt.isUsable())
14855 return StmtError();
14856
14857 // For cond-expression: .floor.iv < NumIterations
14858 ExprResult CondExpr = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
14859 BO_LT, FloorIV, NumIterations);
14860 if (!CondExpr.isUsable())
14861 return StmtError();
14862
14863 // For incr-statement: .floor.iv += DimTileSize
14864 ExprResult IncrStmt = BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(),
14865 BO_AddAssign, FloorIV, DimTileSize);
14866 if (!IncrStmt.isUsable())
14867 return StmtError();
14868
14869 Inner = new (Context)
14870 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14871 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14872 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14873 }
14874
14875 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
14876 AStmt, Inner,
14877 buildPreInits(Context, PreInits));
14878 }
14879
ActOnOpenMPUnrollDirective(ArrayRef<OMPClause * > Clauses,Stmt * AStmt,SourceLocation StartLoc,SourceLocation EndLoc)14880 StmtResult Sema::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses,
14881 Stmt *AStmt,
14882 SourceLocation StartLoc,
14883 SourceLocation EndLoc) {
14884 // Empty statement should only be possible if there already was an error.
14885 if (!AStmt)
14886 return StmtError();
14887
14888 if (checkMutuallyExclusiveClauses(*this, Clauses, {OMPC_partial, OMPC_full}))
14889 return StmtError();
14890
14891 const OMPFullClause *FullClause =
14892 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
14893 const OMPPartialClause *PartialClause =
14894 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
14895 assert(!(FullClause && PartialClause) &&
14896 "mutual exclusivity must have been checked before");
14897
14898 constexpr unsigned NumLoops = 1;
14899 Stmt *Body = nullptr;
14900 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
14901 NumLoops);
14902 SmallVector<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>, NumLoops + 1>
14903 OriginalInits;
14904 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
14905 Body, OriginalInits))
14906 return StmtError();
14907
14908 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
14909
14910 // Delay unrolling to when template is completely instantiated.
14911 if (CurContext->isDependentContext())
14912 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14913 NumGeneratedLoops, nullptr, nullptr);
14914
14915 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
14916
14917 if (FullClause) {
14918 if (!VerifyPositiveIntegerConstantInClause(
14919 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
14920 /*SuppressExprDiags=*/true)
14921 .isUsable()) {
14922 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
14923 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
14924 << "#pragma omp unroll full";
14925 return StmtError();
14926 }
14927 }
14928
14929 // The generated loop may only be passed to other loop-associated directive
14930 // when a partial clause is specified. Without the requirement it is
14931 // sufficient to generate loop unroll metadata at code-generation.
14932 if (NumGeneratedLoops == 0)
14933 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14934 NumGeneratedLoops, nullptr, nullptr);
14935
14936 // Otherwise, we need to provide a de-sugared/transformed AST that can be
14937 // associated with another loop directive.
14938 //
14939 // The canonical loop analysis return by checkTransformableLoopNest assumes
14940 // the following structure to be the same loop without transformations or
14941 // directives applied: \code OriginalInits; LoopHelper.PreInits;
14942 // LoopHelper.Counters;
14943 // for (; IV < LoopHelper.NumIterations; ++IV) {
14944 // LoopHelper.Updates;
14945 // Body;
14946 // }
14947 // \endcode
14948 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
14949 // and referenced by LoopHelper.IterationVarRef.
14950 //
14951 // The unrolling directive transforms this into the following loop:
14952 // \code
14953 // OriginalInits; \
14954 // LoopHelper.PreInits; > NewPreInits
14955 // LoopHelper.Counters; /
14956 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
14957 // #pragma clang loop unroll_count(Factor)
14958 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
14959 // {
14960 // LoopHelper.Updates;
14961 // Body;
14962 // }
14963 // }
14964 // \endcode
14965 // where UIV is a new logical iteration counter. IV must be the same VarDecl
14966 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
14967 // references it. If the partially unrolled loop is associated with another
14968 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
14969 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
14970 // OpenMP canonical loop. The inner loop is not an associable canonical loop
14971 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
14972 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
14973 // property of the OMPLoopBasedDirective instead of statements in
14974 // CompoundStatement. This is to allow the loop to become a non-outermost loop
14975 // of a canonical loop nest where these PreInits are emitted before the
14976 // outermost directive.
14977
14978 // Determine the PreInit declarations.
14979 SmallVector<Decl *, 4> PreInits;
14980 assert(OriginalInits.size() == 1 &&
14981 "Expecting a single-dimensional loop iteration space");
14982 for (auto &P : OriginalInits[0]) {
14983 if (auto *D = P.dyn_cast<Decl *>())
14984 PreInits.push_back(D);
14985 else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
14986 PreInits.append(PI->decl_begin(), PI->decl_end());
14987 }
14988 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
14989 PreInits.append(PI->decl_begin(), PI->decl_end());
14990 // Gather declarations for the data members used as counters.
14991 for (Expr *CounterRef : LoopHelper.Counters) {
14992 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14993 if (isa<OMPCapturedExprDecl>(CounterDecl))
14994 PreInits.push_back(CounterDecl);
14995 }
14996
14997 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14998 QualType IVTy = IterationVarRef->getType();
14999 assert(LoopHelper.Counters.size() == 1 &&
15000 "Expecting a single-dimensional loop iteration space");
15001 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15002
15003 // Determine the unroll factor.
15004 uint64_t Factor;
15005 SourceLocation FactorLoc;
15006 if (Expr *FactorVal = PartialClause->getFactor()) {
15007 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15008 FactorLoc = FactorVal->getExprLoc();
15009 } else {
15010 // TODO: Use a better profitability model.
15011 Factor = 2;
15012 }
15013 assert(Factor > 0 && "Expected positive unroll factor");
15014 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
15015 return IntegerLiteral::Create(
15016 Context, llvm::APInt(Context.getIntWidth(IVTy), Factor), IVTy,
15017 FactorLoc);
15018 };
15019
15020 // Iteration variable SourceLocations.
15021 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15022 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15023 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15024
15025 // Internal variable names.
15026 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15027 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
15028 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
15029 std::string InnerTripCountName =
15030 (Twine(".unroll_inner.tripcount.") + OrigVarName).str();
15031
15032 // Create the iteration variable for the unrolled loop.
15033 VarDecl *OuterIVDecl =
15034 buildVarDecl(*this, {}, IVTy, OuterIVName, nullptr, OrigVar);
15035 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
15036 return buildDeclRefExpr(*this, OuterIVDecl, IVTy, OrigVarLoc);
15037 };
15038
15039 // Iteration variable for the inner loop: Reuse the iteration variable created
15040 // by checkOpenMPLoop.
15041 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15042 InnerIVDecl->setDeclName(&PP.getIdentifierTable().get(InnerIVName));
15043 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
15044 return buildDeclRefExpr(*this, InnerIVDecl, IVTy, OrigVarLoc);
15045 };
15046
15047 // Make a copy of the NumIterations expression for each use: By the AST
15048 // constraints, every expression object in a DeclContext must be unique.
15049 CaptureVars CopyTransformer(*this);
15050 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15051 return AssertSuccess(
15052 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15053 };
15054
15055 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15056 ExprResult LValueConv = DefaultLvalueConversion(MakeOuterRef());
15057 AddInitializerToDecl(InnerIVDecl, LValueConv.get(), /*DirectInit=*/false);
15058 StmtResult InnerInit = new (Context)
15059 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15060 if (!InnerInit.isUsable())
15061 return StmtError();
15062
15063 // Inner For cond-expression:
15064 // \code
15065 // .unroll_inner.iv < .unrolled.iv + Factor &&
15066 // .unroll_inner.iv < NumIterations
15067 // \endcode
15068 // This conjunction of two conditions allows ScalarEvolution to derive the
15069 // maximum trip count of the inner loop.
15070 ExprResult EndOfTile = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15071 BO_Add, MakeOuterRef(), MakeFactorExpr());
15072 if (!EndOfTile.isUsable())
15073 return StmtError();
15074 ExprResult InnerCond1 = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15075 BO_LT, MakeInnerRef(), EndOfTile.get());
15076 if (!InnerCond1.isUsable())
15077 return StmtError();
15078 ExprResult InnerCond2 =
15079 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeInnerRef(),
15080 MakeNumIterations());
15081 if (!InnerCond2.isUsable())
15082 return StmtError();
15083 ExprResult InnerCond =
15084 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15085 InnerCond1.get(), InnerCond2.get());
15086 if (!InnerCond.isUsable())
15087 return StmtError();
15088
15089 // Inner For incr-statement: ++.unroll_inner.iv
15090 ExprResult InnerIncr = BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
15091 UO_PreInc, MakeInnerRef());
15092 if (!InnerIncr.isUsable())
15093 return StmtError();
15094
15095 // Inner For statement.
15096 SmallVector<Stmt *> InnerBodyStmts;
15097 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15098 InnerBodyStmts.push_back(Body);
15099 CompoundStmt *InnerBody =
15100 CompoundStmt::Create(Context, InnerBodyStmts, FPOptionsOverride(),
15101 Body->getBeginLoc(), Body->getEndLoc());
15102 ForStmt *InnerFor = new (Context)
15103 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15104 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15105 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15106
15107 // Unroll metadata for the inner loop.
15108 // This needs to take into account the remainder portion of the unrolled loop,
15109 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15110 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15111 // the maximum trip count, which will also generate a remainder loop. Just
15112 // `unroll(enable)` (which could have been useful if the user has not
15113 // specified a concrete factor; even though the outer loop cannot be
15114 // influenced anymore, would avoid more code bloat than necessary) will refuse
15115 // the loop because "Won't unroll; remainder loop could not be generated when
15116 // assuming runtime trip count". Even if it did work, it must not choose a
15117 // larger unroll factor than the maximum loop length, or it would always just
15118 // execute the remainder loop.
15119 LoopHintAttr *UnrollHintAttr =
15120 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15121 LoopHintAttr::Numeric, MakeFactorExpr());
15122 AttributedStmt *InnerUnrolled =
15123 AttributedStmt::Create(Context, StartLoc, {UnrollHintAttr}, InnerFor);
15124
15125 // Outer For init-statement: auto .unrolled.iv = 0
15126 AddInitializerToDecl(
15127 OuterIVDecl, ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15128 /*DirectInit=*/false);
15129 StmtResult OuterInit = new (Context)
15130 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15131 if (!OuterInit.isUsable())
15132 return StmtError();
15133
15134 // Outer For cond-expression: .unrolled.iv < NumIterations
15135 ExprResult OuterConde =
15136 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeOuterRef(),
15137 MakeNumIterations());
15138 if (!OuterConde.isUsable())
15139 return StmtError();
15140
15141 // Outer For incr-statement: .unrolled.iv += Factor
15142 ExprResult OuterIncr =
15143 BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15144 MakeOuterRef(), MakeFactorExpr());
15145 if (!OuterIncr.isUsable())
15146 return StmtError();
15147
15148 // Outer For statement.
15149 ForStmt *OuterFor = new (Context)
15150 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15151 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15152 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15153
15154 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15155 NumGeneratedLoops, OuterFor,
15156 buildPreInits(Context, PreInits));
15157 }
15158
ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,Expr * Expr,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)15159 OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
15160 SourceLocation StartLoc,
15161 SourceLocation LParenLoc,
15162 SourceLocation EndLoc) {
15163 OMPClause *Res = nullptr;
15164 switch (Kind) {
15165 case OMPC_final:
15166 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
15167 break;
15168 case OMPC_num_threads:
15169 Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
15170 break;
15171 case OMPC_safelen:
15172 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
15173 break;
15174 case OMPC_simdlen:
15175 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
15176 break;
15177 case OMPC_allocator:
15178 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
15179 break;
15180 case OMPC_collapse:
15181 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
15182 break;
15183 case OMPC_ordered:
15184 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
15185 break;
15186 case OMPC_num_teams:
15187 Res = ActOnOpenMPNumTeamsClause(Expr, StartLoc, LParenLoc, EndLoc);
15188 break;
15189 case OMPC_thread_limit:
15190 Res = ActOnOpenMPThreadLimitClause(Expr, StartLoc, LParenLoc, EndLoc);
15191 break;
15192 case OMPC_priority:
15193 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
15194 break;
15195 case OMPC_hint:
15196 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
15197 break;
15198 case OMPC_depobj:
15199 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
15200 break;
15201 case OMPC_detach:
15202 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
15203 break;
15204 case OMPC_novariants:
15205 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
15206 break;
15207 case OMPC_nocontext:
15208 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
15209 break;
15210 case OMPC_filter:
15211 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
15212 break;
15213 case OMPC_partial:
15214 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
15215 break;
15216 case OMPC_message:
15217 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
15218 break;
15219 case OMPC_align:
15220 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
15221 break;
15222 case OMPC_ompx_dyn_cgroup_mem:
15223 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
15224 break;
15225 case OMPC_grainsize:
15226 case OMPC_num_tasks:
15227 case OMPC_device:
15228 case OMPC_if:
15229 case OMPC_default:
15230 case OMPC_proc_bind:
15231 case OMPC_schedule:
15232 case OMPC_private:
15233 case OMPC_firstprivate:
15234 case OMPC_lastprivate:
15235 case OMPC_shared:
15236 case OMPC_reduction:
15237 case OMPC_task_reduction:
15238 case OMPC_in_reduction:
15239 case OMPC_linear:
15240 case OMPC_aligned:
15241 case OMPC_copyin:
15242 case OMPC_copyprivate:
15243 case OMPC_nowait:
15244 case OMPC_untied:
15245 case OMPC_mergeable:
15246 case OMPC_threadprivate:
15247 case OMPC_sizes:
15248 case OMPC_allocate:
15249 case OMPC_flush:
15250 case OMPC_read:
15251 case OMPC_write:
15252 case OMPC_update:
15253 case OMPC_capture:
15254 case OMPC_compare:
15255 case OMPC_seq_cst:
15256 case OMPC_acq_rel:
15257 case OMPC_acquire:
15258 case OMPC_release:
15259 case OMPC_relaxed:
15260 case OMPC_depend:
15261 case OMPC_threads:
15262 case OMPC_simd:
15263 case OMPC_map:
15264 case OMPC_nogroup:
15265 case OMPC_dist_schedule:
15266 case OMPC_defaultmap:
15267 case OMPC_unknown:
15268 case OMPC_uniform:
15269 case OMPC_to:
15270 case OMPC_from:
15271 case OMPC_use_device_ptr:
15272 case OMPC_use_device_addr:
15273 case OMPC_is_device_ptr:
15274 case OMPC_unified_address:
15275 case OMPC_unified_shared_memory:
15276 case OMPC_reverse_offload:
15277 case OMPC_dynamic_allocators:
15278 case OMPC_atomic_default_mem_order:
15279 case OMPC_device_type:
15280 case OMPC_match:
15281 case OMPC_nontemporal:
15282 case OMPC_order:
15283 case OMPC_at:
15284 case OMPC_severity:
15285 case OMPC_destroy:
15286 case OMPC_inclusive:
15287 case OMPC_exclusive:
15288 case OMPC_uses_allocators:
15289 case OMPC_affinity:
15290 case OMPC_when:
15291 case OMPC_bind:
15292 default:
15293 llvm_unreachable("Clause is not allowed.");
15294 }
15295 return Res;
15296 }
15297
15298 // An OpenMP directive such as 'target parallel' has two captured regions:
15299 // for the 'target' and 'parallel' respectively. This function returns
15300 // the region in which to capture expressions associated with a clause.
15301 // A return value of OMPD_unknown signifies that the expression should not
15302 // be captured.
getOpenMPCaptureRegionForClause(OpenMPDirectiveKind DKind,OpenMPClauseKind CKind,unsigned OpenMPVersion,OpenMPDirectiveKind NameModifier=OMPD_unknown)15303 static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
15304 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15305 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15306 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15307 switch (CKind) {
15308 case OMPC_if:
15309 switch (DKind) {
15310 case OMPD_target_parallel_for_simd:
15311 if (OpenMPVersion >= 50 &&
15312 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15313 CaptureRegion = OMPD_parallel;
15314 break;
15315 }
15316 [[fallthrough]];
15317 case OMPD_target_parallel:
15318 case OMPD_target_parallel_for:
15319 case OMPD_target_parallel_loop:
15320 // If this clause applies to the nested 'parallel' region, capture within
15321 // the 'target' region, otherwise do not capture.
15322 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15323 CaptureRegion = OMPD_target;
15324 break;
15325 case OMPD_target_teams_distribute_parallel_for_simd:
15326 if (OpenMPVersion >= 50 &&
15327 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15328 CaptureRegion = OMPD_parallel;
15329 break;
15330 }
15331 [[fallthrough]];
15332 case OMPD_target_teams_distribute_parallel_for:
15333 // If this clause applies to the nested 'parallel' region, capture within
15334 // the 'teams' region, otherwise do not capture.
15335 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15336 CaptureRegion = OMPD_teams;
15337 break;
15338 case OMPD_teams_distribute_parallel_for_simd:
15339 if (OpenMPVersion >= 50 &&
15340 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15341 CaptureRegion = OMPD_parallel;
15342 break;
15343 }
15344 [[fallthrough]];
15345 case OMPD_teams_distribute_parallel_for:
15346 CaptureRegion = OMPD_teams;
15347 break;
15348 case OMPD_target_update:
15349 case OMPD_target_enter_data:
15350 case OMPD_target_exit_data:
15351 CaptureRegion = OMPD_task;
15352 break;
15353 case OMPD_parallel_masked_taskloop:
15354 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15355 CaptureRegion = OMPD_parallel;
15356 break;
15357 case OMPD_parallel_master_taskloop:
15358 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15359 CaptureRegion = OMPD_parallel;
15360 break;
15361 case OMPD_parallel_masked_taskloop_simd:
15362 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15363 NameModifier == OMPD_taskloop) {
15364 CaptureRegion = OMPD_parallel;
15365 break;
15366 }
15367 if (OpenMPVersion <= 45)
15368 break;
15369 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15370 CaptureRegion = OMPD_taskloop;
15371 break;
15372 case OMPD_parallel_master_taskloop_simd:
15373 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15374 NameModifier == OMPD_taskloop) {
15375 CaptureRegion = OMPD_parallel;
15376 break;
15377 }
15378 if (OpenMPVersion <= 45)
15379 break;
15380 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15381 CaptureRegion = OMPD_taskloop;
15382 break;
15383 case OMPD_parallel_for_simd:
15384 if (OpenMPVersion <= 45)
15385 break;
15386 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15387 CaptureRegion = OMPD_parallel;
15388 break;
15389 case OMPD_taskloop_simd:
15390 case OMPD_master_taskloop_simd:
15391 case OMPD_masked_taskloop_simd:
15392 if (OpenMPVersion <= 45)
15393 break;
15394 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15395 CaptureRegion = OMPD_taskloop;
15396 break;
15397 case OMPD_distribute_parallel_for_simd:
15398 if (OpenMPVersion <= 45)
15399 break;
15400 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15401 CaptureRegion = OMPD_parallel;
15402 break;
15403 case OMPD_target_simd:
15404 if (OpenMPVersion >= 50 &&
15405 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15406 CaptureRegion = OMPD_target;
15407 break;
15408 case OMPD_teams_distribute_simd:
15409 case OMPD_target_teams_distribute_simd:
15410 if (OpenMPVersion >= 50 &&
15411 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15412 CaptureRegion = OMPD_teams;
15413 break;
15414 case OMPD_cancel:
15415 case OMPD_parallel:
15416 case OMPD_parallel_master:
15417 case OMPD_parallel_masked:
15418 case OMPD_parallel_sections:
15419 case OMPD_parallel_for:
15420 case OMPD_parallel_loop:
15421 case OMPD_target:
15422 case OMPD_target_teams:
15423 case OMPD_target_teams_distribute:
15424 case OMPD_target_teams_loop:
15425 case OMPD_distribute_parallel_for:
15426 case OMPD_task:
15427 case OMPD_taskloop:
15428 case OMPD_master_taskloop:
15429 case OMPD_masked_taskloop:
15430 case OMPD_target_data:
15431 case OMPD_simd:
15432 case OMPD_for_simd:
15433 case OMPD_distribute_simd:
15434 // Do not capture if-clause expressions.
15435 break;
15436 case OMPD_threadprivate:
15437 case OMPD_allocate:
15438 case OMPD_taskyield:
15439 case OMPD_error:
15440 case OMPD_barrier:
15441 case OMPD_taskwait:
15442 case OMPD_cancellation_point:
15443 case OMPD_flush:
15444 case OMPD_depobj:
15445 case OMPD_scan:
15446 case OMPD_declare_reduction:
15447 case OMPD_declare_mapper:
15448 case OMPD_declare_simd:
15449 case OMPD_declare_variant:
15450 case OMPD_begin_declare_variant:
15451 case OMPD_end_declare_variant:
15452 case OMPD_declare_target:
15453 case OMPD_end_declare_target:
15454 case OMPD_loop:
15455 case OMPD_teams_loop:
15456 case OMPD_teams:
15457 case OMPD_tile:
15458 case OMPD_unroll:
15459 case OMPD_for:
15460 case OMPD_sections:
15461 case OMPD_section:
15462 case OMPD_single:
15463 case OMPD_master:
15464 case OMPD_masked:
15465 case OMPD_critical:
15466 case OMPD_taskgroup:
15467 case OMPD_distribute:
15468 case OMPD_ordered:
15469 case OMPD_atomic:
15470 case OMPD_teams_distribute:
15471 case OMPD_requires:
15472 case OMPD_metadirective:
15473 llvm_unreachable("Unexpected OpenMP directive with if-clause");
15474 case OMPD_unknown:
15475 default:
15476 llvm_unreachable("Unknown OpenMP directive");
15477 }
15478 break;
15479 case OMPC_num_threads:
15480 switch (DKind) {
15481 case OMPD_target_parallel:
15482 case OMPD_target_parallel_for:
15483 case OMPD_target_parallel_for_simd:
15484 case OMPD_target_parallel_loop:
15485 CaptureRegion = OMPD_target;
15486 break;
15487 case OMPD_teams_distribute_parallel_for:
15488 case OMPD_teams_distribute_parallel_for_simd:
15489 case OMPD_target_teams_distribute_parallel_for:
15490 case OMPD_target_teams_distribute_parallel_for_simd:
15491 CaptureRegion = OMPD_teams;
15492 break;
15493 case OMPD_parallel:
15494 case OMPD_parallel_master:
15495 case OMPD_parallel_masked:
15496 case OMPD_parallel_sections:
15497 case OMPD_parallel_for:
15498 case OMPD_parallel_for_simd:
15499 case OMPD_parallel_loop:
15500 case OMPD_distribute_parallel_for:
15501 case OMPD_distribute_parallel_for_simd:
15502 case OMPD_parallel_master_taskloop:
15503 case OMPD_parallel_masked_taskloop:
15504 case OMPD_parallel_master_taskloop_simd:
15505 case OMPD_parallel_masked_taskloop_simd:
15506 // Do not capture num_threads-clause expressions.
15507 break;
15508 case OMPD_target_data:
15509 case OMPD_target_enter_data:
15510 case OMPD_target_exit_data:
15511 case OMPD_target_update:
15512 case OMPD_target:
15513 case OMPD_target_simd:
15514 case OMPD_target_teams:
15515 case OMPD_target_teams_distribute:
15516 case OMPD_target_teams_distribute_simd:
15517 case OMPD_cancel:
15518 case OMPD_task:
15519 case OMPD_taskloop:
15520 case OMPD_taskloop_simd:
15521 case OMPD_master_taskloop:
15522 case OMPD_masked_taskloop:
15523 case OMPD_master_taskloop_simd:
15524 case OMPD_masked_taskloop_simd:
15525 case OMPD_threadprivate:
15526 case OMPD_allocate:
15527 case OMPD_taskyield:
15528 case OMPD_error:
15529 case OMPD_barrier:
15530 case OMPD_taskwait:
15531 case OMPD_cancellation_point:
15532 case OMPD_flush:
15533 case OMPD_depobj:
15534 case OMPD_scan:
15535 case OMPD_declare_reduction:
15536 case OMPD_declare_mapper:
15537 case OMPD_declare_simd:
15538 case OMPD_declare_variant:
15539 case OMPD_begin_declare_variant:
15540 case OMPD_end_declare_variant:
15541 case OMPD_declare_target:
15542 case OMPD_end_declare_target:
15543 case OMPD_loop:
15544 case OMPD_teams_loop:
15545 case OMPD_target_teams_loop:
15546 case OMPD_teams:
15547 case OMPD_simd:
15548 case OMPD_tile:
15549 case OMPD_unroll:
15550 case OMPD_for:
15551 case OMPD_for_simd:
15552 case OMPD_sections:
15553 case OMPD_section:
15554 case OMPD_single:
15555 case OMPD_master:
15556 case OMPD_masked:
15557 case OMPD_critical:
15558 case OMPD_taskgroup:
15559 case OMPD_distribute:
15560 case OMPD_ordered:
15561 case OMPD_atomic:
15562 case OMPD_distribute_simd:
15563 case OMPD_teams_distribute:
15564 case OMPD_teams_distribute_simd:
15565 case OMPD_requires:
15566 case OMPD_metadirective:
15567 llvm_unreachable("Unexpected OpenMP directive with num_threads-clause");
15568 case OMPD_unknown:
15569 default:
15570 llvm_unreachable("Unknown OpenMP directive");
15571 }
15572 break;
15573 case OMPC_num_teams:
15574 switch (DKind) {
15575 case OMPD_target_teams:
15576 case OMPD_target_teams_distribute:
15577 case OMPD_target_teams_distribute_simd:
15578 case OMPD_target_teams_distribute_parallel_for:
15579 case OMPD_target_teams_distribute_parallel_for_simd:
15580 case OMPD_target_teams_loop:
15581 CaptureRegion = OMPD_target;
15582 break;
15583 case OMPD_teams_distribute_parallel_for:
15584 case OMPD_teams_distribute_parallel_for_simd:
15585 case OMPD_teams:
15586 case OMPD_teams_distribute:
15587 case OMPD_teams_distribute_simd:
15588 case OMPD_teams_loop:
15589 // Do not capture num_teams-clause expressions.
15590 break;
15591 case OMPD_distribute_parallel_for:
15592 case OMPD_distribute_parallel_for_simd:
15593 case OMPD_task:
15594 case OMPD_taskloop:
15595 case OMPD_taskloop_simd:
15596 case OMPD_master_taskloop:
15597 case OMPD_masked_taskloop:
15598 case OMPD_master_taskloop_simd:
15599 case OMPD_masked_taskloop_simd:
15600 case OMPD_parallel_master_taskloop:
15601 case OMPD_parallel_masked_taskloop:
15602 case OMPD_parallel_master_taskloop_simd:
15603 case OMPD_parallel_masked_taskloop_simd:
15604 case OMPD_target_data:
15605 case OMPD_target_enter_data:
15606 case OMPD_target_exit_data:
15607 case OMPD_target_update:
15608 case OMPD_cancel:
15609 case OMPD_parallel:
15610 case OMPD_parallel_master:
15611 case OMPD_parallel_masked:
15612 case OMPD_parallel_sections:
15613 case OMPD_parallel_for:
15614 case OMPD_parallel_for_simd:
15615 case OMPD_parallel_loop:
15616 case OMPD_target:
15617 case OMPD_target_simd:
15618 case OMPD_target_parallel:
15619 case OMPD_target_parallel_for:
15620 case OMPD_target_parallel_for_simd:
15621 case OMPD_target_parallel_loop:
15622 case OMPD_threadprivate:
15623 case OMPD_allocate:
15624 case OMPD_taskyield:
15625 case OMPD_error:
15626 case OMPD_barrier:
15627 case OMPD_taskwait:
15628 case OMPD_cancellation_point:
15629 case OMPD_flush:
15630 case OMPD_depobj:
15631 case OMPD_scan:
15632 case OMPD_declare_reduction:
15633 case OMPD_declare_mapper:
15634 case OMPD_declare_simd:
15635 case OMPD_declare_variant:
15636 case OMPD_begin_declare_variant:
15637 case OMPD_end_declare_variant:
15638 case OMPD_declare_target:
15639 case OMPD_end_declare_target:
15640 case OMPD_loop:
15641 case OMPD_simd:
15642 case OMPD_tile:
15643 case OMPD_unroll:
15644 case OMPD_for:
15645 case OMPD_for_simd:
15646 case OMPD_sections:
15647 case OMPD_section:
15648 case OMPD_single:
15649 case OMPD_master:
15650 case OMPD_masked:
15651 case OMPD_critical:
15652 case OMPD_taskgroup:
15653 case OMPD_distribute:
15654 case OMPD_ordered:
15655 case OMPD_atomic:
15656 case OMPD_distribute_simd:
15657 case OMPD_requires:
15658 case OMPD_metadirective:
15659 llvm_unreachable("Unexpected OpenMP directive with num_teams-clause");
15660 case OMPD_unknown:
15661 default:
15662 llvm_unreachable("Unknown OpenMP directive");
15663 }
15664 break;
15665 case OMPC_thread_limit:
15666 switch (DKind) {
15667 case OMPD_target:
15668 case OMPD_target_teams:
15669 case OMPD_target_teams_distribute:
15670 case OMPD_target_teams_distribute_simd:
15671 case OMPD_target_teams_distribute_parallel_for:
15672 case OMPD_target_teams_distribute_parallel_for_simd:
15673 case OMPD_target_teams_loop:
15674 CaptureRegion = OMPD_target;
15675 break;
15676 case OMPD_teams_distribute_parallel_for:
15677 case OMPD_teams_distribute_parallel_for_simd:
15678 case OMPD_teams:
15679 case OMPD_teams_distribute:
15680 case OMPD_teams_distribute_simd:
15681 case OMPD_teams_loop:
15682 // Do not capture thread_limit-clause expressions.
15683 break;
15684 case OMPD_distribute_parallel_for:
15685 case OMPD_distribute_parallel_for_simd:
15686 case OMPD_task:
15687 case OMPD_taskloop:
15688 case OMPD_taskloop_simd:
15689 case OMPD_master_taskloop:
15690 case OMPD_masked_taskloop:
15691 case OMPD_master_taskloop_simd:
15692 case OMPD_masked_taskloop_simd:
15693 case OMPD_parallel_master_taskloop:
15694 case OMPD_parallel_masked_taskloop:
15695 case OMPD_parallel_master_taskloop_simd:
15696 case OMPD_parallel_masked_taskloop_simd:
15697 case OMPD_target_data:
15698 case OMPD_target_enter_data:
15699 case OMPD_target_exit_data:
15700 case OMPD_target_update:
15701 case OMPD_cancel:
15702 case OMPD_parallel:
15703 case OMPD_parallel_master:
15704 case OMPD_parallel_masked:
15705 case OMPD_parallel_sections:
15706 case OMPD_parallel_for:
15707 case OMPD_parallel_for_simd:
15708 case OMPD_parallel_loop:
15709 case OMPD_target_simd:
15710 case OMPD_target_parallel:
15711 case OMPD_target_parallel_for:
15712 case OMPD_target_parallel_for_simd:
15713 case OMPD_target_parallel_loop:
15714 case OMPD_threadprivate:
15715 case OMPD_allocate:
15716 case OMPD_taskyield:
15717 case OMPD_error:
15718 case OMPD_barrier:
15719 case OMPD_taskwait:
15720 case OMPD_cancellation_point:
15721 case OMPD_flush:
15722 case OMPD_depobj:
15723 case OMPD_scan:
15724 case OMPD_declare_reduction:
15725 case OMPD_declare_mapper:
15726 case OMPD_declare_simd:
15727 case OMPD_declare_variant:
15728 case OMPD_begin_declare_variant:
15729 case OMPD_end_declare_variant:
15730 case OMPD_declare_target:
15731 case OMPD_end_declare_target:
15732 case OMPD_loop:
15733 case OMPD_simd:
15734 case OMPD_tile:
15735 case OMPD_unroll:
15736 case OMPD_for:
15737 case OMPD_for_simd:
15738 case OMPD_sections:
15739 case OMPD_section:
15740 case OMPD_single:
15741 case OMPD_master:
15742 case OMPD_masked:
15743 case OMPD_critical:
15744 case OMPD_taskgroup:
15745 case OMPD_distribute:
15746 case OMPD_ordered:
15747 case OMPD_atomic:
15748 case OMPD_distribute_simd:
15749 case OMPD_requires:
15750 case OMPD_metadirective:
15751 llvm_unreachable("Unexpected OpenMP directive with thread_limit-clause");
15752 case OMPD_unknown:
15753 default:
15754 llvm_unreachable("Unknown OpenMP directive");
15755 }
15756 break;
15757 case OMPC_schedule:
15758 switch (DKind) {
15759 case OMPD_parallel_for:
15760 case OMPD_parallel_for_simd:
15761 case OMPD_distribute_parallel_for:
15762 case OMPD_distribute_parallel_for_simd:
15763 case OMPD_teams_distribute_parallel_for:
15764 case OMPD_teams_distribute_parallel_for_simd:
15765 case OMPD_target_parallel_for:
15766 case OMPD_target_parallel_for_simd:
15767 case OMPD_target_teams_distribute_parallel_for:
15768 case OMPD_target_teams_distribute_parallel_for_simd:
15769 CaptureRegion = OMPD_parallel;
15770 break;
15771 case OMPD_for:
15772 case OMPD_for_simd:
15773 // Do not capture schedule-clause expressions.
15774 break;
15775 case OMPD_task:
15776 case OMPD_taskloop:
15777 case OMPD_taskloop_simd:
15778 case OMPD_master_taskloop:
15779 case OMPD_masked_taskloop:
15780 case OMPD_master_taskloop_simd:
15781 case OMPD_masked_taskloop_simd:
15782 case OMPD_parallel_master_taskloop:
15783 case OMPD_parallel_masked_taskloop:
15784 case OMPD_parallel_master_taskloop_simd:
15785 case OMPD_parallel_masked_taskloop_simd:
15786 case OMPD_target_data:
15787 case OMPD_target_enter_data:
15788 case OMPD_target_exit_data:
15789 case OMPD_target_update:
15790 case OMPD_teams:
15791 case OMPD_teams_distribute:
15792 case OMPD_teams_distribute_simd:
15793 case OMPD_target_teams_distribute:
15794 case OMPD_target_teams_distribute_simd:
15795 case OMPD_target:
15796 case OMPD_target_simd:
15797 case OMPD_target_parallel:
15798 case OMPD_cancel:
15799 case OMPD_parallel:
15800 case OMPD_parallel_master:
15801 case OMPD_parallel_masked:
15802 case OMPD_parallel_sections:
15803 case OMPD_threadprivate:
15804 case OMPD_allocate:
15805 case OMPD_taskyield:
15806 case OMPD_error:
15807 case OMPD_barrier:
15808 case OMPD_taskwait:
15809 case OMPD_cancellation_point:
15810 case OMPD_flush:
15811 case OMPD_depobj:
15812 case OMPD_scan:
15813 case OMPD_declare_reduction:
15814 case OMPD_declare_mapper:
15815 case OMPD_declare_simd:
15816 case OMPD_declare_variant:
15817 case OMPD_begin_declare_variant:
15818 case OMPD_end_declare_variant:
15819 case OMPD_declare_target:
15820 case OMPD_end_declare_target:
15821 case OMPD_loop:
15822 case OMPD_teams_loop:
15823 case OMPD_target_teams_loop:
15824 case OMPD_parallel_loop:
15825 case OMPD_target_parallel_loop:
15826 case OMPD_simd:
15827 case OMPD_tile:
15828 case OMPD_unroll:
15829 case OMPD_sections:
15830 case OMPD_section:
15831 case OMPD_single:
15832 case OMPD_master:
15833 case OMPD_masked:
15834 case OMPD_critical:
15835 case OMPD_taskgroup:
15836 case OMPD_distribute:
15837 case OMPD_ordered:
15838 case OMPD_atomic:
15839 case OMPD_distribute_simd:
15840 case OMPD_target_teams:
15841 case OMPD_requires:
15842 case OMPD_metadirective:
15843 llvm_unreachable("Unexpected OpenMP directive with schedule clause");
15844 case OMPD_unknown:
15845 default:
15846 llvm_unreachable("Unknown OpenMP directive");
15847 }
15848 break;
15849 case OMPC_dist_schedule:
15850 switch (DKind) {
15851 case OMPD_teams_distribute_parallel_for:
15852 case OMPD_teams_distribute_parallel_for_simd:
15853 case OMPD_teams_distribute:
15854 case OMPD_teams_distribute_simd:
15855 case OMPD_target_teams_distribute_parallel_for:
15856 case OMPD_target_teams_distribute_parallel_for_simd:
15857 case OMPD_target_teams_distribute:
15858 case OMPD_target_teams_distribute_simd:
15859 CaptureRegion = OMPD_teams;
15860 break;
15861 case OMPD_distribute_parallel_for:
15862 case OMPD_distribute_parallel_for_simd:
15863 case OMPD_distribute:
15864 case OMPD_distribute_simd:
15865 // Do not capture dist_schedule-clause expressions.
15866 break;
15867 case OMPD_parallel_for:
15868 case OMPD_parallel_for_simd:
15869 case OMPD_target_parallel_for_simd:
15870 case OMPD_target_parallel_for:
15871 case OMPD_task:
15872 case OMPD_taskloop:
15873 case OMPD_taskloop_simd:
15874 case OMPD_master_taskloop:
15875 case OMPD_masked_taskloop:
15876 case OMPD_master_taskloop_simd:
15877 case OMPD_masked_taskloop_simd:
15878 case OMPD_parallel_master_taskloop:
15879 case OMPD_parallel_masked_taskloop:
15880 case OMPD_parallel_master_taskloop_simd:
15881 case OMPD_parallel_masked_taskloop_simd:
15882 case OMPD_target_data:
15883 case OMPD_target_enter_data:
15884 case OMPD_target_exit_data:
15885 case OMPD_target_update:
15886 case OMPD_teams:
15887 case OMPD_target:
15888 case OMPD_target_simd:
15889 case OMPD_target_parallel:
15890 case OMPD_cancel:
15891 case OMPD_parallel:
15892 case OMPD_parallel_master:
15893 case OMPD_parallel_masked:
15894 case OMPD_parallel_sections:
15895 case OMPD_threadprivate:
15896 case OMPD_allocate:
15897 case OMPD_taskyield:
15898 case OMPD_error:
15899 case OMPD_barrier:
15900 case OMPD_taskwait:
15901 case OMPD_cancellation_point:
15902 case OMPD_flush:
15903 case OMPD_depobj:
15904 case OMPD_scan:
15905 case OMPD_declare_reduction:
15906 case OMPD_declare_mapper:
15907 case OMPD_declare_simd:
15908 case OMPD_declare_variant:
15909 case OMPD_begin_declare_variant:
15910 case OMPD_end_declare_variant:
15911 case OMPD_declare_target:
15912 case OMPD_end_declare_target:
15913 case OMPD_loop:
15914 case OMPD_teams_loop:
15915 case OMPD_target_teams_loop:
15916 case OMPD_parallel_loop:
15917 case OMPD_target_parallel_loop:
15918 case OMPD_simd:
15919 case OMPD_tile:
15920 case OMPD_unroll:
15921 case OMPD_for:
15922 case OMPD_for_simd:
15923 case OMPD_sections:
15924 case OMPD_section:
15925 case OMPD_single:
15926 case OMPD_master:
15927 case OMPD_masked:
15928 case OMPD_critical:
15929 case OMPD_taskgroup:
15930 case OMPD_ordered:
15931 case OMPD_atomic:
15932 case OMPD_target_teams:
15933 case OMPD_requires:
15934 case OMPD_metadirective:
15935 llvm_unreachable("Unexpected OpenMP directive with dist_schedule clause");
15936 case OMPD_unknown:
15937 default:
15938 llvm_unreachable("Unknown OpenMP directive");
15939 }
15940 break;
15941 case OMPC_ompx_dyn_cgroup_mem:
15942 switch (DKind) {
15943 case OMPD_target:
15944 case OMPD_target_simd:
15945 case OMPD_target_teams:
15946 case OMPD_target_parallel:
15947 case OMPD_target_teams_distribute:
15948 case OMPD_target_teams_distribute_simd:
15949 case OMPD_target_parallel_for:
15950 case OMPD_target_parallel_for_simd:
15951 case OMPD_target_parallel_loop:
15952 case OMPD_target_teams_distribute_parallel_for:
15953 case OMPD_target_teams_distribute_parallel_for_simd:
15954 case OMPD_target_teams_loop:
15955 CaptureRegion = OMPD_target;
15956 break;
15957 default:
15958 llvm_unreachable("Unknown OpenMP directive");
15959 }
15960 break;
15961 case OMPC_device:
15962 switch (DKind) {
15963 case OMPD_target_update:
15964 case OMPD_target_enter_data:
15965 case OMPD_target_exit_data:
15966 case OMPD_target:
15967 case OMPD_target_simd:
15968 case OMPD_target_teams:
15969 case OMPD_target_parallel:
15970 case OMPD_target_teams_distribute:
15971 case OMPD_target_teams_distribute_simd:
15972 case OMPD_target_parallel_for:
15973 case OMPD_target_parallel_for_simd:
15974 case OMPD_target_parallel_loop:
15975 case OMPD_target_teams_distribute_parallel_for:
15976 case OMPD_target_teams_distribute_parallel_for_simd:
15977 case OMPD_target_teams_loop:
15978 case OMPD_dispatch:
15979 CaptureRegion = OMPD_task;
15980 break;
15981 case OMPD_target_data:
15982 case OMPD_interop:
15983 // Do not capture device-clause expressions.
15984 break;
15985 case OMPD_teams_distribute_parallel_for:
15986 case OMPD_teams_distribute_parallel_for_simd:
15987 case OMPD_teams:
15988 case OMPD_teams_distribute:
15989 case OMPD_teams_distribute_simd:
15990 case OMPD_distribute_parallel_for:
15991 case OMPD_distribute_parallel_for_simd:
15992 case OMPD_task:
15993 case OMPD_taskloop:
15994 case OMPD_taskloop_simd:
15995 case OMPD_master_taskloop:
15996 case OMPD_masked_taskloop:
15997 case OMPD_master_taskloop_simd:
15998 case OMPD_masked_taskloop_simd:
15999 case OMPD_parallel_master_taskloop:
16000 case OMPD_parallel_masked_taskloop:
16001 case OMPD_parallel_master_taskloop_simd:
16002 case OMPD_parallel_masked_taskloop_simd:
16003 case OMPD_cancel:
16004 case OMPD_parallel:
16005 case OMPD_parallel_master:
16006 case OMPD_parallel_masked:
16007 case OMPD_parallel_sections:
16008 case OMPD_parallel_for:
16009 case OMPD_parallel_for_simd:
16010 case OMPD_threadprivate:
16011 case OMPD_allocate:
16012 case OMPD_taskyield:
16013 case OMPD_error:
16014 case OMPD_barrier:
16015 case OMPD_taskwait:
16016 case OMPD_cancellation_point:
16017 case OMPD_flush:
16018 case OMPD_depobj:
16019 case OMPD_scan:
16020 case OMPD_declare_reduction:
16021 case OMPD_declare_mapper:
16022 case OMPD_declare_simd:
16023 case OMPD_declare_variant:
16024 case OMPD_begin_declare_variant:
16025 case OMPD_end_declare_variant:
16026 case OMPD_declare_target:
16027 case OMPD_end_declare_target:
16028 case OMPD_loop:
16029 case OMPD_teams_loop:
16030 case OMPD_parallel_loop:
16031 case OMPD_simd:
16032 case OMPD_tile:
16033 case OMPD_unroll:
16034 case OMPD_for:
16035 case OMPD_for_simd:
16036 case OMPD_sections:
16037 case OMPD_section:
16038 case OMPD_single:
16039 case OMPD_master:
16040 case OMPD_masked:
16041 case OMPD_critical:
16042 case OMPD_taskgroup:
16043 case OMPD_distribute:
16044 case OMPD_ordered:
16045 case OMPD_atomic:
16046 case OMPD_distribute_simd:
16047 case OMPD_requires:
16048 case OMPD_metadirective:
16049 llvm_unreachable("Unexpected OpenMP directive with device-clause");
16050 case OMPD_unknown:
16051 default:
16052 llvm_unreachable("Unknown OpenMP directive");
16053 }
16054 break;
16055 case OMPC_grainsize:
16056 case OMPC_num_tasks:
16057 case OMPC_final:
16058 case OMPC_priority:
16059 switch (DKind) {
16060 case OMPD_task:
16061 case OMPD_taskloop:
16062 case OMPD_taskloop_simd:
16063 case OMPD_master_taskloop:
16064 case OMPD_masked_taskloop:
16065 case OMPD_master_taskloop_simd:
16066 case OMPD_masked_taskloop_simd:
16067 break;
16068 case OMPD_parallel_masked_taskloop:
16069 case OMPD_parallel_masked_taskloop_simd:
16070 case OMPD_parallel_master_taskloop:
16071 case OMPD_parallel_master_taskloop_simd:
16072 CaptureRegion = OMPD_parallel;
16073 break;
16074 case OMPD_target_update:
16075 case OMPD_target_enter_data:
16076 case OMPD_target_exit_data:
16077 case OMPD_target:
16078 case OMPD_target_simd:
16079 case OMPD_target_teams:
16080 case OMPD_target_parallel:
16081 case OMPD_target_teams_distribute:
16082 case OMPD_target_teams_distribute_simd:
16083 case OMPD_target_parallel_for:
16084 case OMPD_target_parallel_for_simd:
16085 case OMPD_target_teams_distribute_parallel_for:
16086 case OMPD_target_teams_distribute_parallel_for_simd:
16087 case OMPD_target_data:
16088 case OMPD_teams_distribute_parallel_for:
16089 case OMPD_teams_distribute_parallel_for_simd:
16090 case OMPD_teams:
16091 case OMPD_teams_distribute:
16092 case OMPD_teams_distribute_simd:
16093 case OMPD_distribute_parallel_for:
16094 case OMPD_distribute_parallel_for_simd:
16095 case OMPD_cancel:
16096 case OMPD_parallel:
16097 case OMPD_parallel_master:
16098 case OMPD_parallel_masked:
16099 case OMPD_parallel_sections:
16100 case OMPD_parallel_for:
16101 case OMPD_parallel_for_simd:
16102 case OMPD_threadprivate:
16103 case OMPD_allocate:
16104 case OMPD_taskyield:
16105 case OMPD_error:
16106 case OMPD_barrier:
16107 case OMPD_taskwait:
16108 case OMPD_cancellation_point:
16109 case OMPD_flush:
16110 case OMPD_depobj:
16111 case OMPD_scan:
16112 case OMPD_declare_reduction:
16113 case OMPD_declare_mapper:
16114 case OMPD_declare_simd:
16115 case OMPD_declare_variant:
16116 case OMPD_begin_declare_variant:
16117 case OMPD_end_declare_variant:
16118 case OMPD_declare_target:
16119 case OMPD_end_declare_target:
16120 case OMPD_loop:
16121 case OMPD_teams_loop:
16122 case OMPD_target_teams_loop:
16123 case OMPD_parallel_loop:
16124 case OMPD_target_parallel_loop:
16125 case OMPD_simd:
16126 case OMPD_tile:
16127 case OMPD_unroll:
16128 case OMPD_for:
16129 case OMPD_for_simd:
16130 case OMPD_sections:
16131 case OMPD_section:
16132 case OMPD_single:
16133 case OMPD_master:
16134 case OMPD_masked:
16135 case OMPD_critical:
16136 case OMPD_taskgroup:
16137 case OMPD_distribute:
16138 case OMPD_ordered:
16139 case OMPD_atomic:
16140 case OMPD_distribute_simd:
16141 case OMPD_requires:
16142 case OMPD_metadirective:
16143 llvm_unreachable("Unexpected OpenMP directive with grainsize-clause");
16144 case OMPD_unknown:
16145 default:
16146 llvm_unreachable("Unknown OpenMP directive");
16147 }
16148 break;
16149 case OMPC_novariants:
16150 case OMPC_nocontext:
16151 switch (DKind) {
16152 case OMPD_dispatch:
16153 CaptureRegion = OMPD_task;
16154 break;
16155 default:
16156 llvm_unreachable("Unexpected OpenMP directive");
16157 }
16158 break;
16159 case OMPC_filter:
16160 // Do not capture filter-clause expressions.
16161 break;
16162 case OMPC_when:
16163 if (DKind == OMPD_metadirective) {
16164 CaptureRegion = OMPD_metadirective;
16165 } else if (DKind == OMPD_unknown) {
16166 llvm_unreachable("Unknown OpenMP directive");
16167 } else {
16168 llvm_unreachable("Unexpected OpenMP directive with when clause");
16169 }
16170 break;
16171 case OMPC_firstprivate:
16172 case OMPC_lastprivate:
16173 case OMPC_reduction:
16174 case OMPC_task_reduction:
16175 case OMPC_in_reduction:
16176 case OMPC_linear:
16177 case OMPC_default:
16178 case OMPC_proc_bind:
16179 case OMPC_safelen:
16180 case OMPC_simdlen:
16181 case OMPC_sizes:
16182 case OMPC_allocator:
16183 case OMPC_collapse:
16184 case OMPC_private:
16185 case OMPC_shared:
16186 case OMPC_aligned:
16187 case OMPC_copyin:
16188 case OMPC_copyprivate:
16189 case OMPC_ordered:
16190 case OMPC_nowait:
16191 case OMPC_untied:
16192 case OMPC_mergeable:
16193 case OMPC_threadprivate:
16194 case OMPC_allocate:
16195 case OMPC_flush:
16196 case OMPC_depobj:
16197 case OMPC_read:
16198 case OMPC_write:
16199 case OMPC_update:
16200 case OMPC_capture:
16201 case OMPC_compare:
16202 case OMPC_seq_cst:
16203 case OMPC_acq_rel:
16204 case OMPC_acquire:
16205 case OMPC_release:
16206 case OMPC_relaxed:
16207 case OMPC_depend:
16208 case OMPC_threads:
16209 case OMPC_simd:
16210 case OMPC_map:
16211 case OMPC_nogroup:
16212 case OMPC_hint:
16213 case OMPC_defaultmap:
16214 case OMPC_unknown:
16215 case OMPC_uniform:
16216 case OMPC_to:
16217 case OMPC_from:
16218 case OMPC_use_device_ptr:
16219 case OMPC_use_device_addr:
16220 case OMPC_is_device_ptr:
16221 case OMPC_unified_address:
16222 case OMPC_unified_shared_memory:
16223 case OMPC_reverse_offload:
16224 case OMPC_dynamic_allocators:
16225 case OMPC_atomic_default_mem_order:
16226 case OMPC_device_type:
16227 case OMPC_match:
16228 case OMPC_nontemporal:
16229 case OMPC_order:
16230 case OMPC_at:
16231 case OMPC_severity:
16232 case OMPC_message:
16233 case OMPC_destroy:
16234 case OMPC_detach:
16235 case OMPC_inclusive:
16236 case OMPC_exclusive:
16237 case OMPC_uses_allocators:
16238 case OMPC_affinity:
16239 case OMPC_bind:
16240 default:
16241 llvm_unreachable("Unexpected OpenMP clause.");
16242 }
16243 return CaptureRegion;
16244 }
16245
ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,Expr * Condition,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation NameModifierLoc,SourceLocation ColonLoc,SourceLocation EndLoc)16246 OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,
16247 Expr *Condition, SourceLocation StartLoc,
16248 SourceLocation LParenLoc,
16249 SourceLocation NameModifierLoc,
16250 SourceLocation ColonLoc,
16251 SourceLocation EndLoc) {
16252 Expr *ValExpr = Condition;
16253 Stmt *HelperValStmt = nullptr;
16254 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16255 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16256 !Condition->isInstantiationDependent() &&
16257 !Condition->containsUnexpandedParameterPack()) {
16258 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
16259 if (Val.isInvalid())
16260 return nullptr;
16261
16262 ValExpr = Val.get();
16263
16264 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16265 CaptureRegion = getOpenMPCaptureRegionForClause(
16266 DKind, OMPC_if, LangOpts.OpenMP, NameModifier);
16267 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16268 ValExpr = MakeFullExpr(ValExpr).get();
16269 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16270 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16271 HelperValStmt = buildPreInits(Context, Captures);
16272 }
16273 }
16274
16275 return new (Context)
16276 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16277 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16278 }
16279
ActOnOpenMPFinalClause(Expr * Condition,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16280 OMPClause *Sema::ActOnOpenMPFinalClause(Expr *Condition,
16281 SourceLocation StartLoc,
16282 SourceLocation LParenLoc,
16283 SourceLocation EndLoc) {
16284 Expr *ValExpr = Condition;
16285 Stmt *HelperValStmt = nullptr;
16286 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16287 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16288 !Condition->isInstantiationDependent() &&
16289 !Condition->containsUnexpandedParameterPack()) {
16290 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
16291 if (Val.isInvalid())
16292 return nullptr;
16293
16294 ValExpr = MakeFullExpr(Val.get()).get();
16295
16296 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16297 CaptureRegion =
16298 getOpenMPCaptureRegionForClause(DKind, OMPC_final, LangOpts.OpenMP);
16299 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16300 ValExpr = MakeFullExpr(ValExpr).get();
16301 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16302 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16303 HelperValStmt = buildPreInits(Context, Captures);
16304 }
16305 }
16306
16307 return new (Context) OMPFinalClause(ValExpr, HelperValStmt, CaptureRegion,
16308 StartLoc, LParenLoc, EndLoc);
16309 }
16310
PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,Expr * Op)16311 ExprResult Sema::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
16312 Expr *Op) {
16313 if (!Op)
16314 return ExprError();
16315
16316 class IntConvertDiagnoser : public ICEConvertDiagnoser {
16317 public:
16318 IntConvertDiagnoser()
16319 : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {}
16320 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
16321 QualType T) override {
16322 return S.Diag(Loc, diag::err_omp_not_integral) << T;
16323 }
16324 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
16325 QualType T) override {
16326 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
16327 }
16328 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
16329 QualType T,
16330 QualType ConvTy) override {
16331 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
16332 }
16333 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
16334 QualType ConvTy) override {
16335 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16336 << ConvTy->isEnumeralType() << ConvTy;
16337 }
16338 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
16339 QualType T) override {
16340 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
16341 }
16342 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
16343 QualType ConvTy) override {
16344 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16345 << ConvTy->isEnumeralType() << ConvTy;
16346 }
16347 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
16348 QualType) override {
16349 llvm_unreachable("conversion functions are permitted");
16350 }
16351 } ConvertDiagnoser;
16352 return PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16353 }
16354
16355 static bool
isNonNegativeIntegerValue(Expr * & ValExpr,Sema & SemaRef,OpenMPClauseKind CKind,bool StrictlyPositive,bool BuildCapture=false,OpenMPDirectiveKind DKind=OMPD_unknown,OpenMPDirectiveKind * CaptureRegion=nullptr,Stmt ** HelperValStmt=nullptr)16356 isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind,
16357 bool StrictlyPositive, bool BuildCapture = false,
16358 OpenMPDirectiveKind DKind = OMPD_unknown,
16359 OpenMPDirectiveKind *CaptureRegion = nullptr,
16360 Stmt **HelperValStmt = nullptr) {
16361 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
16362 !ValExpr->isInstantiationDependent()) {
16363 SourceLocation Loc = ValExpr->getExprLoc();
16364 ExprResult Value =
16365 SemaRef.PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
16366 if (Value.isInvalid())
16367 return false;
16368
16369 ValExpr = Value.get();
16370 // The expression must evaluate to a non-negative integer value.
16371 if (std::optional<llvm::APSInt> Result =
16372 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
16373 if (Result->isSigned() &&
16374 !((!StrictlyPositive && Result->isNonNegative()) ||
16375 (StrictlyPositive && Result->isStrictlyPositive()))) {
16376 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
16377 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16378 << ValExpr->getSourceRange();
16379 return false;
16380 }
16381 }
16382 if (!BuildCapture)
16383 return true;
16384 *CaptureRegion =
16385 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
16386 if (*CaptureRegion != OMPD_unknown &&
16387 !SemaRef.CurContext->isDependentContext()) {
16388 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16389 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16390 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16391 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
16392 }
16393 }
16394 return true;
16395 }
16396
ActOnOpenMPNumThreadsClause(Expr * NumThreads,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16397 OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
16398 SourceLocation StartLoc,
16399 SourceLocation LParenLoc,
16400 SourceLocation EndLoc) {
16401 Expr *ValExpr = NumThreads;
16402 Stmt *HelperValStmt = nullptr;
16403
16404 // OpenMP [2.5, Restrictions]
16405 // The num_threads expression must evaluate to a positive integer value.
16406 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_threads,
16407 /*StrictlyPositive=*/true))
16408 return nullptr;
16409
16410 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16411 OpenMPDirectiveKind CaptureRegion =
16412 getOpenMPCaptureRegionForClause(DKind, OMPC_num_threads, LangOpts.OpenMP);
16413 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16414 ValExpr = MakeFullExpr(ValExpr).get();
16415 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16416 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16417 HelperValStmt = buildPreInits(Context, Captures);
16418 }
16419
16420 return new (Context) OMPNumThreadsClause(
16421 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16422 }
16423
VerifyPositiveIntegerConstantInClause(Expr * E,OpenMPClauseKind CKind,bool StrictlyPositive,bool SuppressExprDiags)16424 ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
16425 OpenMPClauseKind CKind,
16426 bool StrictlyPositive,
16427 bool SuppressExprDiags) {
16428 if (!E)
16429 return ExprError();
16430 if (E->isValueDependent() || E->isTypeDependent() ||
16431 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
16432 return E;
16433
16434 llvm::APSInt Result;
16435 ExprResult ICE;
16436 if (SuppressExprDiags) {
16437 // Use a custom diagnoser that suppresses 'note' diagnostics about the
16438 // expression.
16439 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
16440 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
16441 Sema::SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
16442 SourceLocation Loc) override {
16443 llvm_unreachable("Diagnostic suppressed");
16444 }
16445 } Diagnoser;
16446 ICE = VerifyIntegerConstantExpression(E, &Result, Diagnoser, AllowFold);
16447 } else {
16448 ICE = VerifyIntegerConstantExpression(E, &Result, /*FIXME*/ AllowFold);
16449 }
16450 if (ICE.isInvalid())
16451 return ExprError();
16452
16453 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
16454 (!StrictlyPositive && !Result.isNonNegative())) {
16455 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
16456 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16457 << E->getSourceRange();
16458 return ExprError();
16459 }
16460 if ((CKind == OMPC_aligned || CKind == OMPC_align) && !Result.isPowerOf2()) {
16461 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
16462 << E->getSourceRange();
16463 return ExprError();
16464 }
16465 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
16466 DSAStack->setAssociatedLoops(Result.getExtValue());
16467 else if (CKind == OMPC_ordered)
16468 DSAStack->setAssociatedLoops(Result.getExtValue());
16469 return ICE;
16470 }
16471
ActOnOpenMPSafelenClause(Expr * Len,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16472 OMPClause *Sema::ActOnOpenMPSafelenClause(Expr *Len, SourceLocation StartLoc,
16473 SourceLocation LParenLoc,
16474 SourceLocation EndLoc) {
16475 // OpenMP [2.8.1, simd construct, Description]
16476 // The parameter of the safelen clause must be a constant
16477 // positive integer expression.
16478 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
16479 if (Safelen.isInvalid())
16480 return nullptr;
16481 return new (Context)
16482 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
16483 }
16484
ActOnOpenMPSimdlenClause(Expr * Len,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16485 OMPClause *Sema::ActOnOpenMPSimdlenClause(Expr *Len, SourceLocation StartLoc,
16486 SourceLocation LParenLoc,
16487 SourceLocation EndLoc) {
16488 // OpenMP [2.8.1, simd construct, Description]
16489 // The parameter of the simdlen clause must be a constant
16490 // positive integer expression.
16491 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
16492 if (Simdlen.isInvalid())
16493 return nullptr;
16494 return new (Context)
16495 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
16496 }
16497
16498 /// Tries to find omp_allocator_handle_t type.
findOMPAllocatorHandleT(Sema & S,SourceLocation Loc,DSAStackTy * Stack)16499 static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc,
16500 DSAStackTy *Stack) {
16501 if (!Stack->getOMPAllocatorHandleT().isNull())
16502 return true;
16503
16504 // Set the allocator handle type.
16505 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
16506 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
16507 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
16508 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16509 << "omp_allocator_handle_t";
16510 return false;
16511 }
16512 QualType AllocatorHandleEnumTy = PT.get();
16513 AllocatorHandleEnumTy.addConst();
16514 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
16515
16516 // Fill the predefined allocator map.
16517 bool ErrorFound = false;
16518 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
16519 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
16520 StringRef Allocator =
16521 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
16522 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
16523 auto *VD = dyn_cast_or_null<ValueDecl>(
16524 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
16525 if (!VD) {
16526 ErrorFound = true;
16527 break;
16528 }
16529 QualType AllocatorType =
16530 VD->getType().getNonLValueExprType(S.getASTContext());
16531 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
16532 if (!Res.isUsable()) {
16533 ErrorFound = true;
16534 break;
16535 }
16536 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
16537 Sema::AA_Initializing,
16538 /* AllowExplicit */ true);
16539 if (!Res.isUsable()) {
16540 ErrorFound = true;
16541 break;
16542 }
16543 Stack->setAllocator(AllocatorKind, Res.get());
16544 }
16545 if (ErrorFound) {
16546 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16547 << "omp_allocator_handle_t";
16548 return false;
16549 }
16550
16551 return true;
16552 }
16553
ActOnOpenMPAllocatorClause(Expr * A,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16554 OMPClause *Sema::ActOnOpenMPAllocatorClause(Expr *A, SourceLocation StartLoc,
16555 SourceLocation LParenLoc,
16556 SourceLocation EndLoc) {
16557 // OpenMP [2.11.3, allocate Directive, Description]
16558 // allocator is an expression of omp_allocator_handle_t type.
16559 if (!findOMPAllocatorHandleT(*this, A->getExprLoc(), DSAStack))
16560 return nullptr;
16561
16562 ExprResult Allocator = DefaultLvalueConversion(A);
16563 if (Allocator.isInvalid())
16564 return nullptr;
16565 Allocator = PerformImplicitConversion(Allocator.get(),
16566 DSAStack->getOMPAllocatorHandleT(),
16567 Sema::AA_Initializing,
16568 /*AllowExplicit=*/true);
16569 if (Allocator.isInvalid())
16570 return nullptr;
16571 return new (Context)
16572 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
16573 }
16574
ActOnOpenMPCollapseClause(Expr * NumForLoops,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16575 OMPClause *Sema::ActOnOpenMPCollapseClause(Expr *NumForLoops,
16576 SourceLocation StartLoc,
16577 SourceLocation LParenLoc,
16578 SourceLocation EndLoc) {
16579 // OpenMP [2.7.1, loop construct, Description]
16580 // OpenMP [2.8.1, simd construct, Description]
16581 // OpenMP [2.9.6, distribute construct, Description]
16582 // The parameter of the collapse clause must be a constant
16583 // positive integer expression.
16584 ExprResult NumForLoopsResult =
16585 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
16586 if (NumForLoopsResult.isInvalid())
16587 return nullptr;
16588 return new (Context)
16589 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
16590 }
16591
ActOnOpenMPOrderedClause(SourceLocation StartLoc,SourceLocation EndLoc,SourceLocation LParenLoc,Expr * NumForLoops)16592 OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
16593 SourceLocation EndLoc,
16594 SourceLocation LParenLoc,
16595 Expr *NumForLoops) {
16596 // OpenMP [2.7.1, loop construct, Description]
16597 // OpenMP [2.8.1, simd construct, Description]
16598 // OpenMP [2.9.6, distribute construct, Description]
16599 // The parameter of the ordered clause must be a constant
16600 // positive integer expression if any.
16601 if (NumForLoops && LParenLoc.isValid()) {
16602 ExprResult NumForLoopsResult =
16603 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
16604 if (NumForLoopsResult.isInvalid())
16605 return nullptr;
16606 NumForLoops = NumForLoopsResult.get();
16607 } else {
16608 NumForLoops = nullptr;
16609 }
16610 auto *Clause = OMPOrderedClause::Create(
16611 Context, NumForLoops, NumForLoops ? DSAStack->getAssociatedLoops() : 0,
16612 StartLoc, LParenLoc, EndLoc);
16613 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
16614 return Clause;
16615 }
16616
ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,unsigned Argument,SourceLocation ArgumentLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16617 OMPClause *Sema::ActOnOpenMPSimpleClause(
16618 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
16619 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16620 OMPClause *Res = nullptr;
16621 switch (Kind) {
16622 case OMPC_default:
16623 Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument),
16624 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16625 break;
16626 case OMPC_proc_bind:
16627 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
16628 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16629 break;
16630 case OMPC_atomic_default_mem_order:
16631 Res = ActOnOpenMPAtomicDefaultMemOrderClause(
16632 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
16633 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16634 break;
16635 case OMPC_update:
16636 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
16637 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16638 break;
16639 case OMPC_bind:
16640 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
16641 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16642 break;
16643 case OMPC_at:
16644 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
16645 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16646 break;
16647 case OMPC_severity:
16648 Res = ActOnOpenMPSeverityClause(
16649 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
16650 LParenLoc, EndLoc);
16651 break;
16652 case OMPC_if:
16653 case OMPC_final:
16654 case OMPC_num_threads:
16655 case OMPC_safelen:
16656 case OMPC_simdlen:
16657 case OMPC_sizes:
16658 case OMPC_allocator:
16659 case OMPC_collapse:
16660 case OMPC_schedule:
16661 case OMPC_private:
16662 case OMPC_firstprivate:
16663 case OMPC_lastprivate:
16664 case OMPC_shared:
16665 case OMPC_reduction:
16666 case OMPC_task_reduction:
16667 case OMPC_in_reduction:
16668 case OMPC_linear:
16669 case OMPC_aligned:
16670 case OMPC_copyin:
16671 case OMPC_copyprivate:
16672 case OMPC_ordered:
16673 case OMPC_nowait:
16674 case OMPC_untied:
16675 case OMPC_mergeable:
16676 case OMPC_threadprivate:
16677 case OMPC_allocate:
16678 case OMPC_flush:
16679 case OMPC_depobj:
16680 case OMPC_read:
16681 case OMPC_write:
16682 case OMPC_capture:
16683 case OMPC_compare:
16684 case OMPC_seq_cst:
16685 case OMPC_acq_rel:
16686 case OMPC_acquire:
16687 case OMPC_release:
16688 case OMPC_relaxed:
16689 case OMPC_depend:
16690 case OMPC_device:
16691 case OMPC_threads:
16692 case OMPC_simd:
16693 case OMPC_map:
16694 case OMPC_num_teams:
16695 case OMPC_thread_limit:
16696 case OMPC_priority:
16697 case OMPC_grainsize:
16698 case OMPC_nogroup:
16699 case OMPC_num_tasks:
16700 case OMPC_hint:
16701 case OMPC_dist_schedule:
16702 case OMPC_defaultmap:
16703 case OMPC_unknown:
16704 case OMPC_uniform:
16705 case OMPC_to:
16706 case OMPC_from:
16707 case OMPC_use_device_ptr:
16708 case OMPC_use_device_addr:
16709 case OMPC_is_device_ptr:
16710 case OMPC_has_device_addr:
16711 case OMPC_unified_address:
16712 case OMPC_unified_shared_memory:
16713 case OMPC_reverse_offload:
16714 case OMPC_dynamic_allocators:
16715 case OMPC_device_type:
16716 case OMPC_match:
16717 case OMPC_nontemporal:
16718 case OMPC_destroy:
16719 case OMPC_novariants:
16720 case OMPC_nocontext:
16721 case OMPC_detach:
16722 case OMPC_inclusive:
16723 case OMPC_exclusive:
16724 case OMPC_uses_allocators:
16725 case OMPC_affinity:
16726 case OMPC_when:
16727 case OMPC_message:
16728 default:
16729 llvm_unreachable("Clause is not allowed.");
16730 }
16731 return Res;
16732 }
16733
16734 static std::string
getListOfPossibleValues(OpenMPClauseKind K,unsigned First,unsigned Last,ArrayRef<unsigned> Exclude=std::nullopt)16735 getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last,
16736 ArrayRef<unsigned> Exclude = std::nullopt) {
16737 SmallString<256> Buffer;
16738 llvm::raw_svector_ostream Out(Buffer);
16739 unsigned Skipped = Exclude.size();
16740 for (unsigned I = First; I < Last; ++I) {
16741 if (llvm::is_contained(Exclude, I)) {
16742 --Skipped;
16743 continue;
16744 }
16745 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
16746 if (I + Skipped + 2 == Last)
16747 Out << " or ";
16748 else if (I + Skipped + 1 != Last)
16749 Out << ", ";
16750 }
16751 return std::string(Out.str());
16752 }
16753
ActOnOpenMPDefaultClause(DefaultKind Kind,SourceLocation KindKwLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16754 OMPClause *Sema::ActOnOpenMPDefaultClause(DefaultKind Kind,
16755 SourceLocation KindKwLoc,
16756 SourceLocation StartLoc,
16757 SourceLocation LParenLoc,
16758 SourceLocation EndLoc) {
16759 if (Kind == OMP_DEFAULT_unknown) {
16760 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16761 << getListOfPossibleValues(OMPC_default, /*First=*/0,
16762 /*Last=*/unsigned(OMP_DEFAULT_unknown))
16763 << getOpenMPClauseName(OMPC_default);
16764 return nullptr;
16765 }
16766
16767 switch (Kind) {
16768 case OMP_DEFAULT_none:
16769 DSAStack->setDefaultDSANone(KindKwLoc);
16770 break;
16771 case OMP_DEFAULT_shared:
16772 DSAStack->setDefaultDSAShared(KindKwLoc);
16773 break;
16774 case OMP_DEFAULT_firstprivate:
16775 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
16776 break;
16777 case OMP_DEFAULT_private:
16778 DSAStack->setDefaultDSAPrivate(KindKwLoc);
16779 break;
16780 default:
16781 llvm_unreachable("DSA unexpected in OpenMP default clause");
16782 }
16783
16784 return new (Context)
16785 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16786 }
16787
ActOnOpenMPProcBindClause(ProcBindKind Kind,SourceLocation KindKwLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16788 OMPClause *Sema::ActOnOpenMPProcBindClause(ProcBindKind Kind,
16789 SourceLocation KindKwLoc,
16790 SourceLocation StartLoc,
16791 SourceLocation LParenLoc,
16792 SourceLocation EndLoc) {
16793 if (Kind == OMP_PROC_BIND_unknown) {
16794 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16795 << getListOfPossibleValues(OMPC_proc_bind,
16796 /*First=*/unsigned(OMP_PROC_BIND_master),
16797 /*Last=*/
16798 unsigned(LangOpts.OpenMP > 50
16799 ? OMP_PROC_BIND_primary
16800 : OMP_PROC_BIND_spread) +
16801 1)
16802 << getOpenMPClauseName(OMPC_proc_bind);
16803 return nullptr;
16804 }
16805 if (Kind == OMP_PROC_BIND_primary && LangOpts.OpenMP < 51)
16806 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16807 << getListOfPossibleValues(OMPC_proc_bind,
16808 /*First=*/unsigned(OMP_PROC_BIND_master),
16809 /*Last=*/
16810 unsigned(OMP_PROC_BIND_spread) + 1)
16811 << getOpenMPClauseName(OMPC_proc_bind);
16812 return new (Context)
16813 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16814 }
16815
ActOnOpenMPAtomicDefaultMemOrderClause(OpenMPAtomicDefaultMemOrderClauseKind Kind,SourceLocation KindKwLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16816 OMPClause *Sema::ActOnOpenMPAtomicDefaultMemOrderClause(
16817 OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindKwLoc,
16818 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16819 if (Kind == OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) {
16820 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16821 << getListOfPossibleValues(
16822 OMPC_atomic_default_mem_order, /*First=*/0,
16823 /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown)
16824 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
16825 return nullptr;
16826 }
16827 return new (Context) OMPAtomicDefaultMemOrderClause(Kind, KindKwLoc, StartLoc,
16828 LParenLoc, EndLoc);
16829 }
16830
ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,SourceLocation KindKwLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16831 OMPClause *Sema::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
16832 SourceLocation KindKwLoc,
16833 SourceLocation StartLoc,
16834 SourceLocation LParenLoc,
16835 SourceLocation EndLoc) {
16836 if (Kind == OMPC_AT_unknown) {
16837 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16838 << getListOfPossibleValues(OMPC_at, /*First=*/0,
16839 /*Last=*/OMPC_AT_unknown)
16840 << getOpenMPClauseName(OMPC_at);
16841 return nullptr;
16842 }
16843 return new (Context)
16844 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16845 }
16846
ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,SourceLocation KindKwLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16847 OMPClause *Sema::ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,
16848 SourceLocation KindKwLoc,
16849 SourceLocation StartLoc,
16850 SourceLocation LParenLoc,
16851 SourceLocation EndLoc) {
16852 if (Kind == OMPC_SEVERITY_unknown) {
16853 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16854 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
16855 /*Last=*/OMPC_SEVERITY_unknown)
16856 << getOpenMPClauseName(OMPC_severity);
16857 return nullptr;
16858 }
16859 return new (Context)
16860 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16861 }
16862
ActOnOpenMPMessageClause(Expr * ME,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16863 OMPClause *Sema::ActOnOpenMPMessageClause(Expr *ME, SourceLocation StartLoc,
16864 SourceLocation LParenLoc,
16865 SourceLocation EndLoc) {
16866 assert(ME && "NULL expr in Message clause");
16867 if (!isa<StringLiteral>(ME)) {
16868 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
16869 << getOpenMPClauseName(OMPC_message);
16870 return nullptr;
16871 }
16872 return new (Context) OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc);
16873 }
16874
ActOnOpenMPOrderClause(OpenMPOrderClauseModifier Modifier,OpenMPOrderClauseKind Kind,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation MLoc,SourceLocation KindLoc,SourceLocation EndLoc)16875 OMPClause *Sema::ActOnOpenMPOrderClause(
16876 OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind,
16877 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
16878 SourceLocation KindLoc, SourceLocation EndLoc) {
16879 if (Kind != OMPC_ORDER_concurrent ||
16880 (LangOpts.OpenMP < 51 && MLoc.isValid())) {
16881 // Kind should be concurrent,
16882 // Modifiers introduced in OpenMP 5.1
16883 static_assert(OMPC_ORDER_unknown > 0,
16884 "OMPC_ORDER_unknown not greater than 0");
16885
16886 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16887 << getListOfPossibleValues(OMPC_order,
16888 /*First=*/0,
16889 /*Last=*/OMPC_ORDER_unknown)
16890 << getOpenMPClauseName(OMPC_order);
16891 return nullptr;
16892 }
16893 if (LangOpts.OpenMP >= 51) {
16894 if (Modifier == OMPC_ORDER_MODIFIER_unknown && MLoc.isValid()) {
16895 Diag(MLoc, diag::err_omp_unexpected_clause_value)
16896 << getListOfPossibleValues(OMPC_order,
16897 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
16898 /*Last=*/OMPC_ORDER_MODIFIER_last)
16899 << getOpenMPClauseName(OMPC_order);
16900 } else {
16901 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
16902 if (DSAStack->getCurScope()) {
16903 // mark the current scope with 'order' flag
16904 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
16905 DSAStack->getCurScope()->setFlags(existingFlags |
16906 Scope::OpenMPOrderClauseScope);
16907 }
16908 }
16909 }
16910 return new (Context) OMPOrderClause(Kind, KindLoc, StartLoc, LParenLoc,
16911 EndLoc, Modifier, MLoc);
16912 }
16913
ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind,SourceLocation KindKwLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16914 OMPClause *Sema::ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind,
16915 SourceLocation KindKwLoc,
16916 SourceLocation StartLoc,
16917 SourceLocation LParenLoc,
16918 SourceLocation EndLoc) {
16919 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
16920 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
16921 SmallVector<unsigned> Except = {
16922 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
16923 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
16924 if (LangOpts.OpenMP < 51)
16925 Except.push_back(OMPC_DEPEND_inoutset);
16926 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16927 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
16928 /*Last=*/OMPC_DEPEND_unknown, Except)
16929 << getOpenMPClauseName(OMPC_update);
16930 return nullptr;
16931 }
16932 return OMPUpdateClause::Create(Context, StartLoc, LParenLoc, KindKwLoc, Kind,
16933 EndLoc);
16934 }
16935
ActOnOpenMPSizesClause(ArrayRef<Expr * > SizeExprs,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16936 OMPClause *Sema::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs,
16937 SourceLocation StartLoc,
16938 SourceLocation LParenLoc,
16939 SourceLocation EndLoc) {
16940 for (Expr *SizeExpr : SizeExprs) {
16941 ExprResult NumForLoopsResult = VerifyPositiveIntegerConstantInClause(
16942 SizeExpr, OMPC_sizes, /*StrictlyPositive=*/true);
16943 if (!NumForLoopsResult.isUsable())
16944 return nullptr;
16945 }
16946
16947 DSAStack->setAssociatedLoops(SizeExprs.size());
16948 return OMPSizesClause::Create(Context, StartLoc, LParenLoc, EndLoc,
16949 SizeExprs);
16950 }
16951
ActOnOpenMPFullClause(SourceLocation StartLoc,SourceLocation EndLoc)16952 OMPClause *Sema::ActOnOpenMPFullClause(SourceLocation StartLoc,
16953 SourceLocation EndLoc) {
16954 return OMPFullClause::Create(Context, StartLoc, EndLoc);
16955 }
16956
ActOnOpenMPPartialClause(Expr * FactorExpr,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16957 OMPClause *Sema::ActOnOpenMPPartialClause(Expr *FactorExpr,
16958 SourceLocation StartLoc,
16959 SourceLocation LParenLoc,
16960 SourceLocation EndLoc) {
16961 if (FactorExpr) {
16962 // If an argument is specified, it must be a constant (or an unevaluated
16963 // template expression).
16964 ExprResult FactorResult = VerifyPositiveIntegerConstantInClause(
16965 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
16966 if (FactorResult.isInvalid())
16967 return nullptr;
16968 FactorExpr = FactorResult.get();
16969 }
16970
16971 return OMPPartialClause::Create(Context, StartLoc, LParenLoc, EndLoc,
16972 FactorExpr);
16973 }
16974
ActOnOpenMPAlignClause(Expr * A,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)16975 OMPClause *Sema::ActOnOpenMPAlignClause(Expr *A, SourceLocation StartLoc,
16976 SourceLocation LParenLoc,
16977 SourceLocation EndLoc) {
16978 ExprResult AlignVal;
16979 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
16980 if (AlignVal.isInvalid())
16981 return nullptr;
16982 return OMPAlignClause::Create(Context, AlignVal.get(), StartLoc, LParenLoc,
16983 EndLoc);
16984 }
16985
ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,ArrayRef<unsigned> Argument,Expr * Expr,SourceLocation StartLoc,SourceLocation LParenLoc,ArrayRef<SourceLocation> ArgumentLoc,SourceLocation DelimLoc,SourceLocation EndLoc)16986 OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
16987 OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,
16988 SourceLocation StartLoc, SourceLocation LParenLoc,
16989 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
16990 SourceLocation EndLoc) {
16991 OMPClause *Res = nullptr;
16992 switch (Kind) {
16993 case OMPC_schedule:
16994 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
16995 assert(Argument.size() == NumberOfElements &&
16996 ArgumentLoc.size() == NumberOfElements);
16997 Res = ActOnOpenMPScheduleClause(
16998 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
16999 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
17000 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
17001 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
17002 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
17003 break;
17004 case OMPC_if:
17005 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17006 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
17007 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
17008 DelimLoc, EndLoc);
17009 break;
17010 case OMPC_dist_schedule:
17011 Res = ActOnOpenMPDistScheduleClause(
17012 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
17013 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
17014 break;
17015 case OMPC_defaultmap:
17016 enum { Modifier, DefaultmapKind };
17017 Res = ActOnOpenMPDefaultmapClause(
17018 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
17019 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
17020 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
17021 EndLoc);
17022 break;
17023 case OMPC_order:
17024 enum { OrderModifier, OrderKind };
17025 Res = ActOnOpenMPOrderClause(
17026 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
17027 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
17028 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
17029 break;
17030 case OMPC_device:
17031 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17032 Res = ActOnOpenMPDeviceClause(
17033 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
17034 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17035 break;
17036 case OMPC_grainsize:
17037 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17038 "Modifier for grainsize clause and its location are expected.");
17039 Res = ActOnOpenMPGrainsizeClause(
17040 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
17041 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17042 break;
17043 case OMPC_num_tasks:
17044 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17045 "Modifier for num_tasks clause and its location are expected.");
17046 Res = ActOnOpenMPNumTasksClause(
17047 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
17048 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17049 break;
17050 case OMPC_final:
17051 case OMPC_num_threads:
17052 case OMPC_safelen:
17053 case OMPC_simdlen:
17054 case OMPC_sizes:
17055 case OMPC_allocator:
17056 case OMPC_collapse:
17057 case OMPC_default:
17058 case OMPC_proc_bind:
17059 case OMPC_private:
17060 case OMPC_firstprivate:
17061 case OMPC_lastprivate:
17062 case OMPC_shared:
17063 case OMPC_reduction:
17064 case OMPC_task_reduction:
17065 case OMPC_in_reduction:
17066 case OMPC_linear:
17067 case OMPC_aligned:
17068 case OMPC_copyin:
17069 case OMPC_copyprivate:
17070 case OMPC_ordered:
17071 case OMPC_nowait:
17072 case OMPC_untied:
17073 case OMPC_mergeable:
17074 case OMPC_threadprivate:
17075 case OMPC_allocate:
17076 case OMPC_flush:
17077 case OMPC_depobj:
17078 case OMPC_read:
17079 case OMPC_write:
17080 case OMPC_update:
17081 case OMPC_capture:
17082 case OMPC_compare:
17083 case OMPC_seq_cst:
17084 case OMPC_acq_rel:
17085 case OMPC_acquire:
17086 case OMPC_release:
17087 case OMPC_relaxed:
17088 case OMPC_depend:
17089 case OMPC_threads:
17090 case OMPC_simd:
17091 case OMPC_map:
17092 case OMPC_num_teams:
17093 case OMPC_thread_limit:
17094 case OMPC_priority:
17095 case OMPC_nogroup:
17096 case OMPC_hint:
17097 case OMPC_unknown:
17098 case OMPC_uniform:
17099 case OMPC_to:
17100 case OMPC_from:
17101 case OMPC_use_device_ptr:
17102 case OMPC_use_device_addr:
17103 case OMPC_is_device_ptr:
17104 case OMPC_has_device_addr:
17105 case OMPC_unified_address:
17106 case OMPC_unified_shared_memory:
17107 case OMPC_reverse_offload:
17108 case OMPC_dynamic_allocators:
17109 case OMPC_atomic_default_mem_order:
17110 case OMPC_device_type:
17111 case OMPC_match:
17112 case OMPC_nontemporal:
17113 case OMPC_at:
17114 case OMPC_severity:
17115 case OMPC_message:
17116 case OMPC_destroy:
17117 case OMPC_novariants:
17118 case OMPC_nocontext:
17119 case OMPC_detach:
17120 case OMPC_inclusive:
17121 case OMPC_exclusive:
17122 case OMPC_uses_allocators:
17123 case OMPC_affinity:
17124 case OMPC_when:
17125 case OMPC_bind:
17126 default:
17127 llvm_unreachable("Clause is not allowed.");
17128 }
17129 return Res;
17130 }
17131
checkScheduleModifiers(Sema & S,OpenMPScheduleClauseModifier M1,OpenMPScheduleClauseModifier M2,SourceLocation M1Loc,SourceLocation M2Loc)17132 static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1,
17133 OpenMPScheduleClauseModifier M2,
17134 SourceLocation M1Loc, SourceLocation M2Loc) {
17135 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
17136 SmallVector<unsigned, 2> Excluded;
17137 if (M2 != OMPC_SCHEDULE_MODIFIER_unknown)
17138 Excluded.push_back(M2);
17139 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
17140 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
17141 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
17142 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
17143 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
17144 << getListOfPossibleValues(OMPC_schedule,
17145 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
17146 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
17147 Excluded)
17148 << getOpenMPClauseName(OMPC_schedule);
17149 return true;
17150 }
17151 return false;
17152 }
17153
ActOnOpenMPScheduleClause(OpenMPScheduleClauseModifier M1,OpenMPScheduleClauseModifier M2,OpenMPScheduleClauseKind Kind,Expr * ChunkSize,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation M1Loc,SourceLocation M2Loc,SourceLocation KindLoc,SourceLocation CommaLoc,SourceLocation EndLoc)17154 OMPClause *Sema::ActOnOpenMPScheduleClause(
17155 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
17156 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
17157 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
17158 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
17159 if (checkScheduleModifiers(*this, M1, M2, M1Loc, M2Loc) ||
17160 checkScheduleModifiers(*this, M2, M1, M2Loc, M1Loc))
17161 return nullptr;
17162 // OpenMP, 2.7.1, Loop Construct, Restrictions
17163 // Either the monotonic modifier or the nonmonotonic modifier can be specified
17164 // but not both.
17165 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
17166 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
17167 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
17168 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
17169 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
17170 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
17171 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
17172 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
17173 return nullptr;
17174 }
17175 if (Kind == OMPC_SCHEDULE_unknown) {
17176 std::string Values;
17177 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
17178 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
17179 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17180 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
17181 Exclude);
17182 } else {
17183 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17184 /*Last=*/OMPC_SCHEDULE_unknown);
17185 }
17186 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17187 << Values << getOpenMPClauseName(OMPC_schedule);
17188 return nullptr;
17189 }
17190 // OpenMP, 2.7.1, Loop Construct, Restrictions
17191 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
17192 // schedule(guided).
17193 // OpenMP 5.0 does not have this restriction.
17194 if (LangOpts.OpenMP < 50 &&
17195 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
17196 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
17197 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
17198 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
17199 diag::err_omp_schedule_nonmonotonic_static);
17200 return nullptr;
17201 }
17202 Expr *ValExpr = ChunkSize;
17203 Stmt *HelperValStmt = nullptr;
17204 if (ChunkSize) {
17205 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
17206 !ChunkSize->isInstantiationDependent() &&
17207 !ChunkSize->containsUnexpandedParameterPack()) {
17208 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
17209 ExprResult Val =
17210 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
17211 if (Val.isInvalid())
17212 return nullptr;
17213
17214 ValExpr = Val.get();
17215
17216 // OpenMP [2.7.1, Restrictions]
17217 // chunk_size must be a loop invariant integer expression with a positive
17218 // value.
17219 if (std::optional<llvm::APSInt> Result =
17220 ValExpr->getIntegerConstantExpr(Context)) {
17221 if (Result->isSigned() && !Result->isStrictlyPositive()) {
17222 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
17223 << "schedule" << 1 << ChunkSize->getSourceRange();
17224 return nullptr;
17225 }
17226 } else if (getOpenMPCaptureRegionForClause(
17227 DSAStack->getCurrentDirective(), OMPC_schedule,
17228 LangOpts.OpenMP) != OMPD_unknown &&
17229 !CurContext->isDependentContext()) {
17230 ValExpr = MakeFullExpr(ValExpr).get();
17231 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17232 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17233 HelperValStmt = buildPreInits(Context, Captures);
17234 }
17235 }
17236 }
17237
17238 return new (Context)
17239 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
17240 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
17241 }
17242
ActOnOpenMPClause(OpenMPClauseKind Kind,SourceLocation StartLoc,SourceLocation EndLoc)17243 OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
17244 SourceLocation StartLoc,
17245 SourceLocation EndLoc) {
17246 OMPClause *Res = nullptr;
17247 switch (Kind) {
17248 case OMPC_ordered:
17249 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
17250 break;
17251 case OMPC_nowait:
17252 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
17253 break;
17254 case OMPC_untied:
17255 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
17256 break;
17257 case OMPC_mergeable:
17258 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
17259 break;
17260 case OMPC_read:
17261 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
17262 break;
17263 case OMPC_write:
17264 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
17265 break;
17266 case OMPC_update:
17267 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
17268 break;
17269 case OMPC_capture:
17270 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
17271 break;
17272 case OMPC_compare:
17273 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
17274 break;
17275 case OMPC_seq_cst:
17276 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
17277 break;
17278 case OMPC_acq_rel:
17279 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
17280 break;
17281 case OMPC_acquire:
17282 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
17283 break;
17284 case OMPC_release:
17285 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
17286 break;
17287 case OMPC_relaxed:
17288 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
17289 break;
17290 case OMPC_threads:
17291 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
17292 break;
17293 case OMPC_simd:
17294 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
17295 break;
17296 case OMPC_nogroup:
17297 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
17298 break;
17299 case OMPC_unified_address:
17300 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
17301 break;
17302 case OMPC_unified_shared_memory:
17303 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17304 break;
17305 case OMPC_reverse_offload:
17306 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
17307 break;
17308 case OMPC_dynamic_allocators:
17309 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
17310 break;
17311 case OMPC_destroy:
17312 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
17313 /*LParenLoc=*/SourceLocation(),
17314 /*VarLoc=*/SourceLocation(), EndLoc);
17315 break;
17316 case OMPC_full:
17317 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
17318 break;
17319 case OMPC_partial:
17320 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
17321 break;
17322 case OMPC_if:
17323 case OMPC_final:
17324 case OMPC_num_threads:
17325 case OMPC_safelen:
17326 case OMPC_simdlen:
17327 case OMPC_sizes:
17328 case OMPC_allocator:
17329 case OMPC_collapse:
17330 case OMPC_schedule:
17331 case OMPC_private:
17332 case OMPC_firstprivate:
17333 case OMPC_lastprivate:
17334 case OMPC_shared:
17335 case OMPC_reduction:
17336 case OMPC_task_reduction:
17337 case OMPC_in_reduction:
17338 case OMPC_linear:
17339 case OMPC_aligned:
17340 case OMPC_copyin:
17341 case OMPC_copyprivate:
17342 case OMPC_default:
17343 case OMPC_proc_bind:
17344 case OMPC_threadprivate:
17345 case OMPC_allocate:
17346 case OMPC_flush:
17347 case OMPC_depobj:
17348 case OMPC_depend:
17349 case OMPC_device:
17350 case OMPC_map:
17351 case OMPC_num_teams:
17352 case OMPC_thread_limit:
17353 case OMPC_priority:
17354 case OMPC_grainsize:
17355 case OMPC_num_tasks:
17356 case OMPC_hint:
17357 case OMPC_dist_schedule:
17358 case OMPC_defaultmap:
17359 case OMPC_unknown:
17360 case OMPC_uniform:
17361 case OMPC_to:
17362 case OMPC_from:
17363 case OMPC_use_device_ptr:
17364 case OMPC_use_device_addr:
17365 case OMPC_is_device_ptr:
17366 case OMPC_has_device_addr:
17367 case OMPC_atomic_default_mem_order:
17368 case OMPC_device_type:
17369 case OMPC_match:
17370 case OMPC_nontemporal:
17371 case OMPC_order:
17372 case OMPC_at:
17373 case OMPC_severity:
17374 case OMPC_message:
17375 case OMPC_novariants:
17376 case OMPC_nocontext:
17377 case OMPC_detach:
17378 case OMPC_inclusive:
17379 case OMPC_exclusive:
17380 case OMPC_uses_allocators:
17381 case OMPC_affinity:
17382 case OMPC_when:
17383 case OMPC_ompx_dyn_cgroup_mem:
17384 default:
17385 llvm_unreachable("Clause is not allowed.");
17386 }
17387 return Res;
17388 }
17389
ActOnOpenMPNowaitClause(SourceLocation StartLoc,SourceLocation EndLoc)17390 OMPClause *Sema::ActOnOpenMPNowaitClause(SourceLocation StartLoc,
17391 SourceLocation EndLoc) {
17392 DSAStack->setNowaitRegion();
17393 return new (Context) OMPNowaitClause(StartLoc, EndLoc);
17394 }
17395
ActOnOpenMPUntiedClause(SourceLocation StartLoc,SourceLocation EndLoc)17396 OMPClause *Sema::ActOnOpenMPUntiedClause(SourceLocation StartLoc,
17397 SourceLocation EndLoc) {
17398 DSAStack->setUntiedRegion();
17399 return new (Context) OMPUntiedClause(StartLoc, EndLoc);
17400 }
17401
ActOnOpenMPMergeableClause(SourceLocation StartLoc,SourceLocation EndLoc)17402 OMPClause *Sema::ActOnOpenMPMergeableClause(SourceLocation StartLoc,
17403 SourceLocation EndLoc) {
17404 return new (Context) OMPMergeableClause(StartLoc, EndLoc);
17405 }
17406
ActOnOpenMPReadClause(SourceLocation StartLoc,SourceLocation EndLoc)17407 OMPClause *Sema::ActOnOpenMPReadClause(SourceLocation StartLoc,
17408 SourceLocation EndLoc) {
17409 return new (Context) OMPReadClause(StartLoc, EndLoc);
17410 }
17411
ActOnOpenMPWriteClause(SourceLocation StartLoc,SourceLocation EndLoc)17412 OMPClause *Sema::ActOnOpenMPWriteClause(SourceLocation StartLoc,
17413 SourceLocation EndLoc) {
17414 return new (Context) OMPWriteClause(StartLoc, EndLoc);
17415 }
17416
ActOnOpenMPUpdateClause(SourceLocation StartLoc,SourceLocation EndLoc)17417 OMPClause *Sema::ActOnOpenMPUpdateClause(SourceLocation StartLoc,
17418 SourceLocation EndLoc) {
17419 return OMPUpdateClause::Create(Context, StartLoc, EndLoc);
17420 }
17421
ActOnOpenMPCaptureClause(SourceLocation StartLoc,SourceLocation EndLoc)17422 OMPClause *Sema::ActOnOpenMPCaptureClause(SourceLocation StartLoc,
17423 SourceLocation EndLoc) {
17424 return new (Context) OMPCaptureClause(StartLoc, EndLoc);
17425 }
17426
ActOnOpenMPCompareClause(SourceLocation StartLoc,SourceLocation EndLoc)17427 OMPClause *Sema::ActOnOpenMPCompareClause(SourceLocation StartLoc,
17428 SourceLocation EndLoc) {
17429 return new (Context) OMPCompareClause(StartLoc, EndLoc);
17430 }
17431
ActOnOpenMPSeqCstClause(SourceLocation StartLoc,SourceLocation EndLoc)17432 OMPClause *Sema::ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
17433 SourceLocation EndLoc) {
17434 return new (Context) OMPSeqCstClause(StartLoc, EndLoc);
17435 }
17436
ActOnOpenMPAcqRelClause(SourceLocation StartLoc,SourceLocation EndLoc)17437 OMPClause *Sema::ActOnOpenMPAcqRelClause(SourceLocation StartLoc,
17438 SourceLocation EndLoc) {
17439 return new (Context) OMPAcqRelClause(StartLoc, EndLoc);
17440 }
17441
ActOnOpenMPAcquireClause(SourceLocation StartLoc,SourceLocation EndLoc)17442 OMPClause *Sema::ActOnOpenMPAcquireClause(SourceLocation StartLoc,
17443 SourceLocation EndLoc) {
17444 return new (Context) OMPAcquireClause(StartLoc, EndLoc);
17445 }
17446
ActOnOpenMPReleaseClause(SourceLocation StartLoc,SourceLocation EndLoc)17447 OMPClause *Sema::ActOnOpenMPReleaseClause(SourceLocation StartLoc,
17448 SourceLocation EndLoc) {
17449 return new (Context) OMPReleaseClause(StartLoc, EndLoc);
17450 }
17451
ActOnOpenMPRelaxedClause(SourceLocation StartLoc,SourceLocation EndLoc)17452 OMPClause *Sema::ActOnOpenMPRelaxedClause(SourceLocation StartLoc,
17453 SourceLocation EndLoc) {
17454 return new (Context) OMPRelaxedClause(StartLoc, EndLoc);
17455 }
17456
ActOnOpenMPThreadsClause(SourceLocation StartLoc,SourceLocation EndLoc)17457 OMPClause *Sema::ActOnOpenMPThreadsClause(SourceLocation StartLoc,
17458 SourceLocation EndLoc) {
17459 return new (Context) OMPThreadsClause(StartLoc, EndLoc);
17460 }
17461
ActOnOpenMPSIMDClause(SourceLocation StartLoc,SourceLocation EndLoc)17462 OMPClause *Sema::ActOnOpenMPSIMDClause(SourceLocation StartLoc,
17463 SourceLocation EndLoc) {
17464 return new (Context) OMPSIMDClause(StartLoc, EndLoc);
17465 }
17466
ActOnOpenMPNogroupClause(SourceLocation StartLoc,SourceLocation EndLoc)17467 OMPClause *Sema::ActOnOpenMPNogroupClause(SourceLocation StartLoc,
17468 SourceLocation EndLoc) {
17469 return new (Context) OMPNogroupClause(StartLoc, EndLoc);
17470 }
17471
ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,SourceLocation EndLoc)17472 OMPClause *Sema::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,
17473 SourceLocation EndLoc) {
17474 return new (Context) OMPUnifiedAddressClause(StartLoc, EndLoc);
17475 }
17476
ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,SourceLocation EndLoc)17477 OMPClause *Sema::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
17478 SourceLocation EndLoc) {
17479 return new (Context) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17480 }
17481
ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,SourceLocation EndLoc)17482 OMPClause *Sema::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
17483 SourceLocation EndLoc) {
17484 return new (Context) OMPReverseOffloadClause(StartLoc, EndLoc);
17485 }
17486
ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,SourceLocation EndLoc)17487 OMPClause *Sema::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,
17488 SourceLocation EndLoc) {
17489 return new (Context) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
17490 }
17491
ActOnOpenMPInteropDirective(ArrayRef<OMPClause * > Clauses,SourceLocation StartLoc,SourceLocation EndLoc)17492 StmtResult Sema::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
17493 SourceLocation StartLoc,
17494 SourceLocation EndLoc) {
17495
17496 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17497 // At least one action-clause must appear on a directive.
17498 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
17499 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
17500 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
17501 << Expected << getOpenMPDirectiveName(OMPD_interop);
17502 return StmtError();
17503 }
17504
17505 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17506 // A depend clause can only appear on the directive if a targetsync
17507 // interop-type is present or the interop-var was initialized with
17508 // the targetsync interop-type.
17509
17510 // If there is any 'init' clause diagnose if there is no 'init' clause with
17511 // interop-type of 'targetsync'. Cases involving other directives cannot be
17512 // diagnosed.
17513 const OMPDependClause *DependClause = nullptr;
17514 bool HasInitClause = false;
17515 bool IsTargetSync = false;
17516 for (const OMPClause *C : Clauses) {
17517 if (IsTargetSync)
17518 break;
17519 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
17520 HasInitClause = true;
17521 if (InitClause->getIsTargetSync())
17522 IsTargetSync = true;
17523 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
17524 DependClause = DC;
17525 }
17526 }
17527 if (DependClause && HasInitClause && !IsTargetSync) {
17528 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
17529 return StmtError();
17530 }
17531
17532 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17533 // Each interop-var may be specified for at most one action-clause of each
17534 // interop construct.
17535 llvm::SmallPtrSet<const ValueDecl *, 4> InteropVars;
17536 for (OMPClause *C : Clauses) {
17537 OpenMPClauseKind ClauseKind = C->getClauseKind();
17538 std::pair<ValueDecl *, bool> DeclResult;
17539 SourceLocation ELoc;
17540 SourceRange ERange;
17541
17542 if (ClauseKind == OMPC_init) {
17543 auto *E = cast<OMPInitClause>(C)->getInteropVar();
17544 DeclResult = getPrivateItem(*this, E, ELoc, ERange);
17545 } else if (ClauseKind == OMPC_use) {
17546 auto *E = cast<OMPUseClause>(C)->getInteropVar();
17547 DeclResult = getPrivateItem(*this, E, ELoc, ERange);
17548 } else if (ClauseKind == OMPC_destroy) {
17549 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
17550 DeclResult = getPrivateItem(*this, E, ELoc, ERange);
17551 }
17552
17553 if (DeclResult.first) {
17554 if (!InteropVars.insert(DeclResult.first).second) {
17555 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
17556 << DeclResult.first;
17557 return StmtError();
17558 }
17559 }
17560 }
17561
17562 return OMPInteropDirective::Create(Context, StartLoc, EndLoc, Clauses);
17563 }
17564
isValidInteropVariable(Sema & SemaRef,Expr * InteropVarExpr,SourceLocation VarLoc,OpenMPClauseKind Kind)17565 static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
17566 SourceLocation VarLoc,
17567 OpenMPClauseKind Kind) {
17568 SourceLocation ELoc;
17569 SourceRange ERange;
17570 Expr *RefExpr = InteropVarExpr;
17571 auto Res =
17572 getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
17573 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
17574
17575 if (Res.second) {
17576 // It will be analyzed later.
17577 return true;
17578 }
17579
17580 if (!Res.first)
17581 return false;
17582
17583 // Interop variable should be of type omp_interop_t.
17584 bool HasError = false;
17585 QualType InteropType;
17586 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
17587 VarLoc, Sema::LookupOrdinaryName);
17588 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
17589 NamedDecl *ND = Result.getFoundDecl();
17590 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
17591 InteropType = QualType(TD->getTypeForDecl(), 0);
17592 } else {
17593 HasError = true;
17594 }
17595 } else {
17596 HasError = true;
17597 }
17598
17599 if (HasError) {
17600 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
17601 << "omp_interop_t";
17602 return false;
17603 }
17604
17605 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
17606 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
17607 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
17608 return false;
17609 }
17610
17611 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17612 // The interop-var passed to init or destroy must be non-const.
17613 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
17614 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
17615 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
17616 << /*non-const*/ 1;
17617 return false;
17618 }
17619 return true;
17620 }
17621
17622 OMPClause *
ActOnOpenMPInitClause(Expr * InteropVar,OMPInteropInfo & InteropInfo,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation VarLoc,SourceLocation EndLoc)17623 Sema::ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo,
17624 SourceLocation StartLoc, SourceLocation LParenLoc,
17625 SourceLocation VarLoc, SourceLocation EndLoc) {
17626
17627 if (!isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_init))
17628 return nullptr;
17629
17630 // Check prefer_type values. These foreign-runtime-id values are either
17631 // string literals or constant integral expressions.
17632 for (const Expr *E : InteropInfo.PreferTypes) {
17633 if (E->isValueDependent() || E->isTypeDependent() ||
17634 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
17635 continue;
17636 if (E->isIntegerConstantExpr(Context))
17637 continue;
17638 if (isa<StringLiteral>(E))
17639 continue;
17640 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
17641 return nullptr;
17642 }
17643
17644 return OMPInitClause::Create(Context, InteropVar, InteropInfo, StartLoc,
17645 LParenLoc, VarLoc, EndLoc);
17646 }
17647
ActOnOpenMPUseClause(Expr * InteropVar,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation VarLoc,SourceLocation EndLoc)17648 OMPClause *Sema::ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc,
17649 SourceLocation LParenLoc,
17650 SourceLocation VarLoc,
17651 SourceLocation EndLoc) {
17652
17653 if (!isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_use))
17654 return nullptr;
17655
17656 return new (Context)
17657 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17658 }
17659
ActOnOpenMPDestroyClause(Expr * InteropVar,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation VarLoc,SourceLocation EndLoc)17660 OMPClause *Sema::ActOnOpenMPDestroyClause(Expr *InteropVar,
17661 SourceLocation StartLoc,
17662 SourceLocation LParenLoc,
17663 SourceLocation VarLoc,
17664 SourceLocation EndLoc) {
17665 if (InteropVar &&
17666 !isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_destroy))
17667 return nullptr;
17668
17669 return new (Context)
17670 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17671 }
17672
ActOnOpenMPNovariantsClause(Expr * Condition,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)17673 OMPClause *Sema::ActOnOpenMPNovariantsClause(Expr *Condition,
17674 SourceLocation StartLoc,
17675 SourceLocation LParenLoc,
17676 SourceLocation EndLoc) {
17677 Expr *ValExpr = Condition;
17678 Stmt *HelperValStmt = nullptr;
17679 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17680 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17681 !Condition->isInstantiationDependent() &&
17682 !Condition->containsUnexpandedParameterPack()) {
17683 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
17684 if (Val.isInvalid())
17685 return nullptr;
17686
17687 ValExpr = MakeFullExpr(Val.get()).get();
17688
17689 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17690 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
17691 LangOpts.OpenMP);
17692 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
17693 ValExpr = MakeFullExpr(ValExpr).get();
17694 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17695 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17696 HelperValStmt = buildPreInits(Context, Captures);
17697 }
17698 }
17699
17700 return new (Context) OMPNovariantsClause(
17701 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17702 }
17703
ActOnOpenMPNocontextClause(Expr * Condition,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)17704 OMPClause *Sema::ActOnOpenMPNocontextClause(Expr *Condition,
17705 SourceLocation StartLoc,
17706 SourceLocation LParenLoc,
17707 SourceLocation EndLoc) {
17708 Expr *ValExpr = Condition;
17709 Stmt *HelperValStmt = nullptr;
17710 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17711 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17712 !Condition->isInstantiationDependent() &&
17713 !Condition->containsUnexpandedParameterPack()) {
17714 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
17715 if (Val.isInvalid())
17716 return nullptr;
17717
17718 ValExpr = MakeFullExpr(Val.get()).get();
17719
17720 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17721 CaptureRegion =
17722 getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext, LangOpts.OpenMP);
17723 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
17724 ValExpr = MakeFullExpr(ValExpr).get();
17725 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17726 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17727 HelperValStmt = buildPreInits(Context, Captures);
17728 }
17729 }
17730
17731 return new (Context) OMPNocontextClause(ValExpr, HelperValStmt, CaptureRegion,
17732 StartLoc, LParenLoc, EndLoc);
17733 }
17734
ActOnOpenMPFilterClause(Expr * ThreadID,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)17735 OMPClause *Sema::ActOnOpenMPFilterClause(Expr *ThreadID,
17736 SourceLocation StartLoc,
17737 SourceLocation LParenLoc,
17738 SourceLocation EndLoc) {
17739 Expr *ValExpr = ThreadID;
17740 Stmt *HelperValStmt = nullptr;
17741
17742 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17743 OpenMPDirectiveKind CaptureRegion =
17744 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, LangOpts.OpenMP);
17745 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
17746 ValExpr = MakeFullExpr(ValExpr).get();
17747 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17748 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17749 HelperValStmt = buildPreInits(Context, Captures);
17750 }
17751
17752 return new (Context) OMPFilterClause(ValExpr, HelperValStmt, CaptureRegion,
17753 StartLoc, LParenLoc, EndLoc);
17754 }
17755
ActOnOpenMPVarListClause(OpenMPClauseKind Kind,ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs,OpenMPVarListDataTy & Data)17756 OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
17757 ArrayRef<Expr *> VarList,
17758 const OMPVarListLocTy &Locs,
17759 OpenMPVarListDataTy &Data) {
17760 SourceLocation StartLoc = Locs.StartLoc;
17761 SourceLocation LParenLoc = Locs.LParenLoc;
17762 SourceLocation EndLoc = Locs.EndLoc;
17763 OMPClause *Res = nullptr;
17764 int ExtraModifier = Data.ExtraModifier;
17765 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
17766 SourceLocation ColonLoc = Data.ColonLoc;
17767 switch (Kind) {
17768 case OMPC_private:
17769 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17770 break;
17771 case OMPC_firstprivate:
17772 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17773 break;
17774 case OMPC_lastprivate:
17775 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
17776 "Unexpected lastprivate modifier.");
17777 Res = ActOnOpenMPLastprivateClause(
17778 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
17779 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
17780 break;
17781 case OMPC_shared:
17782 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
17783 break;
17784 case OMPC_reduction:
17785 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
17786 "Unexpected lastprivate modifier.");
17787 Res = ActOnOpenMPReductionClause(
17788 VarList, static_cast<OpenMPReductionClauseModifier>(ExtraModifier),
17789 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
17790 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17791 break;
17792 case OMPC_task_reduction:
17793 Res = ActOnOpenMPTaskReductionClause(
17794 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17795 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17796 break;
17797 case OMPC_in_reduction:
17798 Res = ActOnOpenMPInReductionClause(
17799 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17800 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17801 break;
17802 case OMPC_linear:
17803 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
17804 "Unexpected linear modifier.");
17805 Res = ActOnOpenMPLinearClause(
17806 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
17807 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
17808 ColonLoc, EndLoc);
17809 break;
17810 case OMPC_aligned:
17811 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
17812 LParenLoc, ColonLoc, EndLoc);
17813 break;
17814 case OMPC_copyin:
17815 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
17816 break;
17817 case OMPC_copyprivate:
17818 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17819 break;
17820 case OMPC_flush:
17821 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
17822 break;
17823 case OMPC_depend:
17824 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
17825 "Unexpected depend modifier.");
17826 Res = ActOnOpenMPDependClause(
17827 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
17828 ColonLoc, Data.OmpAllMemoryLoc},
17829 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
17830 break;
17831 case OMPC_map:
17832 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
17833 "Unexpected map modifier.");
17834 Res = ActOnOpenMPMapClause(
17835 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
17836 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
17837 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
17838 ExtraModifierLoc, ColonLoc, VarList, Locs);
17839 break;
17840 case OMPC_to:
17841 Res =
17842 ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc,
17843 Data.ReductionOrMapperIdScopeSpec,
17844 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
17845 break;
17846 case OMPC_from:
17847 Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc,
17848 Data.ReductionOrMapperIdScopeSpec,
17849 Data.ReductionOrMapperId, ColonLoc, VarList,
17850 Locs);
17851 break;
17852 case OMPC_use_device_ptr:
17853 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
17854 break;
17855 case OMPC_use_device_addr:
17856 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
17857 break;
17858 case OMPC_is_device_ptr:
17859 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
17860 break;
17861 case OMPC_has_device_addr:
17862 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
17863 break;
17864 case OMPC_allocate:
17865 Res = ActOnOpenMPAllocateClause(Data.DepModOrTailExpr, VarList, StartLoc,
17866 LParenLoc, ColonLoc, EndLoc);
17867 break;
17868 case OMPC_nontemporal:
17869 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
17870 break;
17871 case OMPC_inclusive:
17872 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17873 break;
17874 case OMPC_exclusive:
17875 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17876 break;
17877 case OMPC_affinity:
17878 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
17879 Data.DepModOrTailExpr, VarList);
17880 break;
17881 case OMPC_if:
17882 case OMPC_depobj:
17883 case OMPC_final:
17884 case OMPC_num_threads:
17885 case OMPC_safelen:
17886 case OMPC_simdlen:
17887 case OMPC_sizes:
17888 case OMPC_allocator:
17889 case OMPC_collapse:
17890 case OMPC_default:
17891 case OMPC_proc_bind:
17892 case OMPC_schedule:
17893 case OMPC_ordered:
17894 case OMPC_nowait:
17895 case OMPC_untied:
17896 case OMPC_mergeable:
17897 case OMPC_threadprivate:
17898 case OMPC_read:
17899 case OMPC_write:
17900 case OMPC_update:
17901 case OMPC_capture:
17902 case OMPC_compare:
17903 case OMPC_seq_cst:
17904 case OMPC_acq_rel:
17905 case OMPC_acquire:
17906 case OMPC_release:
17907 case OMPC_relaxed:
17908 case OMPC_device:
17909 case OMPC_threads:
17910 case OMPC_simd:
17911 case OMPC_num_teams:
17912 case OMPC_thread_limit:
17913 case OMPC_priority:
17914 case OMPC_grainsize:
17915 case OMPC_nogroup:
17916 case OMPC_num_tasks:
17917 case OMPC_hint:
17918 case OMPC_dist_schedule:
17919 case OMPC_defaultmap:
17920 case OMPC_unknown:
17921 case OMPC_uniform:
17922 case OMPC_unified_address:
17923 case OMPC_unified_shared_memory:
17924 case OMPC_reverse_offload:
17925 case OMPC_dynamic_allocators:
17926 case OMPC_atomic_default_mem_order:
17927 case OMPC_device_type:
17928 case OMPC_match:
17929 case OMPC_order:
17930 case OMPC_at:
17931 case OMPC_severity:
17932 case OMPC_message:
17933 case OMPC_destroy:
17934 case OMPC_novariants:
17935 case OMPC_nocontext:
17936 case OMPC_detach:
17937 case OMPC_uses_allocators:
17938 case OMPC_when:
17939 case OMPC_bind:
17940 default:
17941 llvm_unreachable("Clause is not allowed.");
17942 }
17943 return Res;
17944 }
17945
getOpenMPCapturedExpr(VarDecl * Capture,ExprValueKind VK,ExprObjectKind OK,SourceLocation Loc)17946 ExprResult Sema::getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
17947 ExprObjectKind OK, SourceLocation Loc) {
17948 ExprResult Res = BuildDeclRefExpr(
17949 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
17950 if (!Res.isUsable())
17951 return ExprError();
17952 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
17953 Res = CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
17954 if (!Res.isUsable())
17955 return ExprError();
17956 }
17957 if (VK != VK_LValue && Res.get()->isGLValue()) {
17958 Res = DefaultLvalueConversion(Res.get());
17959 if (!Res.isUsable())
17960 return ExprError();
17961 }
17962 return Res;
17963 }
17964
ActOnOpenMPPrivateClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)17965 OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
17966 SourceLocation StartLoc,
17967 SourceLocation LParenLoc,
17968 SourceLocation EndLoc) {
17969 SmallVector<Expr *, 8> Vars;
17970 SmallVector<Expr *, 8> PrivateCopies;
17971 bool IsImplicitClause =
17972 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17973 for (Expr *RefExpr : VarList) {
17974 assert(RefExpr && "NULL expr in OpenMP private clause.");
17975 SourceLocation ELoc;
17976 SourceRange ERange;
17977 Expr *SimpleRefExpr = RefExpr;
17978 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
17979 if (Res.second) {
17980 // It will be analyzed later.
17981 Vars.push_back(RefExpr);
17982 PrivateCopies.push_back(nullptr);
17983 }
17984 ValueDecl *D = Res.first;
17985 if (!D)
17986 continue;
17987
17988 QualType Type = D->getType();
17989 auto *VD = dyn_cast<VarDecl>(D);
17990
17991 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17992 // A variable that appears in a private clause must not have an incomplete
17993 // type or a reference type.
17994 if (RequireCompleteType(ELoc, Type, diag::err_omp_private_incomplete_type))
17995 continue;
17996 Type = Type.getNonReferenceType();
17997
17998 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
17999 // A variable that is privatized must not have a const-qualified type
18000 // unless it is of class type with a mutable member. This restriction does
18001 // not apply to the firstprivate clause.
18002 //
18003 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
18004 // A variable that appears in a private clause must not have a
18005 // const-qualified type unless it is of class type with a mutable member.
18006 if (rejectConstNotMutableType(*this, D, Type, OMPC_private, ELoc))
18007 continue;
18008
18009 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18010 // in a Construct]
18011 // Variables with the predetermined data-sharing attributes may not be
18012 // listed in data-sharing attributes clauses, except for the cases
18013 // listed below. For these exceptions only, listing a predetermined
18014 // variable in a data-sharing attribute clause is allowed and overrides
18015 // the variable's predetermined data-sharing attributes.
18016 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18017 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
18018 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
18019 << getOpenMPClauseName(OMPC_private);
18020 reportOriginalDsa(*this, DSAStack, D, DVar);
18021 continue;
18022 }
18023
18024 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18025 // Variably modified types are not supported for tasks.
18026 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
18027 isOpenMPTaskingDirective(CurrDir)) {
18028 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18029 << getOpenMPClauseName(OMPC_private) << Type
18030 << getOpenMPDirectiveName(CurrDir);
18031 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18032 VarDecl::DeclarationOnly;
18033 Diag(D->getLocation(),
18034 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18035 << D;
18036 continue;
18037 }
18038
18039 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18040 // A list item cannot appear in both a map clause and a data-sharing
18041 // attribute clause on the same construct
18042 //
18043 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18044 // A list item cannot appear in both a map clause and a data-sharing
18045 // attribute clause on the same construct unless the construct is a
18046 // combined construct.
18047 if ((LangOpts.OpenMP <= 45 && isOpenMPTargetExecutionDirective(CurrDir)) ||
18048 CurrDir == OMPD_target) {
18049 OpenMPClauseKind ConflictKind;
18050 if (DSAStack->checkMappableExprComponentListsForDecl(
18051 VD, /*CurrentRegionOnly=*/true,
18052 [&](OMPClauseMappableExprCommon::MappableExprComponentListRef,
18053 OpenMPClauseKind WhereFoundClauseKind) -> bool {
18054 ConflictKind = WhereFoundClauseKind;
18055 return true;
18056 })) {
18057 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18058 << getOpenMPClauseName(OMPC_private)
18059 << getOpenMPClauseName(ConflictKind)
18060 << getOpenMPDirectiveName(CurrDir);
18061 reportOriginalDsa(*this, DSAStack, D, DVar);
18062 continue;
18063 }
18064 }
18065
18066 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
18067 // A variable of class type (or array thereof) that appears in a private
18068 // clause requires an accessible, unambiguous default constructor for the
18069 // class type.
18070 // Generate helper private variable and initialize it with the default
18071 // value. The address of the original variable is replaced by the address of
18072 // the new private variable in CodeGen. This new variable is not added to
18073 // IdResolver, so the code in the OpenMP region uses original variable for
18074 // proper diagnostics.
18075 Type = Type.getUnqualifiedType();
18076 VarDecl *VDPrivate =
18077 buildVarDecl(*this, ELoc, Type, D->getName(),
18078 D->hasAttrs() ? &D->getAttrs() : nullptr,
18079 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18080 ActOnUninitializedDecl(VDPrivate);
18081 if (VDPrivate->isInvalidDecl())
18082 continue;
18083 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18084 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
18085
18086 DeclRefExpr *Ref = nullptr;
18087 if (!VD && !CurContext->isDependentContext()) {
18088 auto *FD = dyn_cast<FieldDecl>(D);
18089 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18090 if (VD)
18091 Ref = buildDeclRefExpr(*this, VD, VD->getType().getNonReferenceType(),
18092 RefExpr->getExprLoc());
18093 else
18094 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
18095 }
18096 if (!IsImplicitClause)
18097 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
18098 Vars.push_back((VD || CurContext->isDependentContext())
18099 ? RefExpr->IgnoreParens()
18100 : Ref);
18101 PrivateCopies.push_back(VDPrivateRefExpr);
18102 }
18103
18104 if (Vars.empty())
18105 return nullptr;
18106
18107 return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars,
18108 PrivateCopies);
18109 }
18110
ActOnOpenMPFirstprivateClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)18111 OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
18112 SourceLocation StartLoc,
18113 SourceLocation LParenLoc,
18114 SourceLocation EndLoc) {
18115 SmallVector<Expr *, 8> Vars;
18116 SmallVector<Expr *, 8> PrivateCopies;
18117 SmallVector<Expr *, 8> Inits;
18118 SmallVector<Decl *, 4> ExprCaptures;
18119 bool IsImplicitClause =
18120 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18121 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
18122
18123 for (Expr *RefExpr : VarList) {
18124 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
18125 SourceLocation ELoc;
18126 SourceRange ERange;
18127 Expr *SimpleRefExpr = RefExpr;
18128 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18129 if (Res.second) {
18130 // It will be analyzed later.
18131 Vars.push_back(RefExpr);
18132 PrivateCopies.push_back(nullptr);
18133 Inits.push_back(nullptr);
18134 }
18135 ValueDecl *D = Res.first;
18136 if (!D)
18137 continue;
18138
18139 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
18140 QualType Type = D->getType();
18141 auto *VD = dyn_cast<VarDecl>(D);
18142
18143 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18144 // A variable that appears in a private clause must not have an incomplete
18145 // type or a reference type.
18146 if (RequireCompleteType(ELoc, Type,
18147 diag::err_omp_firstprivate_incomplete_type))
18148 continue;
18149 Type = Type.getNonReferenceType();
18150
18151 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
18152 // A variable of class type (or array thereof) that appears in a private
18153 // clause requires an accessible, unambiguous copy constructor for the
18154 // class type.
18155 QualType ElemType = Context.getBaseElementType(Type).getNonReferenceType();
18156
18157 // If an implicit firstprivate variable found it was checked already.
18158 DSAStackTy::DSAVarData TopDVar;
18159 if (!IsImplicitClause) {
18160 DSAStackTy::DSAVarData DVar =
18161 DSAStack->getTopDSA(D, /*FromParent=*/false);
18162 TopDVar = DVar;
18163 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18164 bool IsConstant = ElemType.isConstant(Context);
18165 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
18166 // A list item that specifies a given variable may not appear in more
18167 // than one clause on the same directive, except that a variable may be
18168 // specified in both firstprivate and lastprivate clauses.
18169 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18170 // A list item may appear in a firstprivate or lastprivate clause but not
18171 // both.
18172 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
18173 (isOpenMPDistributeDirective(CurrDir) ||
18174 DVar.CKind != OMPC_lastprivate) &&
18175 DVar.RefExpr) {
18176 Diag(ELoc, diag::err_omp_wrong_dsa)
18177 << getOpenMPClauseName(DVar.CKind)
18178 << getOpenMPClauseName(OMPC_firstprivate);
18179 reportOriginalDsa(*this, DSAStack, D, DVar);
18180 continue;
18181 }
18182
18183 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18184 // in a Construct]
18185 // Variables with the predetermined data-sharing attributes may not be
18186 // listed in data-sharing attributes clauses, except for the cases
18187 // listed below. For these exceptions only, listing a predetermined
18188 // variable in a data-sharing attribute clause is allowed and overrides
18189 // the variable's predetermined data-sharing attributes.
18190 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18191 // in a Construct, C/C++, p.2]
18192 // Variables with const-qualified type having no mutable member may be
18193 // listed in a firstprivate clause, even if they are static data members.
18194 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
18195 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
18196 Diag(ELoc, diag::err_omp_wrong_dsa)
18197 << getOpenMPClauseName(DVar.CKind)
18198 << getOpenMPClauseName(OMPC_firstprivate);
18199 reportOriginalDsa(*this, DSAStack, D, DVar);
18200 continue;
18201 }
18202
18203 // OpenMP [2.9.3.4, Restrictions, p.2]
18204 // A list item that is private within a parallel region must not appear
18205 // in a firstprivate clause on a worksharing construct if any of the
18206 // worksharing regions arising from the worksharing construct ever bind
18207 // to any of the parallel regions arising from the parallel construct.
18208 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18209 // A list item that is private within a teams region must not appear in a
18210 // firstprivate clause on a distribute construct if any of the distribute
18211 // regions arising from the distribute construct ever bind to any of the
18212 // teams regions arising from the teams construct.
18213 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18214 // A list item that appears in a reduction clause of a teams construct
18215 // must not appear in a firstprivate clause on a distribute construct if
18216 // any of the distribute regions arising from the distribute construct
18217 // ever bind to any of the teams regions arising from the teams construct.
18218 if ((isOpenMPWorksharingDirective(CurrDir) ||
18219 isOpenMPDistributeDirective(CurrDir)) &&
18220 !isOpenMPParallelDirective(CurrDir) &&
18221 !isOpenMPTeamsDirective(CurrDir)) {
18222 DVar = DSAStack->getImplicitDSA(D, true);
18223 if (DVar.CKind != OMPC_shared &&
18224 (isOpenMPParallelDirective(DVar.DKind) ||
18225 isOpenMPTeamsDirective(DVar.DKind) ||
18226 DVar.DKind == OMPD_unknown)) {
18227 Diag(ELoc, diag::err_omp_required_access)
18228 << getOpenMPClauseName(OMPC_firstprivate)
18229 << getOpenMPClauseName(OMPC_shared);
18230 reportOriginalDsa(*this, DSAStack, D, DVar);
18231 continue;
18232 }
18233 }
18234 // OpenMP [2.9.3.4, Restrictions, p.3]
18235 // A list item that appears in a reduction clause of a parallel construct
18236 // must not appear in a firstprivate clause on a worksharing or task
18237 // construct if any of the worksharing or task regions arising from the
18238 // worksharing or task construct ever bind to any of the parallel regions
18239 // arising from the parallel construct.
18240 // OpenMP [2.9.3.4, Restrictions, p.4]
18241 // A list item that appears in a reduction clause in worksharing
18242 // construct must not appear in a firstprivate clause in a task construct
18243 // encountered during execution of any of the worksharing regions arising
18244 // from the worksharing construct.
18245 if (isOpenMPTaskingDirective(CurrDir)) {
18246 DVar = DSAStack->hasInnermostDSA(
18247 D,
18248 [](OpenMPClauseKind C, bool AppliedToPointee) {
18249 return C == OMPC_reduction && !AppliedToPointee;
18250 },
18251 [](OpenMPDirectiveKind K) {
18252 return isOpenMPParallelDirective(K) ||
18253 isOpenMPWorksharingDirective(K) ||
18254 isOpenMPTeamsDirective(K);
18255 },
18256 /*FromParent=*/true);
18257 if (DVar.CKind == OMPC_reduction &&
18258 (isOpenMPParallelDirective(DVar.DKind) ||
18259 isOpenMPWorksharingDirective(DVar.DKind) ||
18260 isOpenMPTeamsDirective(DVar.DKind))) {
18261 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
18262 << getOpenMPDirectiveName(DVar.DKind);
18263 reportOriginalDsa(*this, DSAStack, D, DVar);
18264 continue;
18265 }
18266 }
18267
18268 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18269 // A list item cannot appear in both a map clause and a data-sharing
18270 // attribute clause on the same construct
18271 //
18272 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18273 // A list item cannot appear in both a map clause and a data-sharing
18274 // attribute clause on the same construct unless the construct is a
18275 // combined construct.
18276 if ((LangOpts.OpenMP <= 45 &&
18277 isOpenMPTargetExecutionDirective(CurrDir)) ||
18278 CurrDir == OMPD_target) {
18279 OpenMPClauseKind ConflictKind;
18280 if (DSAStack->checkMappableExprComponentListsForDecl(
18281 VD, /*CurrentRegionOnly=*/true,
18282 [&ConflictKind](
18283 OMPClauseMappableExprCommon::MappableExprComponentListRef,
18284 OpenMPClauseKind WhereFoundClauseKind) {
18285 ConflictKind = WhereFoundClauseKind;
18286 return true;
18287 })) {
18288 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18289 << getOpenMPClauseName(OMPC_firstprivate)
18290 << getOpenMPClauseName(ConflictKind)
18291 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
18292 reportOriginalDsa(*this, DSAStack, D, DVar);
18293 continue;
18294 }
18295 }
18296 }
18297
18298 // Variably modified types are not supported for tasks.
18299 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
18300 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
18301 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18302 << getOpenMPClauseName(OMPC_firstprivate) << Type
18303 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
18304 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18305 VarDecl::DeclarationOnly;
18306 Diag(D->getLocation(),
18307 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18308 << D;
18309 continue;
18310 }
18311
18312 Type = Type.getUnqualifiedType();
18313 VarDecl *VDPrivate =
18314 buildVarDecl(*this, ELoc, Type, D->getName(),
18315 D->hasAttrs() ? &D->getAttrs() : nullptr,
18316 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18317 // Generate helper private variable and initialize it with the value of the
18318 // original variable. The address of the original variable is replaced by
18319 // the address of the new private variable in the CodeGen. This new variable
18320 // is not added to IdResolver, so the code in the OpenMP region uses
18321 // original variable for proper diagnostics and variable capturing.
18322 Expr *VDInitRefExpr = nullptr;
18323 // For arrays generate initializer for single element and replace it by the
18324 // original array element in CodeGen.
18325 if (Type->isArrayType()) {
18326 VarDecl *VDInit =
18327 buildVarDecl(*this, RefExpr->getExprLoc(), ElemType, D->getName());
18328 VDInitRefExpr = buildDeclRefExpr(*this, VDInit, ElemType, ELoc);
18329 Expr *Init = DefaultLvalueConversion(VDInitRefExpr).get();
18330 ElemType = ElemType.getUnqualifiedType();
18331 VarDecl *VDInitTemp = buildVarDecl(*this, RefExpr->getExprLoc(), ElemType,
18332 ".firstprivate.temp");
18333 InitializedEntity Entity =
18334 InitializedEntity::InitializeVariable(VDInitTemp);
18335 InitializationKind Kind = InitializationKind::CreateCopy(ELoc, ELoc);
18336
18337 InitializationSequence InitSeq(*this, Entity, Kind, Init);
18338 ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Init);
18339 if (Result.isInvalid())
18340 VDPrivate->setInvalidDecl();
18341 else
18342 VDPrivate->setInit(Result.getAs<Expr>());
18343 // Remove temp variable declaration.
18344 Context.Deallocate(VDInitTemp);
18345 } else {
18346 VarDecl *VDInit = buildVarDecl(*this, RefExpr->getExprLoc(), Type,
18347 ".firstprivate.temp");
18348 VDInitRefExpr = buildDeclRefExpr(*this, VDInit, RefExpr->getType(),
18349 RefExpr->getExprLoc());
18350 AddInitializerToDecl(VDPrivate,
18351 DefaultLvalueConversion(VDInitRefExpr).get(),
18352 /*DirectInit=*/false);
18353 }
18354 if (VDPrivate->isInvalidDecl()) {
18355 if (IsImplicitClause) {
18356 Diag(RefExpr->getExprLoc(),
18357 diag::note_omp_task_predetermined_firstprivate_here);
18358 }
18359 continue;
18360 }
18361 CurContext->addDecl(VDPrivate);
18362 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18363 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(),
18364 RefExpr->getExprLoc());
18365 DeclRefExpr *Ref = nullptr;
18366 if (!VD && !CurContext->isDependentContext()) {
18367 if (TopDVar.CKind == OMPC_lastprivate) {
18368 Ref = TopDVar.PrivateCopy;
18369 } else {
18370 auto *FD = dyn_cast<FieldDecl>(D);
18371 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18372 if (VD)
18373 Ref = buildDeclRefExpr(*this, VD, VD->getType().getNonReferenceType(),
18374 RefExpr->getExprLoc());
18375 else
18376 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
18377 if (VD || !isOpenMPCapturedDecl(D))
18378 ExprCaptures.push_back(Ref->getDecl());
18379 }
18380 }
18381 if (!IsImplicitClause)
18382 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
18383 Vars.push_back((VD || CurContext->isDependentContext())
18384 ? RefExpr->IgnoreParens()
18385 : Ref);
18386 PrivateCopies.push_back(VDPrivateRefExpr);
18387 Inits.push_back(VDInitRefExpr);
18388 }
18389
18390 if (Vars.empty())
18391 return nullptr;
18392
18393 return OMPFirstprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
18394 Vars, PrivateCopies, Inits,
18395 buildPreInits(Context, ExprCaptures));
18396 }
18397
ActOnOpenMPLastprivateClause(ArrayRef<Expr * > VarList,OpenMPLastprivateModifier LPKind,SourceLocation LPKindLoc,SourceLocation ColonLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)18398 OMPClause *Sema::ActOnOpenMPLastprivateClause(
18399 ArrayRef<Expr *> VarList, OpenMPLastprivateModifier LPKind,
18400 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
18401 SourceLocation LParenLoc, SourceLocation EndLoc) {
18402 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
18403 assert(ColonLoc.isValid() && "Colon location must be valid.");
18404 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
18405 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
18406 /*Last=*/OMPC_LASTPRIVATE_unknown)
18407 << getOpenMPClauseName(OMPC_lastprivate);
18408 return nullptr;
18409 }
18410
18411 SmallVector<Expr *, 8> Vars;
18412 SmallVector<Expr *, 8> SrcExprs;
18413 SmallVector<Expr *, 8> DstExprs;
18414 SmallVector<Expr *, 8> AssignmentOps;
18415 SmallVector<Decl *, 4> ExprCaptures;
18416 SmallVector<Expr *, 4> ExprPostUpdates;
18417 for (Expr *RefExpr : VarList) {
18418 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18419 SourceLocation ELoc;
18420 SourceRange ERange;
18421 Expr *SimpleRefExpr = RefExpr;
18422 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18423 if (Res.second) {
18424 // It will be analyzed later.
18425 Vars.push_back(RefExpr);
18426 SrcExprs.push_back(nullptr);
18427 DstExprs.push_back(nullptr);
18428 AssignmentOps.push_back(nullptr);
18429 }
18430 ValueDecl *D = Res.first;
18431 if (!D)
18432 continue;
18433
18434 QualType Type = D->getType();
18435 auto *VD = dyn_cast<VarDecl>(D);
18436
18437 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
18438 // A variable that appears in a lastprivate clause must not have an
18439 // incomplete type or a reference type.
18440 if (RequireCompleteType(ELoc, Type,
18441 diag::err_omp_lastprivate_incomplete_type))
18442 continue;
18443 Type = Type.getNonReferenceType();
18444
18445 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18446 // A variable that is privatized must not have a const-qualified type
18447 // unless it is of class type with a mutable member. This restriction does
18448 // not apply to the firstprivate clause.
18449 //
18450 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
18451 // A variable that appears in a lastprivate clause must not have a
18452 // const-qualified type unless it is of class type with a mutable member.
18453 if (rejectConstNotMutableType(*this, D, Type, OMPC_lastprivate, ELoc))
18454 continue;
18455
18456 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
18457 // A list item that appears in a lastprivate clause with the conditional
18458 // modifier must be a scalar variable.
18459 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
18460 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
18461 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18462 VarDecl::DeclarationOnly;
18463 Diag(D->getLocation(),
18464 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18465 << D;
18466 continue;
18467 }
18468
18469 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18470 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18471 // in a Construct]
18472 // Variables with the predetermined data-sharing attributes may not be
18473 // listed in data-sharing attributes clauses, except for the cases
18474 // listed below.
18475 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18476 // A list item may appear in a firstprivate or lastprivate clause but not
18477 // both.
18478 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18479 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
18480 (isOpenMPDistributeDirective(CurrDir) ||
18481 DVar.CKind != OMPC_firstprivate) &&
18482 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
18483 Diag(ELoc, diag::err_omp_wrong_dsa)
18484 << getOpenMPClauseName(DVar.CKind)
18485 << getOpenMPClauseName(OMPC_lastprivate);
18486 reportOriginalDsa(*this, DSAStack, D, DVar);
18487 continue;
18488 }
18489
18490 // OpenMP [2.14.3.5, Restrictions, p.2]
18491 // A list item that is private within a parallel region, or that appears in
18492 // the reduction clause of a parallel construct, must not appear in a
18493 // lastprivate clause on a worksharing construct if any of the corresponding
18494 // worksharing regions ever binds to any of the corresponding parallel
18495 // regions.
18496 DSAStackTy::DSAVarData TopDVar = DVar;
18497 if (isOpenMPWorksharingDirective(CurrDir) &&
18498 !isOpenMPParallelDirective(CurrDir) &&
18499 !isOpenMPTeamsDirective(CurrDir)) {
18500 DVar = DSAStack->getImplicitDSA(D, true);
18501 if (DVar.CKind != OMPC_shared) {
18502 Diag(ELoc, diag::err_omp_required_access)
18503 << getOpenMPClauseName(OMPC_lastprivate)
18504 << getOpenMPClauseName(OMPC_shared);
18505 reportOriginalDsa(*this, DSAStack, D, DVar);
18506 continue;
18507 }
18508 }
18509
18510 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
18511 // A variable of class type (or array thereof) that appears in a
18512 // lastprivate clause requires an accessible, unambiguous default
18513 // constructor for the class type, unless the list item is also specified
18514 // in a firstprivate clause.
18515 // A variable of class type (or array thereof) that appears in a
18516 // lastprivate clause requires an accessible, unambiguous copy assignment
18517 // operator for the class type.
18518 Type = Context.getBaseElementType(Type).getNonReferenceType();
18519 VarDecl *SrcVD = buildVarDecl(*this, ERange.getBegin(),
18520 Type.getUnqualifiedType(), ".lastprivate.src",
18521 D->hasAttrs() ? &D->getAttrs() : nullptr);
18522 DeclRefExpr *PseudoSrcExpr =
18523 buildDeclRefExpr(*this, SrcVD, Type.getUnqualifiedType(), ELoc);
18524 VarDecl *DstVD =
18525 buildVarDecl(*this, ERange.getBegin(), Type, ".lastprivate.dst",
18526 D->hasAttrs() ? &D->getAttrs() : nullptr);
18527 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
18528 // For arrays generate assignment operation for single element and replace
18529 // it by the original array element in CodeGen.
18530 ExprResult AssignmentOp = BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
18531 PseudoDstExpr, PseudoSrcExpr);
18532 if (AssignmentOp.isInvalid())
18533 continue;
18534 AssignmentOp =
18535 ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false);
18536 if (AssignmentOp.isInvalid())
18537 continue;
18538
18539 DeclRefExpr *Ref = nullptr;
18540 if (!VD && !CurContext->isDependentContext()) {
18541 if (TopDVar.CKind == OMPC_firstprivate) {
18542 Ref = TopDVar.PrivateCopy;
18543 } else {
18544 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
18545 if (!isOpenMPCapturedDecl(D))
18546 ExprCaptures.push_back(Ref->getDecl());
18547 }
18548 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
18549 (!isOpenMPCapturedDecl(D) &&
18550 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
18551 ExprResult RefRes = DefaultLvalueConversion(Ref);
18552 if (!RefRes.isUsable())
18553 continue;
18554 ExprResult PostUpdateRes =
18555 BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
18556 RefRes.get());
18557 if (!PostUpdateRes.isUsable())
18558 continue;
18559 ExprPostUpdates.push_back(
18560 IgnoredValueConversions(PostUpdateRes.get()).get());
18561 }
18562 }
18563 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
18564 Vars.push_back((VD || CurContext->isDependentContext())
18565 ? RefExpr->IgnoreParens()
18566 : Ref);
18567 SrcExprs.push_back(PseudoSrcExpr);
18568 DstExprs.push_back(PseudoDstExpr);
18569 AssignmentOps.push_back(AssignmentOp.get());
18570 }
18571
18572 if (Vars.empty())
18573 return nullptr;
18574
18575 return OMPLastprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
18576 Vars, SrcExprs, DstExprs, AssignmentOps,
18577 LPKind, LPKindLoc, ColonLoc,
18578 buildPreInits(Context, ExprCaptures),
18579 buildPostUpdate(*this, ExprPostUpdates));
18580 }
18581
ActOnOpenMPSharedClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)18582 OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
18583 SourceLocation StartLoc,
18584 SourceLocation LParenLoc,
18585 SourceLocation EndLoc) {
18586 SmallVector<Expr *, 8> Vars;
18587 for (Expr *RefExpr : VarList) {
18588 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18589 SourceLocation ELoc;
18590 SourceRange ERange;
18591 Expr *SimpleRefExpr = RefExpr;
18592 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18593 if (Res.second) {
18594 // It will be analyzed later.
18595 Vars.push_back(RefExpr);
18596 }
18597 ValueDecl *D = Res.first;
18598 if (!D)
18599 continue;
18600
18601 auto *VD = dyn_cast<VarDecl>(D);
18602 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18603 // in a Construct]
18604 // Variables with the predetermined data-sharing attributes may not be
18605 // listed in data-sharing attributes clauses, except for the cases
18606 // listed below. For these exceptions only, listing a predetermined
18607 // variable in a data-sharing attribute clause is allowed and overrides
18608 // the variable's predetermined data-sharing attributes.
18609 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18610 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
18611 DVar.RefExpr) {
18612 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
18613 << getOpenMPClauseName(OMPC_shared);
18614 reportOriginalDsa(*this, DSAStack, D, DVar);
18615 continue;
18616 }
18617
18618 DeclRefExpr *Ref = nullptr;
18619 if (!VD && isOpenMPCapturedDecl(D) && !CurContext->isDependentContext())
18620 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
18621 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
18622 Vars.push_back((VD || !Ref || CurContext->isDependentContext())
18623 ? RefExpr->IgnoreParens()
18624 : Ref);
18625 }
18626
18627 if (Vars.empty())
18628 return nullptr;
18629
18630 return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
18631 }
18632
18633 namespace {
18634 class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
18635 DSAStackTy *Stack;
18636
18637 public:
VisitDeclRefExpr(DeclRefExpr * E)18638 bool VisitDeclRefExpr(DeclRefExpr *E) {
18639 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
18640 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
18641 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
18642 return false;
18643 if (DVar.CKind != OMPC_unknown)
18644 return true;
18645 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
18646 VD,
18647 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
18648 return isOpenMPPrivate(C) && !AppliedToPointee;
18649 },
18650 [](OpenMPDirectiveKind) { return true; },
18651 /*FromParent=*/true);
18652 return DVarPrivate.CKind != OMPC_unknown;
18653 }
18654 return false;
18655 }
VisitStmt(Stmt * S)18656 bool VisitStmt(Stmt *S) {
18657 for (Stmt *Child : S->children()) {
18658 if (Child && Visit(Child))
18659 return true;
18660 }
18661 return false;
18662 }
DSARefChecker(DSAStackTy * S)18663 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
18664 };
18665 } // namespace
18666
18667 namespace {
18668 // Transform MemberExpression for specified FieldDecl of current class to
18669 // DeclRefExpr to specified OMPCapturedExprDecl.
18670 class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
18671 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
18672 ValueDecl *Field = nullptr;
18673 DeclRefExpr *CapturedExpr = nullptr;
18674
18675 public:
TransformExprToCaptures(Sema & SemaRef,ValueDecl * FieldDecl)18676 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
18677 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
18678
TransformMemberExpr(MemberExpr * E)18679 ExprResult TransformMemberExpr(MemberExpr *E) {
18680 if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
18681 E->getMemberDecl() == Field) {
18682 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
18683 return CapturedExpr;
18684 }
18685 return BaseTransform::TransformMemberExpr(E);
18686 }
getCapturedExpr()18687 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
18688 };
18689 } // namespace
18690
18691 template <typename T, typename U>
filterLookupForUDReductionAndMapper(SmallVectorImpl<U> & Lookups,const llvm::function_ref<T (ValueDecl *)> Gen)18692 static T filterLookupForUDReductionAndMapper(
18693 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
18694 for (U &Set : Lookups) {
18695 for (auto *D : Set) {
18696 if (T Res = Gen(cast<ValueDecl>(D)))
18697 return Res;
18698 }
18699 }
18700 return T();
18701 }
18702
findAcceptableDecl(Sema & SemaRef,NamedDecl * D)18703 static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
18704 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
18705
18706 for (auto *RD : D->redecls()) {
18707 // Don't bother with extra checks if we already know this one isn't visible.
18708 if (RD == D)
18709 continue;
18710
18711 auto ND = cast<NamedDecl>(RD);
18712 if (LookupResult::isVisible(SemaRef, ND))
18713 return ND;
18714 }
18715
18716 return nullptr;
18717 }
18718
18719 static void
argumentDependentLookup(Sema & SemaRef,const DeclarationNameInfo & Id,SourceLocation Loc,QualType Ty,SmallVectorImpl<UnresolvedSet<8>> & Lookups)18720 argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id,
18721 SourceLocation Loc, QualType Ty,
18722 SmallVectorImpl<UnresolvedSet<8>> &Lookups) {
18723 // Find all of the associated namespaces and classes based on the
18724 // arguments we have.
18725 Sema::AssociatedNamespaceSet AssociatedNamespaces;
18726 Sema::AssociatedClassSet AssociatedClasses;
18727 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
18728 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
18729 AssociatedClasses);
18730
18731 // C++ [basic.lookup.argdep]p3:
18732 // Let X be the lookup set produced by unqualified lookup (3.4.1)
18733 // and let Y be the lookup set produced by argument dependent
18734 // lookup (defined as follows). If X contains [...] then Y is
18735 // empty. Otherwise Y is the set of declarations found in the
18736 // namespaces associated with the argument types as described
18737 // below. The set of declarations found by the lookup of the name
18738 // is the union of X and Y.
18739 //
18740 // Here, we compute Y and add its members to the overloaded
18741 // candidate set.
18742 for (auto *NS : AssociatedNamespaces) {
18743 // When considering an associated namespace, the lookup is the
18744 // same as the lookup performed when the associated namespace is
18745 // used as a qualifier (3.4.3.2) except that:
18746 //
18747 // -- Any using-directives in the associated namespace are
18748 // ignored.
18749 //
18750 // -- Any namespace-scope friend functions declared in
18751 // associated classes are visible within their respective
18752 // namespaces even if they are not visible during an ordinary
18753 // lookup (11.4).
18754 DeclContext::lookup_result R = NS->lookup(Id.getName());
18755 for (auto *D : R) {
18756 auto *Underlying = D;
18757 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
18758 Underlying = USD->getTargetDecl();
18759
18760 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
18761 !isa<OMPDeclareMapperDecl>(Underlying))
18762 continue;
18763
18764 if (!SemaRef.isVisible(D)) {
18765 D = findAcceptableDecl(SemaRef, D);
18766 if (!D)
18767 continue;
18768 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
18769 Underlying = USD->getTargetDecl();
18770 }
18771 Lookups.emplace_back();
18772 Lookups.back().addDecl(Underlying);
18773 }
18774 }
18775 }
18776
18777 static ExprResult
buildDeclareReductionRef(Sema & SemaRef,SourceLocation Loc,SourceRange Range,Scope * S,CXXScopeSpec & ReductionIdScopeSpec,const DeclarationNameInfo & ReductionId,QualType Ty,CXXCastPath & BasePath,Expr * UnresolvedReduction)18778 buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
18779 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
18780 const DeclarationNameInfo &ReductionId, QualType Ty,
18781 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
18782 if (ReductionIdScopeSpec.isInvalid())
18783 return ExprError();
18784 SmallVector<UnresolvedSet<8>, 4> Lookups;
18785 if (S) {
18786 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18787 Lookup.suppressDiagnostics();
18788 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec)) {
18789 NamedDecl *D = Lookup.getRepresentativeDecl();
18790 do {
18791 S = S->getParent();
18792 } while (S && !S->isDeclScope(D));
18793 if (S)
18794 S = S->getParent();
18795 Lookups.emplace_back();
18796 Lookups.back().append(Lookup.begin(), Lookup.end());
18797 Lookup.clear();
18798 }
18799 } else if (auto *ULE =
18800 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
18801 Lookups.push_back(UnresolvedSet<8>());
18802 Decl *PrevD = nullptr;
18803 for (NamedDecl *D : ULE->decls()) {
18804 if (D == PrevD)
18805 Lookups.push_back(UnresolvedSet<8>());
18806 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
18807 Lookups.back().addDecl(DRD);
18808 PrevD = D;
18809 }
18810 }
18811 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
18812 Ty->isInstantiationDependentType() ||
18813 Ty->containsUnexpandedParameterPack() ||
18814 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
18815 return !D->isInvalidDecl() &&
18816 (D->getType()->isDependentType() ||
18817 D->getType()->isInstantiationDependentType() ||
18818 D->getType()->containsUnexpandedParameterPack());
18819 })) {
18820 UnresolvedSet<8> ResSet;
18821 for (const UnresolvedSet<8> &Set : Lookups) {
18822 if (Set.empty())
18823 continue;
18824 ResSet.append(Set.begin(), Set.end());
18825 // The last item marks the end of all declarations at the specified scope.
18826 ResSet.addDecl(Set[Set.size() - 1]);
18827 }
18828 return UnresolvedLookupExpr::Create(
18829 SemaRef.Context, /*NamingClass=*/nullptr,
18830 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
18831 /*ADL=*/true, /*Overloaded=*/true, ResSet.begin(), ResSet.end());
18832 }
18833 // Lookup inside the classes.
18834 // C++ [over.match.oper]p3:
18835 // For a unary operator @ with an operand of a type whose
18836 // cv-unqualified version is T1, and for a binary operator @ with
18837 // a left operand of a type whose cv-unqualified version is T1 and
18838 // a right operand of a type whose cv-unqualified version is T2,
18839 // three sets of candidate functions, designated member
18840 // candidates, non-member candidates and built-in candidates, are
18841 // constructed as follows:
18842 // -- If T1 is a complete class type or a class currently being
18843 // defined, the set of member candidates is the result of the
18844 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
18845 // the set of member candidates is empty.
18846 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18847 Lookup.suppressDiagnostics();
18848 if (const auto *TyRec = Ty->getAs<RecordType>()) {
18849 // Complete the type if it can be completed.
18850 // If the type is neither complete nor being defined, bail out now.
18851 if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() ||
18852 TyRec->getDecl()->getDefinition()) {
18853 Lookup.clear();
18854 SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
18855 if (Lookup.empty()) {
18856 Lookups.emplace_back();
18857 Lookups.back().append(Lookup.begin(), Lookup.end());
18858 }
18859 }
18860 }
18861 // Perform ADL.
18862 if (SemaRef.getLangOpts().CPlusPlus)
18863 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
18864 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18865 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
18866 if (!D->isInvalidDecl() &&
18867 SemaRef.Context.hasSameType(D->getType(), Ty))
18868 return D;
18869 return nullptr;
18870 }))
18871 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
18872 VK_LValue, Loc);
18873 if (SemaRef.getLangOpts().CPlusPlus) {
18874 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18875 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
18876 if (!D->isInvalidDecl() &&
18877 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
18878 !Ty.isMoreQualifiedThan(D->getType()))
18879 return D;
18880 return nullptr;
18881 })) {
18882 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
18883 /*DetectVirtual=*/false);
18884 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
18885 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
18886 VD->getType().getUnqualifiedType()))) {
18887 if (SemaRef.CheckBaseClassAccess(
18888 Loc, VD->getType(), Ty, Paths.front(),
18889 /*DiagID=*/0) != Sema::AR_inaccessible) {
18890 SemaRef.BuildBasePathArray(Paths, BasePath);
18891 return SemaRef.BuildDeclRefExpr(
18892 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc);
18893 }
18894 }
18895 }
18896 }
18897 }
18898 if (ReductionIdScopeSpec.isSet()) {
18899 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
18900 << Ty << Range;
18901 return ExprError();
18902 }
18903 return ExprEmpty();
18904 }
18905
18906 namespace {
18907 /// Data for the reduction-based clauses.
18908 struct ReductionData {
18909 /// List of original reduction items.
18910 SmallVector<Expr *, 8> Vars;
18911 /// List of private copies of the reduction items.
18912 SmallVector<Expr *, 8> Privates;
18913 /// LHS expressions for the reduction_op expressions.
18914 SmallVector<Expr *, 8> LHSs;
18915 /// RHS expressions for the reduction_op expressions.
18916 SmallVector<Expr *, 8> RHSs;
18917 /// Reduction operation expression.
18918 SmallVector<Expr *, 8> ReductionOps;
18919 /// inscan copy operation expressions.
18920 SmallVector<Expr *, 8> InscanCopyOps;
18921 /// inscan copy temp array expressions for prefix sums.
18922 SmallVector<Expr *, 8> InscanCopyArrayTemps;
18923 /// inscan copy temp array element expressions for prefix sums.
18924 SmallVector<Expr *, 8> InscanCopyArrayElems;
18925 /// Taskgroup descriptors for the corresponding reduction items in
18926 /// in_reduction clauses.
18927 SmallVector<Expr *, 8> TaskgroupDescriptors;
18928 /// List of captures for clause.
18929 SmallVector<Decl *, 4> ExprCaptures;
18930 /// List of postupdate expressions.
18931 SmallVector<Expr *, 4> ExprPostUpdates;
18932 /// Reduction modifier.
18933 unsigned RedModifier = 0;
18934 ReductionData() = delete;
18935 /// Reserves required memory for the reduction data.
ReductionData__anon7e4ded5b5e11::ReductionData18936 ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
18937 Vars.reserve(Size);
18938 Privates.reserve(Size);
18939 LHSs.reserve(Size);
18940 RHSs.reserve(Size);
18941 ReductionOps.reserve(Size);
18942 if (RedModifier == OMPC_REDUCTION_inscan) {
18943 InscanCopyOps.reserve(Size);
18944 InscanCopyArrayTemps.reserve(Size);
18945 InscanCopyArrayElems.reserve(Size);
18946 }
18947 TaskgroupDescriptors.reserve(Size);
18948 ExprCaptures.reserve(Size);
18949 ExprPostUpdates.reserve(Size);
18950 }
18951 /// Stores reduction item and reduction operation only (required for dependent
18952 /// reduction item).
push__anon7e4ded5b5e11::ReductionData18953 void push(Expr *Item, Expr *ReductionOp) {
18954 Vars.emplace_back(Item);
18955 Privates.emplace_back(nullptr);
18956 LHSs.emplace_back(nullptr);
18957 RHSs.emplace_back(nullptr);
18958 ReductionOps.emplace_back(ReductionOp);
18959 TaskgroupDescriptors.emplace_back(nullptr);
18960 if (RedModifier == OMPC_REDUCTION_inscan) {
18961 InscanCopyOps.push_back(nullptr);
18962 InscanCopyArrayTemps.push_back(nullptr);
18963 InscanCopyArrayElems.push_back(nullptr);
18964 }
18965 }
18966 /// Stores reduction data.
push__anon7e4ded5b5e11::ReductionData18967 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
18968 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
18969 Expr *CopyArrayElem) {
18970 Vars.emplace_back(Item);
18971 Privates.emplace_back(Private);
18972 LHSs.emplace_back(LHS);
18973 RHSs.emplace_back(RHS);
18974 ReductionOps.emplace_back(ReductionOp);
18975 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
18976 if (RedModifier == OMPC_REDUCTION_inscan) {
18977 InscanCopyOps.push_back(CopyOp);
18978 InscanCopyArrayTemps.push_back(CopyArrayTemp);
18979 InscanCopyArrayElems.push_back(CopyArrayElem);
18980 } else {
18981 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
18982 CopyArrayElem == nullptr &&
18983 "Copy operation must be used for inscan reductions only.");
18984 }
18985 }
18986 };
18987 } // namespace
18988
checkOMPArraySectionConstantForReduction(ASTContext & Context,const OMPArraySectionExpr * OASE,bool & SingleElement,SmallVectorImpl<llvm::APSInt> & ArraySizes)18989 static bool checkOMPArraySectionConstantForReduction(
18990 ASTContext &Context, const OMPArraySectionExpr *OASE, bool &SingleElement,
18991 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
18992 const Expr *Length = OASE->getLength();
18993 if (Length == nullptr) {
18994 // For array sections of the form [1:] or [:], we would need to analyze
18995 // the lower bound...
18996 if (OASE->getColonLocFirst().isValid())
18997 return false;
18998
18999 // This is an array subscript which has implicit length 1!
19000 SingleElement = true;
19001 ArraySizes.push_back(llvm::APSInt::get(1));
19002 } else {
19003 Expr::EvalResult Result;
19004 if (!Length->EvaluateAsInt(Result, Context))
19005 return false;
19006
19007 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19008 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
19009 ArraySizes.push_back(ConstantLengthValue);
19010 }
19011
19012 // Get the base of this array section and walk up from there.
19013 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
19014
19015 // We require length = 1 for all array sections except the right-most to
19016 // guarantee that the memory region is contiguous and has no holes in it.
19017 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) {
19018 Length = TempOASE->getLength();
19019 if (Length == nullptr) {
19020 // For array sections of the form [1:] or [:], we would need to analyze
19021 // the lower bound...
19022 if (OASE->getColonLocFirst().isValid())
19023 return false;
19024
19025 // This is an array subscript which has implicit length 1!
19026 ArraySizes.push_back(llvm::APSInt::get(1));
19027 } else {
19028 Expr::EvalResult Result;
19029 if (!Length->EvaluateAsInt(Result, Context))
19030 return false;
19031
19032 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19033 if (ConstantLengthValue.getSExtValue() != 1)
19034 return false;
19035
19036 ArraySizes.push_back(ConstantLengthValue);
19037 }
19038 Base = TempOASE->getBase()->IgnoreParenImpCasts();
19039 }
19040
19041 // If we have a single element, we don't need to add the implicit lengths.
19042 if (!SingleElement) {
19043 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
19044 // Has implicit length 1!
19045 ArraySizes.push_back(llvm::APSInt::get(1));
19046 Base = TempASE->getBase()->IgnoreParenImpCasts();
19047 }
19048 }
19049
19050 // This array section can be privatized as a single value or as a constant
19051 // sized array.
19052 return true;
19053 }
19054
19055 static BinaryOperatorKind
getRelatedCompoundReductionOp(BinaryOperatorKind BOK)19056 getRelatedCompoundReductionOp(BinaryOperatorKind BOK) {
19057 if (BOK == BO_Add)
19058 return BO_AddAssign;
19059 if (BOK == BO_Mul)
19060 return BO_MulAssign;
19061 if (BOK == BO_And)
19062 return BO_AndAssign;
19063 if (BOK == BO_Or)
19064 return BO_OrAssign;
19065 if (BOK == BO_Xor)
19066 return BO_XorAssign;
19067 return BOK;
19068 }
19069
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)19070 static bool actOnOMPReductionKindClause(
19071 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
19072 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19073 SourceLocation ColonLoc, SourceLocation EndLoc,
19074 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19075 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
19076 DeclarationName DN = ReductionId.getName();
19077 OverloadedOperatorKind OOK = DN.getCXXOverloadedOperator();
19078 BinaryOperatorKind BOK = BO_Comma;
19079
19080 ASTContext &Context = S.Context;
19081 // OpenMP [2.14.3.6, reduction clause]
19082 // C
19083 // reduction-identifier is either an identifier or one of the following
19084 // operators: +, -, *, &, |, ^, && and ||
19085 // C++
19086 // reduction-identifier is either an id-expression or one of the following
19087 // operators: +, -, *, &, |, ^, && and ||
19088 switch (OOK) {
19089 case OO_Plus:
19090 case OO_Minus:
19091 BOK = BO_Add;
19092 break;
19093 case OO_Star:
19094 BOK = BO_Mul;
19095 break;
19096 case OO_Amp:
19097 BOK = BO_And;
19098 break;
19099 case OO_Pipe:
19100 BOK = BO_Or;
19101 break;
19102 case OO_Caret:
19103 BOK = BO_Xor;
19104 break;
19105 case OO_AmpAmp:
19106 BOK = BO_LAnd;
19107 break;
19108 case OO_PipePipe:
19109 BOK = BO_LOr;
19110 break;
19111 case OO_New:
19112 case OO_Delete:
19113 case OO_Array_New:
19114 case OO_Array_Delete:
19115 case OO_Slash:
19116 case OO_Percent:
19117 case OO_Tilde:
19118 case OO_Exclaim:
19119 case OO_Equal:
19120 case OO_Less:
19121 case OO_Greater:
19122 case OO_LessEqual:
19123 case OO_GreaterEqual:
19124 case OO_PlusEqual:
19125 case OO_MinusEqual:
19126 case OO_StarEqual:
19127 case OO_SlashEqual:
19128 case OO_PercentEqual:
19129 case OO_CaretEqual:
19130 case OO_AmpEqual:
19131 case OO_PipeEqual:
19132 case OO_LessLess:
19133 case OO_GreaterGreater:
19134 case OO_LessLessEqual:
19135 case OO_GreaterGreaterEqual:
19136 case OO_EqualEqual:
19137 case OO_ExclaimEqual:
19138 case OO_Spaceship:
19139 case OO_PlusPlus:
19140 case OO_MinusMinus:
19141 case OO_Comma:
19142 case OO_ArrowStar:
19143 case OO_Arrow:
19144 case OO_Call:
19145 case OO_Subscript:
19146 case OO_Conditional:
19147 case OO_Coawait:
19148 case NUM_OVERLOADED_OPERATORS:
19149 llvm_unreachable("Unexpected reduction identifier");
19150 case OO_None:
19151 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
19152 if (II->isStr("max"))
19153 BOK = BO_GT;
19154 else if (II->isStr("min"))
19155 BOK = BO_LT;
19156 }
19157 break;
19158 }
19159 SourceRange ReductionIdRange;
19160 if (ReductionIdScopeSpec.isValid())
19161 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
19162 else
19163 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
19164 ReductionIdRange.setEnd(ReductionId.getEndLoc());
19165
19166 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
19167 bool FirstIter = true;
19168 for (Expr *RefExpr : VarList) {
19169 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
19170 // OpenMP [2.1, C/C++]
19171 // A list item is a variable or array section, subject to the restrictions
19172 // specified in Section 2.4 on page 42 and in each of the sections
19173 // describing clauses and directives for which a list appears.
19174 // OpenMP [2.14.3.3, Restrictions, p.1]
19175 // A variable that is part of another variable (as an array or
19176 // structure element) cannot appear in a private clause.
19177 if (!FirstIter && IR != ER)
19178 ++IR;
19179 FirstIter = false;
19180 SourceLocation ELoc;
19181 SourceRange ERange;
19182 Expr *SimpleRefExpr = RefExpr;
19183 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
19184 /*AllowArraySection=*/true);
19185 if (Res.second) {
19186 // Try to find 'declare reduction' corresponding construct before using
19187 // builtin/overloaded operators.
19188 QualType Type = Context.DependentTy;
19189 CXXCastPath BasePath;
19190 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19191 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19192 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19193 Expr *ReductionOp = nullptr;
19194 if (S.CurContext->isDependentContext() &&
19195 (DeclareReductionRef.isUnset() ||
19196 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
19197 ReductionOp = DeclareReductionRef.get();
19198 // It will be analyzed later.
19199 RD.push(RefExpr, ReductionOp);
19200 }
19201 ValueDecl *D = Res.first;
19202 if (!D)
19203 continue;
19204
19205 Expr *TaskgroupDescriptor = nullptr;
19206 QualType Type;
19207 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
19208 auto *OASE = dyn_cast<OMPArraySectionExpr>(RefExpr->IgnoreParens());
19209 if (ASE) {
19210 Type = ASE->getType().getNonReferenceType();
19211 } else if (OASE) {
19212 QualType BaseType =
19213 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
19214 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
19215 Type = ATy->getElementType();
19216 else
19217 Type = BaseType->getPointeeType();
19218 Type = Type.getNonReferenceType();
19219 } else {
19220 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
19221 }
19222 auto *VD = dyn_cast<VarDecl>(D);
19223
19224 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19225 // A variable that appears in a private clause must not have an incomplete
19226 // type or a reference type.
19227 if (S.RequireCompleteType(ELoc, D->getType(),
19228 diag::err_omp_reduction_incomplete_type))
19229 continue;
19230 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19231 // A list item that appears in a reduction clause must not be
19232 // const-qualified.
19233 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
19234 /*AcceptIfMutable*/ false, ASE || OASE))
19235 continue;
19236
19237 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
19238 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
19239 // If a list-item is a reference type then it must bind to the same object
19240 // for all threads of the team.
19241 if (!ASE && !OASE) {
19242 if (VD) {
19243 VarDecl *VDDef = VD->getDefinition();
19244 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
19245 DSARefChecker Check(Stack);
19246 if (Check.Visit(VDDef->getInit())) {
19247 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
19248 << getOpenMPClauseName(ClauseKind) << ERange;
19249 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
19250 continue;
19251 }
19252 }
19253 }
19254
19255 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19256 // in a Construct]
19257 // Variables with the predetermined data-sharing attributes may not be
19258 // listed in data-sharing attributes clauses, except for the cases
19259 // listed below. For these exceptions only, listing a predetermined
19260 // variable in a data-sharing attribute clause is allowed and overrides
19261 // the variable's predetermined data-sharing attributes.
19262 // OpenMP [2.14.3.6, Restrictions, p.3]
19263 // Any number of reduction clauses can be specified on the directive,
19264 // but a list item can appear only once in the reduction clauses for that
19265 // directive.
19266 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19267 if (DVar.CKind == OMPC_reduction) {
19268 S.Diag(ELoc, diag::err_omp_once_referenced)
19269 << getOpenMPClauseName(ClauseKind);
19270 if (DVar.RefExpr)
19271 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
19272 continue;
19273 }
19274 if (DVar.CKind != OMPC_unknown) {
19275 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19276 << getOpenMPClauseName(DVar.CKind)
19277 << getOpenMPClauseName(OMPC_reduction);
19278 reportOriginalDsa(S, Stack, D, DVar);
19279 continue;
19280 }
19281
19282 // OpenMP [2.14.3.6, Restrictions, p.1]
19283 // A list item that appears in a reduction clause of a worksharing
19284 // construct must be shared in the parallel regions to which any of the
19285 // worksharing regions arising from the worksharing construct bind.
19286 if (isOpenMPWorksharingDirective(CurrDir) &&
19287 !isOpenMPParallelDirective(CurrDir) &&
19288 !isOpenMPTeamsDirective(CurrDir)) {
19289 DVar = Stack->getImplicitDSA(D, true);
19290 if (DVar.CKind != OMPC_shared) {
19291 S.Diag(ELoc, diag::err_omp_required_access)
19292 << getOpenMPClauseName(OMPC_reduction)
19293 << getOpenMPClauseName(OMPC_shared);
19294 reportOriginalDsa(S, Stack, D, DVar);
19295 continue;
19296 }
19297 }
19298 } else {
19299 // Threadprivates cannot be shared between threads, so dignose if the base
19300 // is a threadprivate variable.
19301 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19302 if (DVar.CKind == OMPC_threadprivate) {
19303 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19304 << getOpenMPClauseName(DVar.CKind)
19305 << getOpenMPClauseName(OMPC_reduction);
19306 reportOriginalDsa(S, Stack, D, DVar);
19307 continue;
19308 }
19309 }
19310
19311 // Try to find 'declare reduction' corresponding construct before using
19312 // builtin/overloaded operators.
19313 CXXCastPath BasePath;
19314 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19315 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19316 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19317 if (DeclareReductionRef.isInvalid())
19318 continue;
19319 if (S.CurContext->isDependentContext() &&
19320 (DeclareReductionRef.isUnset() ||
19321 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
19322 RD.push(RefExpr, DeclareReductionRef.get());
19323 continue;
19324 }
19325 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
19326 // Not allowed reduction identifier is found.
19327 S.Diag(ReductionId.getBeginLoc(),
19328 diag::err_omp_unknown_reduction_identifier)
19329 << Type << ReductionIdRange;
19330 continue;
19331 }
19332
19333 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19334 // The type of a list item that appears in a reduction clause must be valid
19335 // for the reduction-identifier. For a max or min reduction in C, the type
19336 // of the list item must be an allowed arithmetic data type: char, int,
19337 // float, double, or _Bool, possibly modified with long, short, signed, or
19338 // unsigned. For a max or min reduction in C++, the type of the list item
19339 // must be an allowed arithmetic data type: char, wchar_t, int, float,
19340 // double, or bool, possibly modified with long, short, signed, or unsigned.
19341 if (DeclareReductionRef.isUnset()) {
19342 if ((BOK == BO_GT || BOK == BO_LT) &&
19343 !(Type->isScalarType() ||
19344 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
19345 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
19346 << getOpenMPClauseName(ClauseKind) << S.getLangOpts().CPlusPlus;
19347 if (!ASE && !OASE) {
19348 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19349 VarDecl::DeclarationOnly;
19350 S.Diag(D->getLocation(),
19351 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19352 << D;
19353 }
19354 continue;
19355 }
19356 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
19357 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
19358 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
19359 << getOpenMPClauseName(ClauseKind);
19360 if (!ASE && !OASE) {
19361 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19362 VarDecl::DeclarationOnly;
19363 S.Diag(D->getLocation(),
19364 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19365 << D;
19366 }
19367 continue;
19368 }
19369 }
19370
19371 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
19372 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
19373 D->hasAttrs() ? &D->getAttrs() : nullptr);
19374 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
19375 D->hasAttrs() ? &D->getAttrs() : nullptr);
19376 QualType PrivateTy = Type;
19377
19378 // Try if we can determine constant lengths for all array sections and avoid
19379 // the VLA.
19380 bool ConstantLengthOASE = false;
19381 if (OASE) {
19382 bool SingleElement;
19383 llvm::SmallVector<llvm::APSInt, 4> ArraySizes;
19384 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
19385 Context, OASE, SingleElement, ArraySizes);
19386
19387 // If we don't have a single element, we must emit a constant array type.
19388 if (ConstantLengthOASE && !SingleElement) {
19389 for (llvm::APSInt &Size : ArraySizes)
19390 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
19391 ArrayType::Normal,
19392 /*IndexTypeQuals=*/0);
19393 }
19394 }
19395
19396 if ((OASE && !ConstantLengthOASE) ||
19397 (!OASE && !ASE &&
19398 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
19399 if (!Context.getTargetInfo().isVLASupported()) {
19400 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
19401 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19402 S.Diag(ELoc, diag::note_vla_unsupported);
19403 continue;
19404 } else {
19405 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19406 S.targetDiag(ELoc, diag::note_vla_unsupported);
19407 }
19408 }
19409 // For arrays/array sections only:
19410 // Create pseudo array type for private copy. The size for this array will
19411 // be generated during codegen.
19412 // For array subscripts or single variables Private Ty is the same as Type
19413 // (type of the variable or single array element).
19414 PrivateTy = Context.getVariableArrayType(
19415 Type,
19416 new (Context)
19417 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
19418 ArrayType::Normal, /*IndexTypeQuals=*/0, SourceRange());
19419 } else if (!ASE && !OASE &&
19420 Context.getAsArrayType(D->getType().getNonReferenceType())) {
19421 PrivateTy = D->getType().getNonReferenceType();
19422 }
19423 // Private copy.
19424 VarDecl *PrivateVD =
19425 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19426 D->hasAttrs() ? &D->getAttrs() : nullptr,
19427 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19428 // Add initializer for private variable.
19429 Expr *Init = nullptr;
19430 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
19431 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
19432 if (DeclareReductionRef.isUsable()) {
19433 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
19434 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
19435 if (DRD->getInitializer()) {
19436 Init = DRDRef;
19437 RHSVD->setInit(DRDRef);
19438 RHSVD->setInitStyle(VarDecl::CallInit);
19439 }
19440 } else {
19441 switch (BOK) {
19442 case BO_Add:
19443 case BO_Xor:
19444 case BO_Or:
19445 case BO_LOr:
19446 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
19447 if (Type->isScalarType() || Type->isAnyComplexType())
19448 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
19449 break;
19450 case BO_Mul:
19451 case BO_LAnd:
19452 if (Type->isScalarType() || Type->isAnyComplexType()) {
19453 // '*' and '&&' reduction ops - initializer is '1'.
19454 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
19455 }
19456 break;
19457 case BO_And: {
19458 // '&' reduction op - initializer is '~0'.
19459 QualType OrigType = Type;
19460 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
19461 Type = ComplexTy->getElementType();
19462 if (Type->isRealFloatingType()) {
19463 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
19464 Context.getFloatTypeSemantics(Type));
19465 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19466 Type, ELoc);
19467 } else if (Type->isScalarType()) {
19468 uint64_t Size = Context.getTypeSize(Type);
19469 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
19470 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
19471 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19472 }
19473 if (Init && OrigType->isAnyComplexType()) {
19474 // Init = 0xFFFF + 0xFFFFi;
19475 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
19476 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
19477 }
19478 Type = OrigType;
19479 break;
19480 }
19481 case BO_LT:
19482 case BO_GT: {
19483 // 'min' reduction op - initializer is 'Largest representable number in
19484 // the reduction list item type'.
19485 // 'max' reduction op - initializer is 'Least representable number in
19486 // the reduction list item type'.
19487 if (Type->isIntegerType() || Type->isPointerType()) {
19488 bool IsSigned = Type->hasSignedIntegerRepresentation();
19489 uint64_t Size = Context.getTypeSize(Type);
19490 QualType IntTy =
19491 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
19492 llvm::APInt InitValue =
19493 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
19494 : llvm::APInt::getMinValue(Size)
19495 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
19496 : llvm::APInt::getMaxValue(Size);
19497 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19498 if (Type->isPointerType()) {
19499 // Cast to pointer type.
19500 ExprResult CastExpr = S.BuildCStyleCastExpr(
19501 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
19502 if (CastExpr.isInvalid())
19503 continue;
19504 Init = CastExpr.get();
19505 }
19506 } else if (Type->isRealFloatingType()) {
19507 llvm::APFloat InitValue = llvm::APFloat::getLargest(
19508 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
19509 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19510 Type, ELoc);
19511 }
19512 break;
19513 }
19514 case BO_PtrMemD:
19515 case BO_PtrMemI:
19516 case BO_MulAssign:
19517 case BO_Div:
19518 case BO_Rem:
19519 case BO_Sub:
19520 case BO_Shl:
19521 case BO_Shr:
19522 case BO_LE:
19523 case BO_GE:
19524 case BO_EQ:
19525 case BO_NE:
19526 case BO_Cmp:
19527 case BO_AndAssign:
19528 case BO_XorAssign:
19529 case BO_OrAssign:
19530 case BO_Assign:
19531 case BO_AddAssign:
19532 case BO_SubAssign:
19533 case BO_DivAssign:
19534 case BO_RemAssign:
19535 case BO_ShlAssign:
19536 case BO_ShrAssign:
19537 case BO_Comma:
19538 llvm_unreachable("Unexpected reduction operation");
19539 }
19540 }
19541 if (Init && DeclareReductionRef.isUnset()) {
19542 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
19543 // Store initializer for single element in private copy. Will be used
19544 // during codegen.
19545 PrivateVD->setInit(RHSVD->getInit());
19546 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19547 } else if (!Init) {
19548 S.ActOnUninitializedDecl(RHSVD);
19549 // Store initializer for single element in private copy. Will be used
19550 // during codegen.
19551 PrivateVD->setInit(RHSVD->getInit());
19552 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19553 }
19554 if (RHSVD->isInvalidDecl())
19555 continue;
19556 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
19557 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
19558 << Type << ReductionIdRange;
19559 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19560 VarDecl::DeclarationOnly;
19561 S.Diag(D->getLocation(),
19562 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19563 << D;
19564 continue;
19565 }
19566 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
19567 ExprResult ReductionOp;
19568 if (DeclareReductionRef.isUsable()) {
19569 QualType RedTy = DeclareReductionRef.get()->getType();
19570 QualType PtrRedTy = Context.getPointerType(RedTy);
19571 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
19572 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
19573 if (!BasePath.empty()) {
19574 LHS = S.DefaultLvalueConversion(LHS.get());
19575 RHS = S.DefaultLvalueConversion(RHS.get());
19576 LHS = ImplicitCastExpr::Create(
19577 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
19578 LHS.get()->getValueKind(), FPOptionsOverride());
19579 RHS = ImplicitCastExpr::Create(
19580 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
19581 RHS.get()->getValueKind(), FPOptionsOverride());
19582 }
19583 FunctionProtoType::ExtProtoInfo EPI;
19584 QualType Params[] = {PtrRedTy, PtrRedTy};
19585 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
19586 auto *OVE = new (Context) OpaqueValueExpr(
19587 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
19588 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
19589 Expr *Args[] = {LHS.get(), RHS.get()};
19590 ReductionOp =
19591 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
19592 S.CurFPFeatureOverrides());
19593 } else {
19594 BinaryOperatorKind CombBOK = getRelatedCompoundReductionOp(BOK);
19595 if (Type->isRecordType() && CombBOK != BOK) {
19596 Sema::TentativeAnalysisScope Trap(S);
19597 ReductionOp =
19598 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19599 CombBOK, LHSDRE, RHSDRE);
19600 }
19601 if (!ReductionOp.isUsable()) {
19602 ReductionOp =
19603 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
19604 LHSDRE, RHSDRE);
19605 if (ReductionOp.isUsable()) {
19606 if (BOK != BO_LT && BOK != BO_GT) {
19607 ReductionOp =
19608 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19609 BO_Assign, LHSDRE, ReductionOp.get());
19610 } else {
19611 auto *ConditionalOp = new (Context)
19612 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
19613 RHSDRE, Type, VK_LValue, OK_Ordinary);
19614 ReductionOp =
19615 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19616 BO_Assign, LHSDRE, ConditionalOp);
19617 }
19618 }
19619 }
19620 if (ReductionOp.isUsable())
19621 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
19622 /*DiscardedValue*/ false);
19623 if (!ReductionOp.isUsable())
19624 continue;
19625 }
19626
19627 // Add copy operations for inscan reductions.
19628 // LHS = RHS;
19629 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
19630 if (ClauseKind == OMPC_reduction &&
19631 RD.RedModifier == OMPC_REDUCTION_inscan) {
19632 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
19633 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
19634 RHS.get());
19635 if (!CopyOpRes.isUsable())
19636 continue;
19637 CopyOpRes =
19638 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
19639 if (!CopyOpRes.isUsable())
19640 continue;
19641 // For simd directive and simd-based directives in simd mode no need to
19642 // construct temp array, need just a single temp element.
19643 if (Stack->getCurrentDirective() == OMPD_simd ||
19644 (S.getLangOpts().OpenMPSimd &&
19645 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
19646 VarDecl *TempArrayVD =
19647 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19648 D->hasAttrs() ? &D->getAttrs() : nullptr);
19649 // Add a constructor to the temp decl.
19650 S.ActOnUninitializedDecl(TempArrayVD);
19651 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
19652 } else {
19653 // Build temp array for prefix sum.
19654 auto *Dim = new (S.Context)
19655 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
19656 QualType ArrayTy =
19657 S.Context.getVariableArrayType(PrivateTy, Dim, ArrayType::Normal,
19658 /*IndexTypeQuals=*/0, {ELoc, ELoc});
19659 VarDecl *TempArrayVD =
19660 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
19661 D->hasAttrs() ? &D->getAttrs() : nullptr);
19662 // Add a constructor to the temp decl.
19663 S.ActOnUninitializedDecl(TempArrayVD);
19664 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
19665 TempArrayElem =
19666 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
19667 auto *Idx = new (S.Context)
19668 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
19669 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
19670 ELoc, Idx, ELoc);
19671 }
19672 }
19673
19674 // OpenMP [2.15.4.6, Restrictions, p.2]
19675 // A list item that appears in an in_reduction clause of a task construct
19676 // must appear in a task_reduction clause of a construct associated with a
19677 // taskgroup region that includes the participating task in its taskgroup
19678 // set. The construct associated with the innermost region that meets this
19679 // condition must specify the same reduction-identifier as the in_reduction
19680 // clause.
19681 if (ClauseKind == OMPC_in_reduction) {
19682 SourceRange ParentSR;
19683 BinaryOperatorKind ParentBOK;
19684 const Expr *ParentReductionOp = nullptr;
19685 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
19686 DSAStackTy::DSAVarData ParentBOKDSA =
19687 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
19688 ParentBOKTD);
19689 DSAStackTy::DSAVarData ParentReductionOpDSA =
19690 Stack->getTopMostTaskgroupReductionData(
19691 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
19692 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
19693 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
19694 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
19695 (DeclareReductionRef.isUsable() && IsParentBOK) ||
19696 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
19697 bool EmitError = true;
19698 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
19699 llvm::FoldingSetNodeID RedId, ParentRedId;
19700 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
19701 DeclareReductionRef.get()->Profile(RedId, Context,
19702 /*Canonical=*/true);
19703 EmitError = RedId != ParentRedId;
19704 }
19705 if (EmitError) {
19706 S.Diag(ReductionId.getBeginLoc(),
19707 diag::err_omp_reduction_identifier_mismatch)
19708 << ReductionIdRange << RefExpr->getSourceRange();
19709 S.Diag(ParentSR.getBegin(),
19710 diag::note_omp_previous_reduction_identifier)
19711 << ParentSR
19712 << (IsParentBOK ? ParentBOKDSA.RefExpr
19713 : ParentReductionOpDSA.RefExpr)
19714 ->getSourceRange();
19715 continue;
19716 }
19717 }
19718 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
19719 }
19720
19721 DeclRefExpr *Ref = nullptr;
19722 Expr *VarsExpr = RefExpr->IgnoreParens();
19723 if (!VD && !S.CurContext->isDependentContext()) {
19724 if (ASE || OASE) {
19725 TransformExprToCaptures RebuildToCapture(S, D);
19726 VarsExpr =
19727 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
19728 Ref = RebuildToCapture.getCapturedExpr();
19729 } else {
19730 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
19731 }
19732 if (!S.isOpenMPCapturedDecl(D)) {
19733 RD.ExprCaptures.emplace_back(Ref->getDecl());
19734 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19735 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
19736 if (!RefRes.isUsable())
19737 continue;
19738 ExprResult PostUpdateRes =
19739 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
19740 RefRes.get());
19741 if (!PostUpdateRes.isUsable())
19742 continue;
19743 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
19744 Stack->getCurrentDirective() == OMPD_taskgroup) {
19745 S.Diag(RefExpr->getExprLoc(),
19746 diag::err_omp_reduction_non_addressable_expression)
19747 << RefExpr->getSourceRange();
19748 continue;
19749 }
19750 RD.ExprPostUpdates.emplace_back(
19751 S.IgnoredValueConversions(PostUpdateRes.get()).get());
19752 }
19753 }
19754 }
19755 // All reduction items are still marked as reduction (to do not increase
19756 // code base size).
19757 unsigned Modifier = RD.RedModifier;
19758 // Consider task_reductions as reductions with task modifier. Required for
19759 // correct analysis of in_reduction clauses.
19760 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
19761 Modifier = OMPC_REDUCTION_task;
19762 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
19763 ASE || OASE);
19764 if (Modifier == OMPC_REDUCTION_task &&
19765 (CurrDir == OMPD_taskgroup ||
19766 ((isOpenMPParallelDirective(CurrDir) ||
19767 isOpenMPWorksharingDirective(CurrDir)) &&
19768 !isOpenMPSimdDirective(CurrDir)))) {
19769 if (DeclareReductionRef.isUsable())
19770 Stack->addTaskgroupReductionData(D, ReductionIdRange,
19771 DeclareReductionRef.get());
19772 else
19773 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
19774 }
19775 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
19776 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
19777 TempArrayElem.get());
19778 }
19779 return RD.Vars.empty();
19780 }
19781
ActOnOpenMPReductionClause(ArrayRef<Expr * > VarList,OpenMPReductionClauseModifier Modifier,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ModifierLoc,SourceLocation ColonLoc,SourceLocation EndLoc,CXXScopeSpec & ReductionIdScopeSpec,const DeclarationNameInfo & ReductionId,ArrayRef<Expr * > UnresolvedReductions)19782 OMPClause *Sema::ActOnOpenMPReductionClause(
19783 ArrayRef<Expr *> VarList, OpenMPReductionClauseModifier Modifier,
19784 SourceLocation StartLoc, SourceLocation LParenLoc,
19785 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
19786 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19787 ArrayRef<Expr *> UnresolvedReductions) {
19788 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
19789 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
19790 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
19791 /*Last=*/OMPC_REDUCTION_unknown)
19792 << getOpenMPClauseName(OMPC_reduction);
19793 return nullptr;
19794 }
19795 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
19796 // A reduction clause with the inscan reduction-modifier may only appear on a
19797 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
19798 // construct, a parallel worksharing-loop construct or a parallel
19799 // worksharing-loop SIMD construct.
19800 if (Modifier == OMPC_REDUCTION_inscan &&
19801 (DSAStack->getCurrentDirective() != OMPD_for &&
19802 DSAStack->getCurrentDirective() != OMPD_for_simd &&
19803 DSAStack->getCurrentDirective() != OMPD_simd &&
19804 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
19805 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
19806 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
19807 return nullptr;
19808 }
19809
19810 ReductionData RD(VarList.size(), Modifier);
19811 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_reduction, VarList,
19812 StartLoc, LParenLoc, ColonLoc, EndLoc,
19813 ReductionIdScopeSpec, ReductionId,
19814 UnresolvedReductions, RD))
19815 return nullptr;
19816
19817 return OMPReductionClause::Create(
19818 Context, StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc, Modifier,
19819 RD.Vars, ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
19820 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
19821 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
19822 buildPreInits(Context, RD.ExprCaptures),
19823 buildPostUpdate(*this, RD.ExprPostUpdates));
19824 }
19825
ActOnOpenMPTaskReductionClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ColonLoc,SourceLocation EndLoc,CXXScopeSpec & ReductionIdScopeSpec,const DeclarationNameInfo & ReductionId,ArrayRef<Expr * > UnresolvedReductions)19826 OMPClause *Sema::ActOnOpenMPTaskReductionClause(
19827 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19828 SourceLocation ColonLoc, SourceLocation EndLoc,
19829 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19830 ArrayRef<Expr *> UnresolvedReductions) {
19831 ReductionData RD(VarList.size());
19832 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_task_reduction, VarList,
19833 StartLoc, LParenLoc, ColonLoc, EndLoc,
19834 ReductionIdScopeSpec, ReductionId,
19835 UnresolvedReductions, RD))
19836 return nullptr;
19837
19838 return OMPTaskReductionClause::Create(
19839 Context, StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19840 ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
19841 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
19842 buildPreInits(Context, RD.ExprCaptures),
19843 buildPostUpdate(*this, RD.ExprPostUpdates));
19844 }
19845
ActOnOpenMPInReductionClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ColonLoc,SourceLocation EndLoc,CXXScopeSpec & ReductionIdScopeSpec,const DeclarationNameInfo & ReductionId,ArrayRef<Expr * > UnresolvedReductions)19846 OMPClause *Sema::ActOnOpenMPInReductionClause(
19847 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19848 SourceLocation ColonLoc, SourceLocation EndLoc,
19849 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19850 ArrayRef<Expr *> UnresolvedReductions) {
19851 ReductionData RD(VarList.size());
19852 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_in_reduction, VarList,
19853 StartLoc, LParenLoc, ColonLoc, EndLoc,
19854 ReductionIdScopeSpec, ReductionId,
19855 UnresolvedReductions, RD))
19856 return nullptr;
19857
19858 return OMPInReductionClause::Create(
19859 Context, StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19860 ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
19861 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
19862 buildPreInits(Context, RD.ExprCaptures),
19863 buildPostUpdate(*this, RD.ExprPostUpdates));
19864 }
19865
CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,SourceLocation LinLoc)19866 bool Sema::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
19867 SourceLocation LinLoc) {
19868 if ((!LangOpts.CPlusPlus && LinKind != OMPC_LINEAR_val) ||
19869 LinKind == OMPC_LINEAR_unknown) {
19870 Diag(LinLoc, diag::err_omp_wrong_linear_modifier) << LangOpts.CPlusPlus;
19871 return true;
19872 }
19873 return false;
19874 }
19875
CheckOpenMPLinearDecl(const ValueDecl * D,SourceLocation ELoc,OpenMPLinearClauseKind LinKind,QualType Type,bool IsDeclareSimd)19876 bool Sema::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc,
19877 OpenMPLinearClauseKind LinKind, QualType Type,
19878 bool IsDeclareSimd) {
19879 const auto *VD = dyn_cast_or_null<VarDecl>(D);
19880 // A variable must not have an incomplete type or a reference type.
19881 if (RequireCompleteType(ELoc, Type, diag::err_omp_linear_incomplete_type))
19882 return true;
19883 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
19884 !Type->isReferenceType()) {
19885 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
19886 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
19887 return true;
19888 }
19889 Type = Type.getNonReferenceType();
19890
19891 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19892 // A variable that is privatized must not have a const-qualified type
19893 // unless it is of class type with a mutable member. This restriction does
19894 // not apply to the firstprivate clause, nor to the linear clause on
19895 // declarative directives (like declare simd).
19896 if (!IsDeclareSimd &&
19897 rejectConstNotMutableType(*this, D, Type, OMPC_linear, ELoc))
19898 return true;
19899
19900 // A list item must be of integral or pointer type.
19901 Type = Type.getUnqualifiedType().getCanonicalType();
19902 const auto *Ty = Type.getTypePtrOrNull();
19903 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
19904 !Ty->isIntegralType(Context) && !Ty->isPointerType())) {
19905 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
19906 if (D) {
19907 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19908 VarDecl::DeclarationOnly;
19909 Diag(D->getLocation(),
19910 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19911 << D;
19912 }
19913 return true;
19914 }
19915 return false;
19916 }
19917
ActOnOpenMPLinearClause(ArrayRef<Expr * > VarList,Expr * Step,SourceLocation StartLoc,SourceLocation LParenLoc,OpenMPLinearClauseKind LinKind,SourceLocation LinLoc,SourceLocation ColonLoc,SourceLocation EndLoc)19918 OMPClause *Sema::ActOnOpenMPLinearClause(
19919 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
19920 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
19921 SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
19922 SmallVector<Expr *, 8> Vars;
19923 SmallVector<Expr *, 8> Privates;
19924 SmallVector<Expr *, 8> Inits;
19925 SmallVector<Decl *, 4> ExprCaptures;
19926 SmallVector<Expr *, 4> ExprPostUpdates;
19927 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
19928 LinKind = OMPC_LINEAR_val;
19929 for (Expr *RefExpr : VarList) {
19930 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19931 SourceLocation ELoc;
19932 SourceRange ERange;
19933 Expr *SimpleRefExpr = RefExpr;
19934 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
19935 if (Res.second) {
19936 // It will be analyzed later.
19937 Vars.push_back(RefExpr);
19938 Privates.push_back(nullptr);
19939 Inits.push_back(nullptr);
19940 }
19941 ValueDecl *D = Res.first;
19942 if (!D)
19943 continue;
19944
19945 QualType Type = D->getType();
19946 auto *VD = dyn_cast<VarDecl>(D);
19947
19948 // OpenMP [2.14.3.7, linear clause]
19949 // A list-item cannot appear in more than one linear clause.
19950 // A list-item that appears in a linear clause cannot appear in any
19951 // other data-sharing attribute clause.
19952 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19953 if (DVar.RefExpr) {
19954 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
19955 << getOpenMPClauseName(OMPC_linear);
19956 reportOriginalDsa(*this, DSAStack, D, DVar);
19957 continue;
19958 }
19959
19960 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
19961 continue;
19962 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19963
19964 // Build private copy of original var.
19965 VarDecl *Private =
19966 buildVarDecl(*this, ELoc, Type, D->getName(),
19967 D->hasAttrs() ? &D->getAttrs() : nullptr,
19968 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19969 DeclRefExpr *PrivateRef = buildDeclRefExpr(*this, Private, Type, ELoc);
19970 // Build var to save initial value.
19971 VarDecl *Init = buildVarDecl(*this, ELoc, Type, ".linear.start");
19972 Expr *InitExpr;
19973 DeclRefExpr *Ref = nullptr;
19974 if (!VD && !CurContext->isDependentContext()) {
19975 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
19976 if (!isOpenMPCapturedDecl(D)) {
19977 ExprCaptures.push_back(Ref->getDecl());
19978 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19979 ExprResult RefRes = DefaultLvalueConversion(Ref);
19980 if (!RefRes.isUsable())
19981 continue;
19982 ExprResult PostUpdateRes =
19983 BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
19984 SimpleRefExpr, RefRes.get());
19985 if (!PostUpdateRes.isUsable())
19986 continue;
19987 ExprPostUpdates.push_back(
19988 IgnoredValueConversions(PostUpdateRes.get()).get());
19989 }
19990 }
19991 }
19992 if (LinKind == OMPC_LINEAR_uval)
19993 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
19994 else
19995 InitExpr = VD ? SimpleRefExpr : Ref;
19996 AddInitializerToDecl(Init, DefaultLvalueConversion(InitExpr).get(),
19997 /*DirectInit=*/false);
19998 DeclRefExpr *InitRef = buildDeclRefExpr(*this, Init, Type, ELoc);
19999
20000 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
20001 Vars.push_back((VD || CurContext->isDependentContext())
20002 ? RefExpr->IgnoreParens()
20003 : Ref);
20004 Privates.push_back(PrivateRef);
20005 Inits.push_back(InitRef);
20006 }
20007
20008 if (Vars.empty())
20009 return nullptr;
20010
20011 Expr *StepExpr = Step;
20012 Expr *CalcStepExpr = nullptr;
20013 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
20014 !Step->isInstantiationDependent() &&
20015 !Step->containsUnexpandedParameterPack()) {
20016 SourceLocation StepLoc = Step->getBeginLoc();
20017 ExprResult Val = PerformOpenMPImplicitIntegerConversion(StepLoc, Step);
20018 if (Val.isInvalid())
20019 return nullptr;
20020 StepExpr = Val.get();
20021
20022 // Build var to save the step value.
20023 VarDecl *SaveVar =
20024 buildVarDecl(*this, StepLoc, StepExpr->getType(), ".linear.step");
20025 ExprResult SaveRef =
20026 buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc);
20027 ExprResult CalcStep =
20028 BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr);
20029 CalcStep = ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false);
20030
20031 // Warn about zero linear step (it would be probably better specified as
20032 // making corresponding variables 'const').
20033 if (std::optional<llvm::APSInt> Result =
20034 StepExpr->getIntegerConstantExpr(Context)) {
20035 if (!Result->isNegative() && !Result->isStrictlyPositive())
20036 Diag(StepLoc, diag::warn_omp_linear_step_zero)
20037 << Vars[0] << (Vars.size() > 1);
20038 } else if (CalcStep.isUsable()) {
20039 // Calculate the step beforehand instead of doing this on each iteration.
20040 // (This is not used if the number of iterations may be kfold-ed).
20041 CalcStepExpr = CalcStep.get();
20042 }
20043 }
20044
20045 return OMPLinearClause::Create(Context, StartLoc, LParenLoc, LinKind, LinLoc,
20046 ColonLoc, EndLoc, Vars, Privates, Inits,
20047 StepExpr, CalcStepExpr,
20048 buildPreInits(Context, ExprCaptures),
20049 buildPostUpdate(*this, ExprPostUpdates));
20050 }
20051
FinishOpenMPLinearClause(OMPLinearClause & Clause,DeclRefExpr * IV,Expr * NumIterations,Sema & SemaRef,Scope * S,DSAStackTy * Stack)20052 static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
20053 Expr *NumIterations, Sema &SemaRef,
20054 Scope *S, DSAStackTy *Stack) {
20055 // Walk the vars and build update/final expressions for the CodeGen.
20056 SmallVector<Expr *, 8> Updates;
20057 SmallVector<Expr *, 8> Finals;
20058 SmallVector<Expr *, 8> UsedExprs;
20059 Expr *Step = Clause.getStep();
20060 Expr *CalcStep = Clause.getCalcStep();
20061 // OpenMP [2.14.3.7, linear clause]
20062 // If linear-step is not specified it is assumed to be 1.
20063 if (!Step)
20064 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
20065 else if (CalcStep)
20066 Step = cast<BinaryOperator>(CalcStep)->getLHS();
20067 bool HasErrors = false;
20068 auto CurInit = Clause.inits().begin();
20069 auto CurPrivate = Clause.privates().begin();
20070 OpenMPLinearClauseKind LinKind = Clause.getModifier();
20071 for (Expr *RefExpr : Clause.varlists()) {
20072 SourceLocation ELoc;
20073 SourceRange ERange;
20074 Expr *SimpleRefExpr = RefExpr;
20075 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20076 ValueDecl *D = Res.first;
20077 if (Res.second || !D) {
20078 Updates.push_back(nullptr);
20079 Finals.push_back(nullptr);
20080 HasErrors = true;
20081 continue;
20082 }
20083 auto &&Info = Stack->isLoopControlVariable(D);
20084 // OpenMP [2.15.11, distribute simd Construct]
20085 // A list item may not appear in a linear clause, unless it is the loop
20086 // iteration variable.
20087 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
20088 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
20089 SemaRef.Diag(ELoc,
20090 diag::err_omp_linear_distribute_var_non_loop_iteration);
20091 Updates.push_back(nullptr);
20092 Finals.push_back(nullptr);
20093 HasErrors = true;
20094 continue;
20095 }
20096 Expr *InitExpr = *CurInit;
20097
20098 // Build privatized reference to the current linear var.
20099 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
20100 Expr *CapturedRef;
20101 if (LinKind == OMPC_LINEAR_uval)
20102 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
20103 else
20104 CapturedRef =
20105 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
20106 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
20107 /*RefersToCapture=*/true);
20108
20109 // Build update: Var = InitExpr + IV * Step
20110 ExprResult Update;
20111 if (!Info.first)
20112 Update = buildCounterUpdate(
20113 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
20114 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
20115 else
20116 Update = *CurPrivate;
20117 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
20118 /*DiscardedValue*/ false);
20119
20120 // Build final: Var = PrivCopy;
20121 ExprResult Final;
20122 if (!Info.first)
20123 Final = SemaRef.BuildBinOp(
20124 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
20125 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
20126 else
20127 Final = *CurPrivate;
20128 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
20129 /*DiscardedValue*/ false);
20130
20131 if (!Update.isUsable() || !Final.isUsable()) {
20132 Updates.push_back(nullptr);
20133 Finals.push_back(nullptr);
20134 UsedExprs.push_back(nullptr);
20135 HasErrors = true;
20136 } else {
20137 Updates.push_back(Update.get());
20138 Finals.push_back(Final.get());
20139 if (!Info.first)
20140 UsedExprs.push_back(SimpleRefExpr);
20141 }
20142 ++CurInit;
20143 ++CurPrivate;
20144 }
20145 if (Expr *S = Clause.getStep())
20146 UsedExprs.push_back(S);
20147 // Fill the remaining part with the nullptr.
20148 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
20149 Clause.setUpdates(Updates);
20150 Clause.setFinals(Finals);
20151 Clause.setUsedExprs(UsedExprs);
20152 return HasErrors;
20153 }
20154
ActOnOpenMPAlignedClause(ArrayRef<Expr * > VarList,Expr * Alignment,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ColonLoc,SourceLocation EndLoc)20155 OMPClause *Sema::ActOnOpenMPAlignedClause(
20156 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
20157 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
20158 SmallVector<Expr *, 8> Vars;
20159 for (Expr *RefExpr : VarList) {
20160 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20161 SourceLocation ELoc;
20162 SourceRange ERange;
20163 Expr *SimpleRefExpr = RefExpr;
20164 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
20165 if (Res.second) {
20166 // It will be analyzed later.
20167 Vars.push_back(RefExpr);
20168 }
20169 ValueDecl *D = Res.first;
20170 if (!D)
20171 continue;
20172
20173 QualType QType = D->getType();
20174 auto *VD = dyn_cast<VarDecl>(D);
20175
20176 // OpenMP [2.8.1, simd construct, Restrictions]
20177 // The type of list items appearing in the aligned clause must be
20178 // array, pointer, reference to array, or reference to pointer.
20179 QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20180 const Type *Ty = QType.getTypePtrOrNull();
20181 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
20182 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
20183 << QType << getLangOpts().CPlusPlus << ERange;
20184 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20185 VarDecl::DeclarationOnly;
20186 Diag(D->getLocation(),
20187 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20188 << D;
20189 continue;
20190 }
20191
20192 // OpenMP [2.8.1, simd construct, Restrictions]
20193 // A list-item cannot appear in more than one aligned clause.
20194 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
20195 Diag(ELoc, diag::err_omp_used_in_clause_twice)
20196 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
20197 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
20198 << getOpenMPClauseName(OMPC_aligned);
20199 continue;
20200 }
20201
20202 DeclRefExpr *Ref = nullptr;
20203 if (!VD && isOpenMPCapturedDecl(D))
20204 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
20205 Vars.push_back(DefaultFunctionArrayConversion(
20206 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
20207 .get());
20208 }
20209
20210 // OpenMP [2.8.1, simd construct, Description]
20211 // The parameter of the aligned clause, alignment, must be a constant
20212 // positive integer expression.
20213 // If no optional parameter is specified, implementation-defined default
20214 // alignments for SIMD instructions on the target platforms are assumed.
20215 if (Alignment != nullptr) {
20216 ExprResult AlignResult =
20217 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
20218 if (AlignResult.isInvalid())
20219 return nullptr;
20220 Alignment = AlignResult.get();
20221 }
20222 if (Vars.empty())
20223 return nullptr;
20224
20225 return OMPAlignedClause::Create(Context, StartLoc, LParenLoc, ColonLoc,
20226 EndLoc, Vars, Alignment);
20227 }
20228
ActOnOpenMPCopyinClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)20229 OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
20230 SourceLocation StartLoc,
20231 SourceLocation LParenLoc,
20232 SourceLocation EndLoc) {
20233 SmallVector<Expr *, 8> Vars;
20234 SmallVector<Expr *, 8> SrcExprs;
20235 SmallVector<Expr *, 8> DstExprs;
20236 SmallVector<Expr *, 8> AssignmentOps;
20237 for (Expr *RefExpr : VarList) {
20238 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
20239 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20240 // It will be analyzed later.
20241 Vars.push_back(RefExpr);
20242 SrcExprs.push_back(nullptr);
20243 DstExprs.push_back(nullptr);
20244 AssignmentOps.push_back(nullptr);
20245 continue;
20246 }
20247
20248 SourceLocation ELoc = RefExpr->getExprLoc();
20249 // OpenMP [2.1, C/C++]
20250 // A list item is a variable name.
20251 // OpenMP [2.14.4.1, Restrictions, p.1]
20252 // A list item that appears in a copyin clause must be threadprivate.
20253 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
20254 if (!DE || !isa<VarDecl>(DE->getDecl())) {
20255 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
20256 << 0 << RefExpr->getSourceRange();
20257 continue;
20258 }
20259
20260 Decl *D = DE->getDecl();
20261 auto *VD = cast<VarDecl>(D);
20262
20263 QualType Type = VD->getType();
20264 if (Type->isDependentType() || Type->isInstantiationDependentType()) {
20265 // It will be analyzed later.
20266 Vars.push_back(DE);
20267 SrcExprs.push_back(nullptr);
20268 DstExprs.push_back(nullptr);
20269 AssignmentOps.push_back(nullptr);
20270 continue;
20271 }
20272
20273 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
20274 // A list item that appears in a copyin clause must be threadprivate.
20275 if (!DSAStack->isThreadPrivate(VD)) {
20276 Diag(ELoc, diag::err_omp_required_access)
20277 << getOpenMPClauseName(OMPC_copyin)
20278 << getOpenMPDirectiveName(OMPD_threadprivate);
20279 continue;
20280 }
20281
20282 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20283 // A variable of class type (or array thereof) that appears in a
20284 // copyin clause requires an accessible, unambiguous copy assignment
20285 // operator for the class type.
20286 QualType ElemType = Context.getBaseElementType(Type).getNonReferenceType();
20287 VarDecl *SrcVD =
20288 buildVarDecl(*this, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
20289 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20290 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
20291 *this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
20292 VarDecl *DstVD =
20293 buildVarDecl(*this, DE->getBeginLoc(), ElemType, ".copyin.dst",
20294 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20295 DeclRefExpr *PseudoDstExpr =
20296 buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc());
20297 // For arrays generate assignment operation for single element and replace
20298 // it by the original array element in CodeGen.
20299 ExprResult AssignmentOp =
20300 BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, PseudoDstExpr,
20301 PseudoSrcExpr);
20302 if (AssignmentOp.isInvalid())
20303 continue;
20304 AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
20305 /*DiscardedValue*/ false);
20306 if (AssignmentOp.isInvalid())
20307 continue;
20308
20309 DSAStack->addDSA(VD, DE, OMPC_copyin);
20310 Vars.push_back(DE);
20311 SrcExprs.push_back(PseudoSrcExpr);
20312 DstExprs.push_back(PseudoDstExpr);
20313 AssignmentOps.push_back(AssignmentOp.get());
20314 }
20315
20316 if (Vars.empty())
20317 return nullptr;
20318
20319 return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars,
20320 SrcExprs, DstExprs, AssignmentOps);
20321 }
20322
ActOnOpenMPCopyprivateClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)20323 OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
20324 SourceLocation StartLoc,
20325 SourceLocation LParenLoc,
20326 SourceLocation EndLoc) {
20327 SmallVector<Expr *, 8> Vars;
20328 SmallVector<Expr *, 8> SrcExprs;
20329 SmallVector<Expr *, 8> DstExprs;
20330 SmallVector<Expr *, 8> AssignmentOps;
20331 for (Expr *RefExpr : VarList) {
20332 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20333 SourceLocation ELoc;
20334 SourceRange ERange;
20335 Expr *SimpleRefExpr = RefExpr;
20336 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
20337 if (Res.second) {
20338 // It will be analyzed later.
20339 Vars.push_back(RefExpr);
20340 SrcExprs.push_back(nullptr);
20341 DstExprs.push_back(nullptr);
20342 AssignmentOps.push_back(nullptr);
20343 }
20344 ValueDecl *D = Res.first;
20345 if (!D)
20346 continue;
20347
20348 QualType Type = D->getType();
20349 auto *VD = dyn_cast<VarDecl>(D);
20350
20351 // OpenMP [2.14.4.2, Restrictions, p.2]
20352 // A list item that appears in a copyprivate clause may not appear in a
20353 // private or firstprivate clause on the single construct.
20354 if (!VD || !DSAStack->isThreadPrivate(VD)) {
20355 DSAStackTy::DSAVarData DVar =
20356 DSAStack->getTopDSA(D, /*FromParent=*/false);
20357 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
20358 DVar.RefExpr) {
20359 Diag(ELoc, diag::err_omp_wrong_dsa)
20360 << getOpenMPClauseName(DVar.CKind)
20361 << getOpenMPClauseName(OMPC_copyprivate);
20362 reportOriginalDsa(*this, DSAStack, D, DVar);
20363 continue;
20364 }
20365
20366 // OpenMP [2.11.4.2, Restrictions, p.1]
20367 // All list items that appear in a copyprivate clause must be either
20368 // threadprivate or private in the enclosing context.
20369 if (DVar.CKind == OMPC_unknown) {
20370 DVar = DSAStack->getImplicitDSA(D, false);
20371 if (DVar.CKind == OMPC_shared) {
20372 Diag(ELoc, diag::err_omp_required_access)
20373 << getOpenMPClauseName(OMPC_copyprivate)
20374 << "threadprivate or private in the enclosing context";
20375 reportOriginalDsa(*this, DSAStack, D, DVar);
20376 continue;
20377 }
20378 }
20379 }
20380
20381 // Variably modified types are not supported.
20382 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType()) {
20383 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
20384 << getOpenMPClauseName(OMPC_copyprivate) << Type
20385 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
20386 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20387 VarDecl::DeclarationOnly;
20388 Diag(D->getLocation(),
20389 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20390 << D;
20391 continue;
20392 }
20393
20394 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20395 // A variable of class type (or array thereof) that appears in a
20396 // copyin clause requires an accessible, unambiguous copy assignment
20397 // operator for the class type.
20398 Type = Context.getBaseElementType(Type.getNonReferenceType())
20399 .getUnqualifiedType();
20400 VarDecl *SrcVD =
20401 buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
20402 D->hasAttrs() ? &D->getAttrs() : nullptr);
20403 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(*this, SrcVD, Type, ELoc);
20404 VarDecl *DstVD =
20405 buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
20406 D->hasAttrs() ? &D->getAttrs() : nullptr);
20407 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
20408 ExprResult AssignmentOp = BuildBinOp(
20409 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
20410 if (AssignmentOp.isInvalid())
20411 continue;
20412 AssignmentOp =
20413 ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false);
20414 if (AssignmentOp.isInvalid())
20415 continue;
20416
20417 // No need to mark vars as copyprivate, they are already threadprivate or
20418 // implicitly private.
20419 assert(VD || isOpenMPCapturedDecl(D));
20420 Vars.push_back(
20421 VD ? RefExpr->IgnoreParens()
20422 : buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false));
20423 SrcExprs.push_back(PseudoSrcExpr);
20424 DstExprs.push_back(PseudoDstExpr);
20425 AssignmentOps.push_back(AssignmentOp.get());
20426 }
20427
20428 if (Vars.empty())
20429 return nullptr;
20430
20431 return OMPCopyprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
20432 Vars, SrcExprs, DstExprs, AssignmentOps);
20433 }
20434
ActOnOpenMPFlushClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)20435 OMPClause *Sema::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
20436 SourceLocation StartLoc,
20437 SourceLocation LParenLoc,
20438 SourceLocation EndLoc) {
20439 if (VarList.empty())
20440 return nullptr;
20441
20442 return OMPFlushClause::Create(Context, StartLoc, LParenLoc, EndLoc, VarList);
20443 }
20444
20445 /// Tries to find omp_depend_t. type.
findOMPDependT(Sema & S,SourceLocation Loc,DSAStackTy * Stack,bool Diagnose=true)20446 static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
20447 bool Diagnose = true) {
20448 QualType OMPDependT = Stack->getOMPDependT();
20449 if (!OMPDependT.isNull())
20450 return true;
20451 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
20452 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
20453 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
20454 if (Diagnose)
20455 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
20456 return false;
20457 }
20458 Stack->setOMPDependT(PT.get());
20459 return true;
20460 }
20461
ActOnOpenMPDepobjClause(Expr * Depobj,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)20462 OMPClause *Sema::ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc,
20463 SourceLocation LParenLoc,
20464 SourceLocation EndLoc) {
20465 if (!Depobj)
20466 return nullptr;
20467
20468 bool OMPDependTFound = findOMPDependT(*this, StartLoc, DSAStack);
20469
20470 // OpenMP 5.0, 2.17.10.1 depobj Construct
20471 // depobj is an lvalue expression of type omp_depend_t.
20472 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
20473 !Depobj->isInstantiationDependent() &&
20474 !Depobj->containsUnexpandedParameterPack() &&
20475 (OMPDependTFound &&
20476 !Context.typesAreCompatible(DSAStack->getOMPDependT(), Depobj->getType(),
20477 /*CompareUnqualified=*/true))) {
20478 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20479 << 0 << Depobj->getType() << Depobj->getSourceRange();
20480 }
20481
20482 if (!Depobj->isLValue()) {
20483 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20484 << 1 << Depobj->getSourceRange();
20485 }
20486
20487 return OMPDepobjClause::Create(Context, StartLoc, LParenLoc, EndLoc, Depobj);
20488 }
20489
20490 OMPClause *
ActOnOpenMPDependClause(const OMPDependClause::DependDataTy & Data,Expr * DepModifier,ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)20491 Sema::ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data,
20492 Expr *DepModifier, ArrayRef<Expr *> VarList,
20493 SourceLocation StartLoc, SourceLocation LParenLoc,
20494 SourceLocation EndLoc) {
20495 OpenMPDependClauseKind DepKind = Data.DepKind;
20496 SourceLocation DepLoc = Data.DepLoc;
20497 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
20498 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
20499 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20500 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
20501 return nullptr;
20502 }
20503 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
20504 DepKind == OMPC_DEPEND_mutexinoutset) {
20505 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
20506 return nullptr;
20507 }
20508 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
20509 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20510 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
20511 DepKind == OMPC_DEPEND_sink ||
20512 ((LangOpts.OpenMP < 50 ||
20513 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20514 DepKind == OMPC_DEPEND_depobj))) {
20515 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
20516 OMPC_DEPEND_outallmemory,
20517 OMPC_DEPEND_inoutallmemory};
20518 if (LangOpts.OpenMP < 50 || DSAStack->getCurrentDirective() == OMPD_depobj)
20519 Except.push_back(OMPC_DEPEND_depobj);
20520 if (LangOpts.OpenMP < 51)
20521 Except.push_back(OMPC_DEPEND_inoutset);
20522 std::string Expected = (LangOpts.OpenMP >= 50 && !DepModifier)
20523 ? "depend modifier(iterator) or "
20524 : "";
20525 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20526 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
20527 /*Last=*/OMPC_DEPEND_unknown,
20528 Except)
20529 << getOpenMPClauseName(OMPC_depend);
20530 return nullptr;
20531 }
20532 if (DepModifier &&
20533 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
20534 Diag(DepModifier->getExprLoc(),
20535 diag::err_omp_depend_sink_source_with_modifier);
20536 return nullptr;
20537 }
20538 if (DepModifier &&
20539 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
20540 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
20541
20542 SmallVector<Expr *, 8> Vars;
20543 DSAStackTy::OperatorOffsetTy OpsOffs;
20544 llvm::APSInt DepCounter(/*BitWidth=*/32);
20545 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20546 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
20547 if (const Expr *OrderedCountExpr =
20548 DSAStack->getParentOrderedRegionParam().first) {
20549 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Context);
20550 TotalDepCount.setIsUnsigned(/*Val=*/true);
20551 }
20552 }
20553 for (Expr *RefExpr : VarList) {
20554 assert(RefExpr && "NULL expr in OpenMP shared clause.");
20555 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20556 // It will be analyzed later.
20557 Vars.push_back(RefExpr);
20558 continue;
20559 }
20560
20561 SourceLocation ELoc = RefExpr->getExprLoc();
20562 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20563 if (DepKind == OMPC_DEPEND_sink) {
20564 if (DSAStack->getParentOrderedRegionParam().first &&
20565 DepCounter >= TotalDepCount) {
20566 Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
20567 continue;
20568 }
20569 ++DepCounter;
20570 // OpenMP [2.13.9, Summary]
20571 // depend(dependence-type : vec), where dependence-type is:
20572 // 'sink' and where vec is the iteration vector, which has the form:
20573 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
20574 // where n is the value specified by the ordered clause in the loop
20575 // directive, xi denotes the loop iteration variable of the i-th nested
20576 // loop associated with the loop directive, and di is a constant
20577 // non-negative integer.
20578 if (CurContext->isDependentContext()) {
20579 // It will be analyzed later.
20580 Vars.push_back(RefExpr);
20581 continue;
20582 }
20583 SimpleExpr = SimpleExpr->IgnoreImplicit();
20584 OverloadedOperatorKind OOK = OO_None;
20585 SourceLocation OOLoc;
20586 Expr *LHS = SimpleExpr;
20587 Expr *RHS = nullptr;
20588 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
20589 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
20590 OOLoc = BO->getOperatorLoc();
20591 LHS = BO->getLHS()->IgnoreParenImpCasts();
20592 RHS = BO->getRHS()->IgnoreParenImpCasts();
20593 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
20594 OOK = OCE->getOperator();
20595 OOLoc = OCE->getOperatorLoc();
20596 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20597 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
20598 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
20599 OOK = MCE->getMethodDecl()
20600 ->getNameInfo()
20601 .getName()
20602 .getCXXOverloadedOperator();
20603 OOLoc = MCE->getCallee()->getExprLoc();
20604 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
20605 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20606 }
20607 SourceLocation ELoc;
20608 SourceRange ERange;
20609 auto Res = getPrivateItem(*this, LHS, ELoc, ERange);
20610 if (Res.second) {
20611 // It will be analyzed later.
20612 Vars.push_back(RefExpr);
20613 }
20614 ValueDecl *D = Res.first;
20615 if (!D)
20616 continue;
20617
20618 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
20619 Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
20620 continue;
20621 }
20622 if (RHS) {
20623 ExprResult RHSRes = VerifyPositiveIntegerConstantInClause(
20624 RHS, OMPC_depend, /*StrictlyPositive=*/false);
20625 if (RHSRes.isInvalid())
20626 continue;
20627 }
20628 if (!CurContext->isDependentContext() &&
20629 DSAStack->getParentOrderedRegionParam().first &&
20630 DepCounter != DSAStack->isParentLoopControlVariable(D).first) {
20631 const ValueDecl *VD =
20632 DSAStack->getParentLoopControlVariable(DepCounter.getZExtValue());
20633 if (VD)
20634 Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20635 << 1 << VD;
20636 else
20637 Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration) << 0;
20638 continue;
20639 }
20640 OpsOffs.emplace_back(RHS, OOK);
20641 } else {
20642 bool OMPDependTFound = LangOpts.OpenMP >= 50;
20643 if (OMPDependTFound)
20644 OMPDependTFound = findOMPDependT(*this, StartLoc, DSAStack,
20645 DepKind == OMPC_DEPEND_depobj);
20646 if (DepKind == OMPC_DEPEND_depobj) {
20647 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20648 // List items used in depend clauses with the depobj dependence type
20649 // must be expressions of the omp_depend_t type.
20650 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20651 !RefExpr->isInstantiationDependent() &&
20652 !RefExpr->containsUnexpandedParameterPack() &&
20653 (OMPDependTFound &&
20654 !Context.hasSameUnqualifiedType(DSAStack->getOMPDependT(),
20655 RefExpr->getType()))) {
20656 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20657 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
20658 continue;
20659 }
20660 if (!RefExpr->isLValue()) {
20661 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20662 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
20663 continue;
20664 }
20665 } else {
20666 // OpenMP 5.0 [2.17.11, Restrictions]
20667 // List items used in depend clauses cannot be zero-length array
20668 // sections.
20669 QualType ExprTy = RefExpr->getType().getNonReferenceType();
20670 const auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr);
20671 if (OASE) {
20672 QualType BaseType =
20673 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
20674 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20675 ExprTy = ATy->getElementType();
20676 else
20677 ExprTy = BaseType->getPointeeType();
20678 ExprTy = ExprTy.getNonReferenceType();
20679 const Expr *Length = OASE->getLength();
20680 Expr::EvalResult Result;
20681 if (Length && !Length->isValueDependent() &&
20682 Length->EvaluateAsInt(Result, Context) &&
20683 Result.Val.getInt().isZero()) {
20684 Diag(ELoc,
20685 diag::err_omp_depend_zero_length_array_section_not_allowed)
20686 << SimpleExpr->getSourceRange();
20687 continue;
20688 }
20689 }
20690
20691 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20692 // List items used in depend clauses with the in, out, inout,
20693 // inoutset, or mutexinoutset dependence types cannot be
20694 // expressions of the omp_depend_t type.
20695 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20696 !RefExpr->isInstantiationDependent() &&
20697 !RefExpr->containsUnexpandedParameterPack() &&
20698 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
20699 (OMPDependTFound &&
20700 DSAStack->getOMPDependT().getTypePtr() == ExprTy.getTypePtr()))) {
20701 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20702 << (LangOpts.OpenMP >= 50 ? 1 : 0)
20703 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
20704 continue;
20705 }
20706
20707 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
20708 if (ASE && !ASE->getBase()->isTypeDependent() &&
20709 !ASE->getBase()->getType().getNonReferenceType()->isPointerType() &&
20710 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
20711 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20712 << (LangOpts.OpenMP >= 50 ? 1 : 0)
20713 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
20714 continue;
20715 }
20716
20717 ExprResult Res;
20718 {
20719 Sema::TentativeAnalysisScope Trap(*this);
20720 Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
20721 RefExpr->IgnoreParenImpCasts());
20722 }
20723 if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr) &&
20724 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
20725 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20726 << (LangOpts.OpenMP >= 50 ? 1 : 0)
20727 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
20728 continue;
20729 }
20730 }
20731 }
20732 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20733 }
20734
20735 if (!CurContext->isDependentContext() && DepKind == OMPC_DEPEND_sink &&
20736 TotalDepCount > VarList.size() &&
20737 DSAStack->getParentOrderedRegionParam().first &&
20738 DSAStack->getParentLoopControlVariable(VarList.size() + 1)) {
20739 Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
20740 << 1 << DSAStack->getParentLoopControlVariable(VarList.size() + 1);
20741 }
20742 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
20743 DepKind != OMPC_DEPEND_outallmemory &&
20744 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
20745 return nullptr;
20746
20747 auto *C = OMPDependClause::Create(
20748 Context, StartLoc, LParenLoc, EndLoc,
20749 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
20750 TotalDepCount.getZExtValue());
20751 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
20752 DSAStack->isParentOrderedRegion())
20753 DSAStack->addDoacrossDependClause(C, OpsOffs);
20754 return C;
20755 }
20756
ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier,Expr * Device,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ModifierLoc,SourceLocation EndLoc)20757 OMPClause *Sema::ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier,
20758 Expr *Device, SourceLocation StartLoc,
20759 SourceLocation LParenLoc,
20760 SourceLocation ModifierLoc,
20761 SourceLocation EndLoc) {
20762 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 50) &&
20763 "Unexpected device modifier in OpenMP < 50.");
20764
20765 bool ErrorFound = false;
20766 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
20767 std::string Values =
20768 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
20769 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
20770 << Values << getOpenMPClauseName(OMPC_device);
20771 ErrorFound = true;
20772 }
20773
20774 Expr *ValExpr = Device;
20775 Stmt *HelperValStmt = nullptr;
20776
20777 // OpenMP [2.9.1, Restrictions]
20778 // The device expression must evaluate to a non-negative integer value.
20779 ErrorFound = !isNonNegativeIntegerValue(ValExpr, *this, OMPC_device,
20780 /*StrictlyPositive=*/false) ||
20781 ErrorFound;
20782 if (ErrorFound)
20783 return nullptr;
20784
20785 // OpenMP 5.0 [2.12.5, Restrictions]
20786 // In case of ancestor device-modifier, a requires directive with
20787 // the reverse_offload clause must be specified.
20788 if (Modifier == OMPC_DEVICE_ancestor) {
20789 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
20790 targetDiag(
20791 StartLoc,
20792 diag::err_omp_device_ancestor_without_requires_reverse_offload);
20793 ErrorFound = true;
20794 }
20795 }
20796
20797 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
20798 OpenMPDirectiveKind CaptureRegion =
20799 getOpenMPCaptureRegionForClause(DKind, OMPC_device, LangOpts.OpenMP);
20800 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
20801 ValExpr = MakeFullExpr(ValExpr).get();
20802 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20803 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
20804 HelperValStmt = buildPreInits(Context, Captures);
20805 }
20806
20807 return new (Context)
20808 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
20809 LParenLoc, ModifierLoc, EndLoc);
20810 }
20811
checkTypeMappable(SourceLocation SL,SourceRange SR,Sema & SemaRef,DSAStackTy * Stack,QualType QTy,bool FullCheck=true)20812 static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
20813 DSAStackTy *Stack, QualType QTy,
20814 bool FullCheck = true) {
20815 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
20816 return false;
20817 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
20818 !QTy.isTriviallyCopyableType(SemaRef.Context))
20819 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
20820 return true;
20821 }
20822
20823 /// Return true if it can be proven that the provided array expression
20824 /// (array section or array subscript) does NOT specify the whole size of the
20825 /// array whose base type is \a BaseQTy.
checkArrayExpressionDoesNotReferToWholeSize(Sema & SemaRef,const Expr * E,QualType BaseQTy)20826 static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
20827 const Expr *E,
20828 QualType BaseQTy) {
20829 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
20830
20831 // If this is an array subscript, it refers to the whole size if the size of
20832 // the dimension is constant and equals 1. Also, an array section assumes the
20833 // format of an array subscript if no colon is used.
20834 if (isa<ArraySubscriptExpr>(E) ||
20835 (OASE && OASE->getColonLocFirst().isInvalid())) {
20836 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20837 return ATy->getSize().getSExtValue() != 1;
20838 // Size can't be evaluated statically.
20839 return false;
20840 }
20841
20842 assert(OASE && "Expecting array section if not an array subscript.");
20843 const Expr *LowerBound = OASE->getLowerBound();
20844 const Expr *Length = OASE->getLength();
20845
20846 // If there is a lower bound that does not evaluates to zero, we are not
20847 // covering the whole dimension.
20848 if (LowerBound) {
20849 Expr::EvalResult Result;
20850 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
20851 return false; // Can't get the integer value as a constant.
20852
20853 llvm::APSInt ConstLowerBound = Result.Val.getInt();
20854 if (ConstLowerBound.getSExtValue())
20855 return true;
20856 }
20857
20858 // If we don't have a length we covering the whole dimension.
20859 if (!Length)
20860 return false;
20861
20862 // If the base is a pointer, we don't have a way to get the size of the
20863 // pointee.
20864 if (BaseQTy->isPointerType())
20865 return false;
20866
20867 // We can only check if the length is the same as the size of the dimension
20868 // if we have a constant array.
20869 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
20870 if (!CATy)
20871 return false;
20872
20873 Expr::EvalResult Result;
20874 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20875 return false; // Can't get the integer value as a constant.
20876
20877 llvm::APSInt ConstLength = Result.Val.getInt();
20878 return CATy->getSize().getSExtValue() != ConstLength.getSExtValue();
20879 }
20880
20881 // Return true if it can be proven that the provided array expression (array
20882 // section or array subscript) does NOT specify a single element of the array
20883 // whose base type is \a BaseQTy.
checkArrayExpressionDoesNotReferToUnitySize(Sema & SemaRef,const Expr * E,QualType BaseQTy)20884 static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
20885 const Expr *E,
20886 QualType BaseQTy) {
20887 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
20888
20889 // An array subscript always refer to a single element. Also, an array section
20890 // assumes the format of an array subscript if no colon is used.
20891 if (isa<ArraySubscriptExpr>(E) ||
20892 (OASE && OASE->getColonLocFirst().isInvalid()))
20893 return false;
20894
20895 assert(OASE && "Expecting array section if not an array subscript.");
20896 const Expr *Length = OASE->getLength();
20897
20898 // If we don't have a length we have to check if the array has unitary size
20899 // for this dimension. Also, we should always expect a length if the base type
20900 // is pointer.
20901 if (!Length) {
20902 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20903 return ATy->getSize().getSExtValue() != 1;
20904 // We cannot assume anything.
20905 return false;
20906 }
20907
20908 // Check if the length evaluates to 1.
20909 Expr::EvalResult Result;
20910 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20911 return false; // Can't get the integer value as a constant.
20912
20913 llvm::APSInt ConstLength = Result.Val.getInt();
20914 return ConstLength.getSExtValue() != 1;
20915 }
20916
20917 // The base of elements of list in a map clause have to be either:
20918 // - a reference to variable or field.
20919 // - a member expression.
20920 // - an array expression.
20921 //
20922 // E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
20923 // reference to 'r'.
20924 //
20925 // If we have:
20926 //
20927 // struct SS {
20928 // Bla S;
20929 // foo() {
20930 // #pragma omp target map (S.Arr[:12]);
20931 // }
20932 // }
20933 //
20934 // We want to retrieve the member expression 'this->S';
20935
20936 // OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
20937 // If a list item is an array section, it must specify contiguous storage.
20938 //
20939 // For this restriction it is sufficient that we make sure only references
20940 // to variables or fields and array expressions, and that no array sections
20941 // exist except in the rightmost expression (unless they cover the whole
20942 // dimension of the array). E.g. these would be invalid:
20943 //
20944 // r.ArrS[3:5].Arr[6:7]
20945 //
20946 // r.ArrS[3:5].x
20947 //
20948 // but these would be valid:
20949 // r.ArrS[3].Arr[6:7]
20950 //
20951 // r.ArrS[3].x
20952 namespace {
20953 class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
20954 Sema &SemaRef;
20955 OpenMPClauseKind CKind = OMPC_unknown;
20956 OpenMPDirectiveKind DKind = OMPD_unknown;
20957 OMPClauseMappableExprCommon::MappableExprComponentList &Components;
20958 bool IsNonContiguous = false;
20959 bool NoDiagnose = false;
20960 const Expr *RelevantExpr = nullptr;
20961 bool AllowUnitySizeArraySection = true;
20962 bool AllowWholeSizeArraySection = true;
20963 bool AllowAnotherPtr = true;
20964 SourceLocation ELoc;
20965 SourceRange ERange;
20966
emitErrorMsg()20967 void emitErrorMsg() {
20968 // If nothing else worked, this is not a valid map clause expression.
20969 if (SemaRef.getLangOpts().OpenMP < 50) {
20970 SemaRef.Diag(ELoc,
20971 diag::err_omp_expected_named_var_member_or_array_expression)
20972 << ERange;
20973 } else {
20974 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20975 << getOpenMPClauseName(CKind) << ERange;
20976 }
20977 }
20978
20979 public:
VisitDeclRefExpr(DeclRefExpr * DRE)20980 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
20981 if (!isa<VarDecl>(DRE->getDecl())) {
20982 emitErrorMsg();
20983 return false;
20984 }
20985 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20986 RelevantExpr = DRE;
20987 // Record the component.
20988 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
20989 return true;
20990 }
20991
VisitMemberExpr(MemberExpr * ME)20992 bool VisitMemberExpr(MemberExpr *ME) {
20993 Expr *E = ME;
20994 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
20995
20996 if (isa<CXXThisExpr>(BaseE)) {
20997 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20998 // We found a base expression: this->Val.
20999 RelevantExpr = ME;
21000 } else {
21001 E = BaseE;
21002 }
21003
21004 if (!isa<FieldDecl>(ME->getMemberDecl())) {
21005 if (!NoDiagnose) {
21006 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
21007 << ME->getSourceRange();
21008 return false;
21009 }
21010 if (RelevantExpr)
21011 return false;
21012 return Visit(E);
21013 }
21014
21015 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
21016
21017 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
21018 // A bit-field cannot appear in a map clause.
21019 //
21020 if (FD->isBitField()) {
21021 if (!NoDiagnose) {
21022 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
21023 << ME->getSourceRange() << getOpenMPClauseName(CKind);
21024 return false;
21025 }
21026 if (RelevantExpr)
21027 return false;
21028 return Visit(E);
21029 }
21030
21031 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21032 // If the type of a list item is a reference to a type T then the type
21033 // will be considered to be T for all purposes of this clause.
21034 QualType CurType = BaseE->getType().getNonReferenceType();
21035
21036 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
21037 // A list item cannot be a variable that is a member of a structure with
21038 // a union type.
21039 //
21040 if (CurType->isUnionType()) {
21041 if (!NoDiagnose) {
21042 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
21043 << ME->getSourceRange();
21044 return false;
21045 }
21046 return RelevantExpr || Visit(E);
21047 }
21048
21049 // If we got a member expression, we should not expect any array section
21050 // before that:
21051 //
21052 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
21053 // If a list item is an element of a structure, only the rightmost symbol
21054 // of the variable reference can be an array section.
21055 //
21056 AllowUnitySizeArraySection = false;
21057 AllowWholeSizeArraySection = false;
21058
21059 // Record the component.
21060 Components.emplace_back(ME, FD, IsNonContiguous);
21061 return RelevantExpr || Visit(E);
21062 }
21063
VisitArraySubscriptExpr(ArraySubscriptExpr * AE)21064 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
21065 Expr *E = AE->getBase()->IgnoreParenImpCasts();
21066
21067 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
21068 if (!NoDiagnose) {
21069 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21070 << 0 << AE->getSourceRange();
21071 return false;
21072 }
21073 return RelevantExpr || Visit(E);
21074 }
21075
21076 // If we got an array subscript that express the whole dimension we
21077 // can have any array expressions before. If it only expressing part of
21078 // the dimension, we can only have unitary-size array expressions.
21079 if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef, AE, E->getType()))
21080 AllowWholeSizeArraySection = false;
21081
21082 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
21083 Expr::EvalResult Result;
21084 if (!AE->getIdx()->isValueDependent() &&
21085 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
21086 !Result.Val.getInt().isZero()) {
21087 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21088 diag::err_omp_invalid_map_this_expr);
21089 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21090 diag::note_omp_invalid_subscript_on_this_ptr_map);
21091 }
21092 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21093 RelevantExpr = TE;
21094 }
21095
21096 // Record the component - we don't have any declaration associated.
21097 Components.emplace_back(AE, nullptr, IsNonContiguous);
21098
21099 return RelevantExpr || Visit(E);
21100 }
21101
VisitOMPArraySectionExpr(OMPArraySectionExpr * OASE)21102 bool VisitOMPArraySectionExpr(OMPArraySectionExpr *OASE) {
21103 // After OMP 5.0 Array section in reduction clause will be implicitly
21104 // mapped
21105 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
21106 "Array sections cannot be implicitly mapped.");
21107 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21108 QualType CurType =
21109 OMPArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
21110
21111 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21112 // If the type of a list item is a reference to a type T then the type
21113 // will be considered to be T for all purposes of this clause.
21114 if (CurType->isReferenceType())
21115 CurType = CurType->getPointeeType();
21116
21117 bool IsPointer = CurType->isAnyPointerType();
21118
21119 if (!IsPointer && !CurType->isArrayType()) {
21120 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21121 << 0 << OASE->getSourceRange();
21122 return false;
21123 }
21124
21125 bool NotWhole =
21126 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
21127 bool NotUnity =
21128 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
21129
21130 if (AllowWholeSizeArraySection) {
21131 // Any array section is currently allowed. Allowing a whole size array
21132 // section implies allowing a unity array section as well.
21133 //
21134 // If this array section refers to the whole dimension we can still
21135 // accept other array sections before this one, except if the base is a
21136 // pointer. Otherwise, only unitary sections are accepted.
21137 if (NotWhole || IsPointer)
21138 AllowWholeSizeArraySection = false;
21139 } else if (DKind == OMPD_target_update &&
21140 SemaRef.getLangOpts().OpenMP >= 50) {
21141 if (IsPointer && !AllowAnotherPtr)
21142 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
21143 << /*array of unknown bound */ 1;
21144 else
21145 IsNonContiguous = true;
21146 } else if (AllowUnitySizeArraySection && NotUnity) {
21147 // A unity or whole array section is not allowed and that is not
21148 // compatible with the properties of the current array section.
21149 if (NoDiagnose)
21150 return false;
21151 SemaRef.Diag(ELoc,
21152 diag::err_array_section_does_not_specify_contiguous_storage)
21153 << OASE->getSourceRange();
21154 return false;
21155 }
21156
21157 if (IsPointer)
21158 AllowAnotherPtr = false;
21159
21160 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
21161 Expr::EvalResult ResultR;
21162 Expr::EvalResult ResultL;
21163 if (!OASE->getLength()->isValueDependent() &&
21164 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
21165 !ResultR.Val.getInt().isOne()) {
21166 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21167 diag::err_omp_invalid_map_this_expr);
21168 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21169 diag::note_omp_invalid_length_on_this_ptr_mapping);
21170 }
21171 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
21172 OASE->getLowerBound()->EvaluateAsInt(ResultL,
21173 SemaRef.getASTContext()) &&
21174 !ResultL.Val.getInt().isZero()) {
21175 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21176 diag::err_omp_invalid_map_this_expr);
21177 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21178 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
21179 }
21180 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21181 RelevantExpr = TE;
21182 }
21183
21184 // Record the component - we don't have any declaration associated.
21185 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
21186 return RelevantExpr || Visit(E);
21187 }
VisitOMPArrayShapingExpr(OMPArrayShapingExpr * E)21188 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
21189 Expr *Base = E->getBase();
21190
21191 // Record the component - we don't have any declaration associated.
21192 Components.emplace_back(E, nullptr, IsNonContiguous);
21193
21194 return Visit(Base->IgnoreParenImpCasts());
21195 }
21196
VisitUnaryOperator(UnaryOperator * UO)21197 bool VisitUnaryOperator(UnaryOperator *UO) {
21198 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
21199 UO->getOpcode() != UO_Deref) {
21200 emitErrorMsg();
21201 return false;
21202 }
21203 if (!RelevantExpr) {
21204 // Record the component if haven't found base decl.
21205 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
21206 }
21207 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
21208 }
VisitBinaryOperator(BinaryOperator * BO)21209 bool VisitBinaryOperator(BinaryOperator *BO) {
21210 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
21211 emitErrorMsg();
21212 return false;
21213 }
21214
21215 // Pointer arithmetic is the only thing we expect to happen here so after we
21216 // make sure the binary operator is a pointer type, the only thing we need
21217 // to do is to visit the subtree that has the same type as root (so that we
21218 // know the other subtree is just an offset)
21219 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
21220 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
21221 Components.emplace_back(BO, nullptr, false);
21222 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
21223 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
21224 "Either LHS or RHS have base decl inside");
21225 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
21226 return RelevantExpr || Visit(LE);
21227 return RelevantExpr || Visit(RE);
21228 }
VisitCXXThisExpr(CXXThisExpr * CTE)21229 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
21230 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21231 RelevantExpr = CTE;
21232 Components.emplace_back(CTE, nullptr, IsNonContiguous);
21233 return true;
21234 }
VisitCXXOperatorCallExpr(CXXOperatorCallExpr * COCE)21235 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
21236 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21237 Components.emplace_back(COCE, nullptr, IsNonContiguous);
21238 return true;
21239 }
VisitOpaqueValueExpr(OpaqueValueExpr * E)21240 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
21241 Expr *Source = E->getSourceExpr();
21242 if (!Source) {
21243 emitErrorMsg();
21244 return false;
21245 }
21246 return Visit(Source);
21247 }
VisitStmt(Stmt *)21248 bool VisitStmt(Stmt *) {
21249 emitErrorMsg();
21250 return false;
21251 }
getFoundBase() const21252 const Expr *getFoundBase() const { return RelevantExpr; }
MapBaseChecker(Sema & SemaRef,OpenMPClauseKind CKind,OpenMPDirectiveKind DKind,OMPClauseMappableExprCommon::MappableExprComponentList & Components,bool NoDiagnose,SourceLocation & ELoc,SourceRange & ERange)21253 explicit MapBaseChecker(
21254 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
21255 OMPClauseMappableExprCommon::MappableExprComponentList &Components,
21256 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
21257 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
21258 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
21259 };
21260 } // namespace
21261
21262 /// Return the expression of the base of the mappable expression or null if it
21263 /// cannot be determined and do all the necessary checks to see if the
21264 /// expression is valid as a standalone mappable expression. In the process,
21265 /// record all the components of the expression.
checkMapClauseExpressionBase(Sema & SemaRef,Expr * E,OMPClauseMappableExprCommon::MappableExprComponentList & CurComponents,OpenMPClauseKind CKind,OpenMPDirectiveKind DKind,bool NoDiagnose)21266 static const Expr *checkMapClauseExpressionBase(
21267 Sema &SemaRef, Expr *E,
21268 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
21269 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
21270 SourceLocation ELoc = E->getExprLoc();
21271 SourceRange ERange = E->getSourceRange();
21272 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
21273 ERange);
21274 if (Checker.Visit(E->IgnoreParens())) {
21275 // Check if the highest dimension array section has length specified
21276 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
21277 (CKind == OMPC_to || CKind == OMPC_from)) {
21278 auto CI = CurComponents.rbegin();
21279 auto CE = CurComponents.rend();
21280 for (; CI != CE; ++CI) {
21281 const auto *OASE =
21282 dyn_cast<OMPArraySectionExpr>(CI->getAssociatedExpression());
21283 if (!OASE)
21284 continue;
21285 if (OASE && OASE->getLength())
21286 break;
21287 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
21288 << ERange;
21289 }
21290 }
21291 return Checker.getFoundBase();
21292 }
21293 return nullptr;
21294 }
21295
21296 // Return true if expression E associated with value VD has conflicts with other
21297 // map information.
checkMapConflicts(Sema & SemaRef,DSAStackTy * DSAS,const ValueDecl * VD,const Expr * E,bool CurrentRegionOnly,OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents,OpenMPClauseKind CKind)21298 static bool checkMapConflicts(
21299 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
21300 bool CurrentRegionOnly,
21301 OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents,
21302 OpenMPClauseKind CKind) {
21303 assert(VD && E);
21304 SourceLocation ELoc = E->getExprLoc();
21305 SourceRange ERange = E->getSourceRange();
21306
21307 // In order to easily check the conflicts we need to match each component of
21308 // the expression under test with the components of the expressions that are
21309 // already in the stack.
21310
21311 assert(!CurComponents.empty() && "Map clause expression with no components!");
21312 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
21313 "Map clause expression with unexpected base!");
21314
21315 // Variables to help detecting enclosing problems in data environment nests.
21316 bool IsEnclosedByDataEnvironmentExpr = false;
21317 const Expr *EnclosingExpr = nullptr;
21318
21319 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
21320 VD, CurrentRegionOnly,
21321 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
21322 ERange, CKind, &EnclosingExpr,
21323 CurComponents](OMPClauseMappableExprCommon::MappableExprComponentListRef
21324 StackComponents,
21325 OpenMPClauseKind Kind) {
21326 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
21327 return false;
21328 assert(!StackComponents.empty() &&
21329 "Map clause expression with no components!");
21330 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
21331 "Map clause expression with unexpected base!");
21332 (void)VD;
21333
21334 // The whole expression in the stack.
21335 const Expr *RE = StackComponents.front().getAssociatedExpression();
21336
21337 // Expressions must start from the same base. Here we detect at which
21338 // point both expressions diverge from each other and see if we can
21339 // detect if the memory referred to both expressions is contiguous and
21340 // do not overlap.
21341 auto CI = CurComponents.rbegin();
21342 auto CE = CurComponents.rend();
21343 auto SI = StackComponents.rbegin();
21344 auto SE = StackComponents.rend();
21345 for (; CI != CE && SI != SE; ++CI, ++SI) {
21346
21347 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
21348 // At most one list item can be an array item derived from a given
21349 // variable in map clauses of the same construct.
21350 if (CurrentRegionOnly &&
21351 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
21352 isa<OMPArraySectionExpr>(CI->getAssociatedExpression()) ||
21353 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
21354 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
21355 isa<OMPArraySectionExpr>(SI->getAssociatedExpression()) ||
21356 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
21357 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
21358 diag::err_omp_multiple_array_items_in_map_clause)
21359 << CI->getAssociatedExpression()->getSourceRange();
21360 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
21361 diag::note_used_here)
21362 << SI->getAssociatedExpression()->getSourceRange();
21363 return true;
21364 }
21365
21366 // Do both expressions have the same kind?
21367 if (CI->getAssociatedExpression()->getStmtClass() !=
21368 SI->getAssociatedExpression()->getStmtClass())
21369 break;
21370
21371 // Are we dealing with different variables/fields?
21372 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
21373 break;
21374 }
21375 // Check if the extra components of the expressions in the enclosing
21376 // data environment are redundant for the current base declaration.
21377 // If they are, the maps completely overlap, which is legal.
21378 for (; SI != SE; ++SI) {
21379 QualType Type;
21380 if (const auto *ASE =
21381 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
21382 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
21383 } else if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(
21384 SI->getAssociatedExpression())) {
21385 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21386 Type =
21387 OMPArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
21388 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
21389 SI->getAssociatedExpression())) {
21390 Type = OASE->getBase()->getType()->getPointeeType();
21391 }
21392 if (Type.isNull() || Type->isAnyPointerType() ||
21393 checkArrayExpressionDoesNotReferToWholeSize(
21394 SemaRef, SI->getAssociatedExpression(), Type))
21395 break;
21396 }
21397
21398 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21399 // List items of map clauses in the same construct must not share
21400 // original storage.
21401 //
21402 // If the expressions are exactly the same or one is a subset of the
21403 // other, it means they are sharing storage.
21404 if (CI == CE && SI == SE) {
21405 if (CurrentRegionOnly) {
21406 if (CKind == OMPC_map) {
21407 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21408 } else {
21409 assert(CKind == OMPC_to || CKind == OMPC_from);
21410 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21411 << ERange;
21412 }
21413 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21414 << RE->getSourceRange();
21415 return true;
21416 }
21417 // If we find the same expression in the enclosing data environment,
21418 // that is legal.
21419 IsEnclosedByDataEnvironmentExpr = true;
21420 return false;
21421 }
21422
21423 QualType DerivedType =
21424 std::prev(CI)->getAssociatedDeclaration()->getType();
21425 SourceLocation DerivedLoc =
21426 std::prev(CI)->getAssociatedExpression()->getExprLoc();
21427
21428 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21429 // If the type of a list item is a reference to a type T then the type
21430 // will be considered to be T for all purposes of this clause.
21431 DerivedType = DerivedType.getNonReferenceType();
21432
21433 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
21434 // A variable for which the type is pointer and an array section
21435 // derived from that variable must not appear as list items of map
21436 // clauses of the same construct.
21437 //
21438 // Also, cover one of the cases in:
21439 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21440 // If any part of the original storage of a list item has corresponding
21441 // storage in the device data environment, all of the original storage
21442 // must have corresponding storage in the device data environment.
21443 //
21444 if (DerivedType->isAnyPointerType()) {
21445 if (CI == CE || SI == SE) {
21446 SemaRef.Diag(
21447 DerivedLoc,
21448 diag::err_omp_pointer_mapped_along_with_derived_section)
21449 << DerivedLoc;
21450 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21451 << RE->getSourceRange();
21452 return true;
21453 }
21454 if (CI->getAssociatedExpression()->getStmtClass() !=
21455 SI->getAssociatedExpression()->getStmtClass() ||
21456 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
21457 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
21458 assert(CI != CE && SI != SE);
21459 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
21460 << DerivedLoc;
21461 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21462 << RE->getSourceRange();
21463 return true;
21464 }
21465 }
21466
21467 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21468 // List items of map clauses in the same construct must not share
21469 // original storage.
21470 //
21471 // An expression is a subset of the other.
21472 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
21473 if (CKind == OMPC_map) {
21474 if (CI != CE || SI != SE) {
21475 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
21476 // a pointer.
21477 auto Begin =
21478 CI != CE ? CurComponents.begin() : StackComponents.begin();
21479 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
21480 auto It = Begin;
21481 while (It != End && !It->getAssociatedDeclaration())
21482 std::advance(It, 1);
21483 assert(It != End &&
21484 "Expected at least one component with the declaration.");
21485 if (It != Begin && It->getAssociatedDeclaration()
21486 ->getType()
21487 .getCanonicalType()
21488 ->isAnyPointerType()) {
21489 IsEnclosedByDataEnvironmentExpr = false;
21490 EnclosingExpr = nullptr;
21491 return false;
21492 }
21493 }
21494 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21495 } else {
21496 assert(CKind == OMPC_to || CKind == OMPC_from);
21497 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21498 << ERange;
21499 }
21500 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21501 << RE->getSourceRange();
21502 return true;
21503 }
21504
21505 // The current expression uses the same base as other expression in the
21506 // data environment but does not contain it completely.
21507 if (!CurrentRegionOnly && SI != SE)
21508 EnclosingExpr = RE;
21509
21510 // The current expression is a subset of the expression in the data
21511 // environment.
21512 IsEnclosedByDataEnvironmentExpr |=
21513 (!CurrentRegionOnly && CI != CE && SI == SE);
21514
21515 return false;
21516 });
21517
21518 if (CurrentRegionOnly)
21519 return FoundError;
21520
21521 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21522 // If any part of the original storage of a list item has corresponding
21523 // storage in the device data environment, all of the original storage must
21524 // have corresponding storage in the device data environment.
21525 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
21526 // If a list item is an element of a structure, and a different element of
21527 // the structure has a corresponding list item in the device data environment
21528 // prior to a task encountering the construct associated with the map clause,
21529 // then the list item must also have a corresponding list item in the device
21530 // data environment prior to the task encountering the construct.
21531 //
21532 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
21533 SemaRef.Diag(ELoc,
21534 diag::err_omp_original_storage_is_shared_and_does_not_contain)
21535 << ERange;
21536 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
21537 << EnclosingExpr->getSourceRange();
21538 return true;
21539 }
21540
21541 return FoundError;
21542 }
21543
21544 // Look up the user-defined mapper given the mapper name and mapped type, and
21545 // build a reference to it.
buildUserDefinedMapperRef(Sema & SemaRef,Scope * S,CXXScopeSpec & MapperIdScopeSpec,const DeclarationNameInfo & MapperId,QualType Type,Expr * UnresolvedMapper)21546 static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
21547 CXXScopeSpec &MapperIdScopeSpec,
21548 const DeclarationNameInfo &MapperId,
21549 QualType Type,
21550 Expr *UnresolvedMapper) {
21551 if (MapperIdScopeSpec.isInvalid())
21552 return ExprError();
21553 // Get the actual type for the array type.
21554 if (Type->isArrayType()) {
21555 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
21556 Type = Type->getAsArrayTypeUnsafe()->getElementType().getCanonicalType();
21557 }
21558 // Find all user-defined mappers with the given MapperId.
21559 SmallVector<UnresolvedSet<8>, 4> Lookups;
21560 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
21561 Lookup.suppressDiagnostics();
21562 if (S) {
21563 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec)) {
21564 NamedDecl *D = Lookup.getRepresentativeDecl();
21565 while (S && !S->isDeclScope(D))
21566 S = S->getParent();
21567 if (S)
21568 S = S->getParent();
21569 Lookups.emplace_back();
21570 Lookups.back().append(Lookup.begin(), Lookup.end());
21571 Lookup.clear();
21572 }
21573 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
21574 // Extract the user-defined mappers with the given MapperId.
21575 Lookups.push_back(UnresolvedSet<8>());
21576 for (NamedDecl *D : ULE->decls()) {
21577 auto *DMD = cast<OMPDeclareMapperDecl>(D);
21578 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
21579 Lookups.back().addDecl(DMD);
21580 }
21581 }
21582 // Defer the lookup for dependent types. The results will be passed through
21583 // UnresolvedMapper on instantiation.
21584 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21585 Type->isInstantiationDependentType() ||
21586 Type->containsUnexpandedParameterPack() ||
21587 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
21588 return !D->isInvalidDecl() &&
21589 (D->getType()->isDependentType() ||
21590 D->getType()->isInstantiationDependentType() ||
21591 D->getType()->containsUnexpandedParameterPack());
21592 })) {
21593 UnresolvedSet<8> URS;
21594 for (const UnresolvedSet<8> &Set : Lookups) {
21595 if (Set.empty())
21596 continue;
21597 URS.append(Set.begin(), Set.end());
21598 }
21599 return UnresolvedLookupExpr::Create(
21600 SemaRef.Context, /*NamingClass=*/nullptr,
21601 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
21602 /*ADL=*/false, /*Overloaded=*/true, URS.begin(), URS.end());
21603 }
21604 SourceLocation Loc = MapperId.getLoc();
21605 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21606 // The type must be of struct, union or class type in C and C++
21607 if (!Type->isStructureOrClassType() && !Type->isUnionType() &&
21608 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
21609 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
21610 return ExprError();
21611 }
21612 // Perform argument dependent lookup.
21613 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21614 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
21615 // Return the first user-defined mapper with the desired type.
21616 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21617 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21618 if (!D->isInvalidDecl() &&
21619 SemaRef.Context.hasSameType(D->getType(), Type))
21620 return D;
21621 return nullptr;
21622 }))
21623 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21624 // Find the first user-defined mapper with a type derived from the desired
21625 // type.
21626 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21627 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21628 if (!D->isInvalidDecl() &&
21629 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
21630 !Type.isMoreQualifiedThan(D->getType()))
21631 return D;
21632 return nullptr;
21633 })) {
21634 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21635 /*DetectVirtual=*/false);
21636 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
21637 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
21638 VD->getType().getUnqualifiedType()))) {
21639 if (SemaRef.CheckBaseClassAccess(
21640 Loc, VD->getType(), Type, Paths.front(),
21641 /*DiagID=*/0) != Sema::AR_inaccessible) {
21642 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21643 }
21644 }
21645 }
21646 }
21647 // Report error if a mapper is specified, but cannot be found.
21648 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
21649 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
21650 << Type << MapperId.getName();
21651 return ExprError();
21652 }
21653 return ExprEmpty();
21654 }
21655
21656 namespace {
21657 // Utility struct that gathers all the related lists associated with a mappable
21658 // expression.
21659 struct MappableVarListInfo {
21660 // The list of expressions.
21661 ArrayRef<Expr *> VarList;
21662 // The list of processed expressions.
21663 SmallVector<Expr *, 16> ProcessedVarList;
21664 // The mappble components for each expression.
21665 OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents;
21666 // The base declaration of the variable.
21667 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
21668 // The reference to the user-defined mapper associated with every expression.
21669 SmallVector<Expr *, 16> UDMapperList;
21670
MappableVarListInfo__anon7e4ded5b6411::MappableVarListInfo21671 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
21672 // We have a list of components and base declarations for each entry in the
21673 // variable list.
21674 VarComponents.reserve(VarList.size());
21675 VarBaseDeclarations.reserve(VarList.size());
21676 }
21677 };
21678 } // namespace
21679
21680 // Check the validity of the provided variable list for the provided clause kind
21681 // \a CKind. In the check process the valid expressions, mappable expression
21682 // components, variables, and user-defined mappers are extracted and used to
21683 // fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
21684 // UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
21685 // 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)21686 static void checkMappableExpressionList(
21687 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
21688 MappableVarListInfo &MVLI, SourceLocation StartLoc,
21689 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
21690 ArrayRef<Expr *> UnresolvedMappers,
21691 OpenMPMapClauseKind MapType = OMPC_MAP_unknown,
21692 ArrayRef<OpenMPMapModifierKind> Modifiers = std::nullopt,
21693 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
21694 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
21695 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
21696 "Unexpected clause kind with mappable expressions!");
21697
21698 // If the identifier of user-defined mapper is not specified, it is "default".
21699 // We do not change the actual name in this clause to distinguish whether a
21700 // mapper is specified explicitly, i.e., it is not explicitly specified when
21701 // MapperId.getName() is empty.
21702 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
21703 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
21704 MapperId.setName(DeclNames.getIdentifier(
21705 &SemaRef.getASTContext().Idents.get("default")));
21706 MapperId.setLoc(StartLoc);
21707 }
21708
21709 // Iterators to find the current unresolved mapper expression.
21710 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
21711 bool UpdateUMIt = false;
21712 Expr *UnresolvedMapper = nullptr;
21713
21714 bool HasHoldModifier =
21715 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
21716
21717 // Keep track of the mappable components and base declarations in this clause.
21718 // Each entry in the list is going to have a list of components associated. We
21719 // record each set of the components so that we can build the clause later on.
21720 // In the end we should have the same amount of declarations and component
21721 // lists.
21722
21723 for (Expr *RE : MVLI.VarList) {
21724 assert(RE && "Null expr in omp to/from/map clause");
21725 SourceLocation ELoc = RE->getExprLoc();
21726
21727 // Find the current unresolved mapper expression.
21728 if (UpdateUMIt && UMIt != UMEnd) {
21729 UMIt++;
21730 assert(
21731 UMIt != UMEnd &&
21732 "Expect the size of UnresolvedMappers to match with that of VarList");
21733 }
21734 UpdateUMIt = true;
21735 if (UMIt != UMEnd)
21736 UnresolvedMapper = *UMIt;
21737
21738 const Expr *VE = RE->IgnoreParenLValueCasts();
21739
21740 if (VE->isValueDependent() || VE->isTypeDependent() ||
21741 VE->isInstantiationDependent() ||
21742 VE->containsUnexpandedParameterPack()) {
21743 // Try to find the associated user-defined mapper.
21744 ExprResult ER = buildUserDefinedMapperRef(
21745 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21746 VE->getType().getCanonicalType(), UnresolvedMapper);
21747 if (ER.isInvalid())
21748 continue;
21749 MVLI.UDMapperList.push_back(ER.get());
21750 // We can only analyze this information once the missing information is
21751 // resolved.
21752 MVLI.ProcessedVarList.push_back(RE);
21753 continue;
21754 }
21755
21756 Expr *SimpleExpr = RE->IgnoreParenCasts();
21757
21758 if (!RE->isLValue()) {
21759 if (SemaRef.getLangOpts().OpenMP < 50) {
21760 SemaRef.Diag(
21761 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
21762 << RE->getSourceRange();
21763 } else {
21764 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21765 << getOpenMPClauseName(CKind) << RE->getSourceRange();
21766 }
21767 continue;
21768 }
21769
21770 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
21771 ValueDecl *CurDeclaration = nullptr;
21772
21773 // Obtain the array or member expression bases if required. Also, fill the
21774 // components array with all the components identified in the process.
21775 const Expr *BE =
21776 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
21777 DSAS->getCurrentDirective(), NoDiagnose);
21778 if (!BE)
21779 continue;
21780
21781 assert(!CurComponents.empty() &&
21782 "Invalid mappable expression information.");
21783
21784 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
21785 // Add store "this" pointer to class in DSAStackTy for future checking
21786 DSAS->addMappedClassesQualTypes(TE->getType());
21787 // Try to find the associated user-defined mapper.
21788 ExprResult ER = buildUserDefinedMapperRef(
21789 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21790 VE->getType().getCanonicalType(), UnresolvedMapper);
21791 if (ER.isInvalid())
21792 continue;
21793 MVLI.UDMapperList.push_back(ER.get());
21794 // Skip restriction checking for variable or field declarations
21795 MVLI.ProcessedVarList.push_back(RE);
21796 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21797 MVLI.VarComponents.back().append(CurComponents.begin(),
21798 CurComponents.end());
21799 MVLI.VarBaseDeclarations.push_back(nullptr);
21800 continue;
21801 }
21802
21803 // For the following checks, we rely on the base declaration which is
21804 // expected to be associated with the last component. The declaration is
21805 // expected to be a variable or a field (if 'this' is being mapped).
21806 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
21807 assert(CurDeclaration && "Null decl on map clause.");
21808 assert(
21809 CurDeclaration->isCanonicalDecl() &&
21810 "Expecting components to have associated only canonical declarations.");
21811
21812 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
21813 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
21814
21815 assert((VD || FD) && "Only variables or fields are expected here!");
21816 (void)FD;
21817
21818 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
21819 // threadprivate variables cannot appear in a map clause.
21820 // OpenMP 4.5 [2.10.5, target update Construct]
21821 // threadprivate variables cannot appear in a from clause.
21822 if (VD && DSAS->isThreadPrivate(VD)) {
21823 if (NoDiagnose)
21824 continue;
21825 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21826 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
21827 << getOpenMPClauseName(CKind);
21828 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
21829 continue;
21830 }
21831
21832 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21833 // A list item cannot appear in both a map clause and a data-sharing
21834 // attribute clause on the same construct.
21835
21836 // Check conflicts with other map clause expressions. We check the conflicts
21837 // with the current construct separately from the enclosing data
21838 // environment, because the restrictions are different. We only have to
21839 // check conflicts across regions for the map clauses.
21840 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21841 /*CurrentRegionOnly=*/true, CurComponents, CKind))
21842 break;
21843 if (CKind == OMPC_map &&
21844 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
21845 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21846 /*CurrentRegionOnly=*/false, CurComponents, CKind))
21847 break;
21848
21849 // OpenMP 4.5 [2.10.5, target update Construct]
21850 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21851 // If the type of a list item is a reference to a type T then the type will
21852 // be considered to be T for all purposes of this clause.
21853 auto I = llvm::find_if(
21854 CurComponents,
21855 [](const OMPClauseMappableExprCommon::MappableComponent &MC) {
21856 return MC.getAssociatedDeclaration();
21857 });
21858 assert(I != CurComponents.end() && "Null decl on map clause.");
21859 (void)I;
21860 QualType Type;
21861 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
21862 auto *OASE = dyn_cast<OMPArraySectionExpr>(VE->IgnoreParens());
21863 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
21864 if (ASE) {
21865 Type = ASE->getType().getNonReferenceType();
21866 } else if (OASE) {
21867 QualType BaseType =
21868 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
21869 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21870 Type = ATy->getElementType();
21871 else
21872 Type = BaseType->getPointeeType();
21873 Type = Type.getNonReferenceType();
21874 } else if (OAShE) {
21875 Type = OAShE->getBase()->getType()->getPointeeType();
21876 } else {
21877 Type = VE->getType();
21878 }
21879
21880 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
21881 // A list item in a to or from clause must have a mappable type.
21882 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21883 // A list item must have a mappable type.
21884 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
21885 DSAS, Type, /*FullCheck=*/true))
21886 continue;
21887
21888 if (CKind == OMPC_map) {
21889 // target enter data
21890 // OpenMP [2.10.2, Restrictions, p. 99]
21891 // A map-type must be specified in all map clauses and must be either
21892 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
21893 // no map type is present.
21894 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
21895 if (DKind == OMPD_target_enter_data &&
21896 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
21897 SemaRef.getLangOpts().OpenMP >= 52)) {
21898 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21899 << (IsMapTypeImplicit ? 1 : 0)
21900 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21901 << getOpenMPDirectiveName(DKind);
21902 continue;
21903 }
21904
21905 // target exit_data
21906 // OpenMP [2.10.3, Restrictions, p. 102]
21907 // A map-type must be specified in all map clauses and must be either
21908 // from, release, or delete. Starting with OpenMP 5.2 the default map
21909 // type is `from` if no map type is present.
21910 if (DKind == OMPD_target_exit_data &&
21911 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
21912 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
21913 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21914 << (IsMapTypeImplicit ? 1 : 0)
21915 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21916 << getOpenMPDirectiveName(DKind);
21917 continue;
21918 }
21919
21920 // The 'ompx_hold' modifier is specifically intended to be used on a
21921 // 'target' or 'target data' directive to prevent data from being unmapped
21922 // during the associated statement. It is not permitted on a 'target
21923 // enter data' or 'target exit data' directive, which have no associated
21924 // statement.
21925 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
21926 HasHoldModifier) {
21927 SemaRef.Diag(StartLoc,
21928 diag::err_omp_invalid_map_type_modifier_for_directive)
21929 << getOpenMPSimpleClauseTypeName(OMPC_map,
21930 OMPC_MAP_MODIFIER_ompx_hold)
21931 << getOpenMPDirectiveName(DKind);
21932 continue;
21933 }
21934
21935 // target, target data
21936 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
21937 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
21938 // A map-type in a map clause must be to, from, tofrom or alloc
21939 if ((DKind == OMPD_target_data ||
21940 isOpenMPTargetExecutionDirective(DKind)) &&
21941 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
21942 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
21943 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21944 << (IsMapTypeImplicit ? 1 : 0)
21945 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21946 << getOpenMPDirectiveName(DKind);
21947 continue;
21948 }
21949
21950 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
21951 // A list item cannot appear in both a map clause and a data-sharing
21952 // attribute clause on the same construct
21953 //
21954 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
21955 // A list item cannot appear in both a map clause and a data-sharing
21956 // attribute clause on the same construct unless the construct is a
21957 // combined construct.
21958 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
21959 isOpenMPTargetExecutionDirective(DKind)) ||
21960 DKind == OMPD_target)) {
21961 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21962 if (isOpenMPPrivate(DVar.CKind)) {
21963 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
21964 << getOpenMPClauseName(DVar.CKind)
21965 << getOpenMPClauseName(OMPC_map)
21966 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
21967 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
21968 continue;
21969 }
21970 }
21971 }
21972
21973 // Try to find the associated user-defined mapper.
21974 ExprResult ER = buildUserDefinedMapperRef(
21975 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21976 Type.getCanonicalType(), UnresolvedMapper);
21977 if (ER.isInvalid())
21978 continue;
21979 MVLI.UDMapperList.push_back(ER.get());
21980
21981 // Save the current expression.
21982 MVLI.ProcessedVarList.push_back(RE);
21983
21984 // Store the components in the stack so that they can be used to check
21985 // against other clauses later on.
21986 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
21987 /*WhereFoundClauseKind=*/OMPC_map);
21988
21989 // Save the components and declaration to create the clause. For purposes of
21990 // the clause creation, any component list that has base 'this' uses
21991 // null as base declaration.
21992 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21993 MVLI.VarComponents.back().append(CurComponents.begin(),
21994 CurComponents.end());
21995 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
21996 : CurDeclaration);
21997 }
21998 }
21999
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)22000 OMPClause *Sema::ActOnOpenMPMapClause(
22001 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
22002 ArrayRef<SourceLocation> MapTypeModifiersLoc,
22003 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22004 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
22005 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22006 const OMPVarListLocTy &Locs, bool NoDiagnose,
22007 ArrayRef<Expr *> UnresolvedMappers) {
22008 OpenMPMapModifierKind Modifiers[] = {
22009 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
22010 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
22011 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown};
22012 SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers];
22013
22014 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
22015 BuiltinType::OMPIterator))
22016 Diag(IteratorModifier->getExprLoc(),
22017 diag::err_omp_map_modifier_not_iterator);
22018
22019 // Process map-type-modifiers, flag errors for duplicate modifiers.
22020 unsigned Count = 0;
22021 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
22022 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
22023 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
22024 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
22025 continue;
22026 }
22027 assert(Count < NumberOfOMPMapClauseModifiers &&
22028 "Modifiers exceed the allowed number of map type modifiers");
22029 Modifiers[Count] = MapTypeModifiers[I];
22030 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
22031 ++Count;
22032 }
22033
22034 MappableVarListInfo MVLI(VarList);
22035 checkMappableExpressionList(*this, DSAStack, OMPC_map, MVLI, Locs.StartLoc,
22036 MapperIdScopeSpec, MapperId, UnresolvedMappers,
22037 MapType, Modifiers, IsMapTypeImplicit,
22038 NoDiagnose);
22039
22040 // We need to produce a map clause even if we don't have variables so that
22041 // other diagnostics related with non-existing map clauses are accurate.
22042 return OMPMapClause::Create(
22043 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22044 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
22045 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(Context), MapperId,
22046 MapType, IsMapTypeImplicit, MapLoc);
22047 }
22048
ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,TypeResult ParsedType)22049 QualType Sema::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
22050 TypeResult ParsedType) {
22051 assert(ParsedType.isUsable());
22052
22053 QualType ReductionType = GetTypeFromParser(ParsedType.get());
22054 if (ReductionType.isNull())
22055 return QualType();
22056
22057 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
22058 // A type name in a declare reduction directive cannot be a function type, an
22059 // array type, a reference type, or a type qualified with const, volatile or
22060 // restrict.
22061 if (ReductionType.hasQualifiers()) {
22062 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
22063 return QualType();
22064 }
22065
22066 if (ReductionType->isFunctionType()) {
22067 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
22068 return QualType();
22069 }
22070 if (ReductionType->isReferenceType()) {
22071 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
22072 return QualType();
22073 }
22074 if (ReductionType->isArrayType()) {
22075 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
22076 return QualType();
22077 }
22078 return ReductionType;
22079 }
22080
ActOnOpenMPDeclareReductionDirectiveStart(Scope * S,DeclContext * DC,DeclarationName Name,ArrayRef<std::pair<QualType,SourceLocation>> ReductionTypes,AccessSpecifier AS,Decl * PrevDeclInScope)22081 Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveStart(
22082 Scope *S, DeclContext *DC, DeclarationName Name,
22083 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
22084 AccessSpecifier AS, Decl *PrevDeclInScope) {
22085 SmallVector<Decl *, 8> Decls;
22086 Decls.reserve(ReductionTypes.size());
22087
22088 LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPReductionName,
22089 forRedeclarationInCurContext());
22090 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
22091 // A reduction-identifier may not be re-declared in the current scope for the
22092 // same type or for a type that is compatible according to the base language
22093 // rules.
22094 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22095 OMPDeclareReductionDecl *PrevDRD = nullptr;
22096 bool InCompoundScope = true;
22097 if (S != nullptr) {
22098 // Find previous declaration with the same name not referenced in other
22099 // declarations.
22100 FunctionScopeInfo *ParentFn = getEnclosingFunction();
22101 InCompoundScope =
22102 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22103 LookupName(Lookup, S);
22104 FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22105 /*AllowInlineNamespace=*/false);
22106 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
22107 LookupResult::Filter Filter = Lookup.makeFilter();
22108 while (Filter.hasNext()) {
22109 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
22110 if (InCompoundScope) {
22111 auto I = UsedAsPrevious.find(PrevDecl);
22112 if (I == UsedAsPrevious.end())
22113 UsedAsPrevious[PrevDecl] = false;
22114 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
22115 UsedAsPrevious[D] = true;
22116 }
22117 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22118 PrevDecl->getLocation();
22119 }
22120 Filter.done();
22121 if (InCompoundScope) {
22122 for (const auto &PrevData : UsedAsPrevious) {
22123 if (!PrevData.second) {
22124 PrevDRD = PrevData.first;
22125 break;
22126 }
22127 }
22128 }
22129 } else if (PrevDeclInScope != nullptr) {
22130 auto *PrevDRDInScope = PrevDRD =
22131 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
22132 do {
22133 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
22134 PrevDRDInScope->getLocation();
22135 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
22136 } while (PrevDRDInScope != nullptr);
22137 }
22138 for (const auto &TyData : ReductionTypes) {
22139 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
22140 bool Invalid = false;
22141 if (I != PreviousRedeclTypes.end()) {
22142 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
22143 << TyData.first;
22144 Diag(I->second, diag::note_previous_definition);
22145 Invalid = true;
22146 }
22147 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
22148 auto *DRD = OMPDeclareReductionDecl::Create(Context, DC, TyData.second,
22149 Name, TyData.first, PrevDRD);
22150 DC->addDecl(DRD);
22151 DRD->setAccess(AS);
22152 Decls.push_back(DRD);
22153 if (Invalid)
22154 DRD->setInvalidDecl();
22155 else
22156 PrevDRD = DRD;
22157 }
22158
22159 return DeclGroupPtrTy::make(
22160 DeclGroupRef::Create(Context, Decls.begin(), Decls.size()));
22161 }
22162
ActOnOpenMPDeclareReductionCombinerStart(Scope * S,Decl * D)22163 void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
22164 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22165
22166 // Enter new function scope.
22167 PushFunctionScope();
22168 setFunctionHasBranchProtectedScope();
22169 getCurFunction()->setHasOMPDeclareReductionCombiner();
22170
22171 if (S != nullptr)
22172 PushDeclContext(S, DRD);
22173 else
22174 CurContext = DRD;
22175
22176 PushExpressionEvaluationContext(
22177 ExpressionEvaluationContext::PotentiallyEvaluated);
22178
22179 QualType ReductionType = DRD->getType();
22180 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
22181 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
22182 // uses semantics of argument handles by value, but it should be passed by
22183 // reference. C lang does not support references, so pass all parameters as
22184 // pointers.
22185 // Create 'T omp_in;' variable.
22186 VarDecl *OmpInParm =
22187 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_in");
22188 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
22189 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
22190 // uses semantics of argument handles by value, but it should be passed by
22191 // reference. C lang does not support references, so pass all parameters as
22192 // pointers.
22193 // Create 'T omp_out;' variable.
22194 VarDecl *OmpOutParm =
22195 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_out");
22196 if (S != nullptr) {
22197 PushOnScopeChains(OmpInParm, S);
22198 PushOnScopeChains(OmpOutParm, S);
22199 } else {
22200 DRD->addDecl(OmpInParm);
22201 DRD->addDecl(OmpOutParm);
22202 }
22203 Expr *InE =
22204 ::buildDeclRefExpr(*this, OmpInParm, ReductionType, D->getLocation());
22205 Expr *OutE =
22206 ::buildDeclRefExpr(*this, OmpOutParm, ReductionType, D->getLocation());
22207 DRD->setCombinerData(InE, OutE);
22208 }
22209
ActOnOpenMPDeclareReductionCombinerEnd(Decl * D,Expr * Combiner)22210 void Sema::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner) {
22211 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22212 DiscardCleanupsInEvaluationContext();
22213 PopExpressionEvaluationContext();
22214
22215 PopDeclContext();
22216 PopFunctionScopeInfo();
22217
22218 if (Combiner != nullptr)
22219 DRD->setCombiner(Combiner);
22220 else
22221 DRD->setInvalidDecl();
22222 }
22223
ActOnOpenMPDeclareReductionInitializerStart(Scope * S,Decl * D)22224 VarDecl *Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) {
22225 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22226
22227 // Enter new function scope.
22228 PushFunctionScope();
22229 setFunctionHasBranchProtectedScope();
22230
22231 if (S != nullptr)
22232 PushDeclContext(S, DRD);
22233 else
22234 CurContext = DRD;
22235
22236 PushExpressionEvaluationContext(
22237 ExpressionEvaluationContext::PotentiallyEvaluated);
22238
22239 QualType ReductionType = DRD->getType();
22240 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
22241 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
22242 // uses semantics of argument handles by value, but it should be passed by
22243 // reference. C lang does not support references, so pass all parameters as
22244 // pointers.
22245 // Create 'T omp_priv;' variable.
22246 VarDecl *OmpPrivParm =
22247 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_priv");
22248 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
22249 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
22250 // uses semantics of argument handles by value, but it should be passed by
22251 // reference. C lang does not support references, so pass all parameters as
22252 // pointers.
22253 // Create 'T omp_orig;' variable.
22254 VarDecl *OmpOrigParm =
22255 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_orig");
22256 if (S != nullptr) {
22257 PushOnScopeChains(OmpPrivParm, S);
22258 PushOnScopeChains(OmpOrigParm, S);
22259 } else {
22260 DRD->addDecl(OmpPrivParm);
22261 DRD->addDecl(OmpOrigParm);
22262 }
22263 Expr *OrigE =
22264 ::buildDeclRefExpr(*this, OmpOrigParm, ReductionType, D->getLocation());
22265 Expr *PrivE =
22266 ::buildDeclRefExpr(*this, OmpPrivParm, ReductionType, D->getLocation());
22267 DRD->setInitializerData(OrigE, PrivE);
22268 return OmpPrivParm;
22269 }
22270
ActOnOpenMPDeclareReductionInitializerEnd(Decl * D,Expr * Initializer,VarDecl * OmpPrivParm)22271 void Sema::ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer,
22272 VarDecl *OmpPrivParm) {
22273 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22274 DiscardCleanupsInEvaluationContext();
22275 PopExpressionEvaluationContext();
22276
22277 PopDeclContext();
22278 PopFunctionScopeInfo();
22279
22280 if (Initializer != nullptr) {
22281 DRD->setInitializer(Initializer, OMPDeclareReductionDecl::CallInit);
22282 } else if (OmpPrivParm->hasInit()) {
22283 DRD->setInitializer(OmpPrivParm->getInit(),
22284 OmpPrivParm->isDirectInit()
22285 ? OMPDeclareReductionDecl::DirectInit
22286 : OMPDeclareReductionDecl::CopyInit);
22287 } else {
22288 DRD->setInvalidDecl();
22289 }
22290 }
22291
ActOnOpenMPDeclareReductionDirectiveEnd(Scope * S,DeclGroupPtrTy DeclReductions,bool IsValid)22292 Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveEnd(
22293 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
22294 for (Decl *D : DeclReductions.get()) {
22295 if (IsValid) {
22296 if (S)
22297 PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
22298 /*AddToContext=*/false);
22299 } else {
22300 D->setInvalidDecl();
22301 }
22302 }
22303 return DeclReductions;
22304 }
22305
ActOnOpenMPDeclareMapperVarDecl(Scope * S,Declarator & D)22306 TypeResult Sema::ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D) {
22307 TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
22308 QualType T = TInfo->getType();
22309 if (D.isInvalidType())
22310 return true;
22311
22312 if (getLangOpts().CPlusPlus) {
22313 // Check that there are no default arguments (C++ only).
22314 CheckExtraCXXDefaultArguments(D);
22315 }
22316
22317 return CreateParsedType(T, TInfo);
22318 }
22319
ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,TypeResult ParsedType)22320 QualType Sema::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
22321 TypeResult ParsedType) {
22322 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
22323
22324 QualType MapperType = GetTypeFromParser(ParsedType.get());
22325 assert(!MapperType.isNull() && "Expect valid mapper type");
22326
22327 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22328 // The type must be of struct, union or class type in C and C++
22329 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
22330 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
22331 return QualType();
22332 }
22333 return MapperType;
22334 }
22335
ActOnOpenMPDeclareMapperDirective(Scope * S,DeclContext * DC,DeclarationName Name,QualType MapperType,SourceLocation StartLoc,DeclarationName VN,AccessSpecifier AS,Expr * MapperVarRef,ArrayRef<OMPClause * > Clauses,Decl * PrevDeclInScope)22336 Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareMapperDirective(
22337 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
22338 SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
22339 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
22340 LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPMapperName,
22341 forRedeclarationInCurContext());
22342 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22343 // A mapper-identifier may not be redeclared in the current scope for the
22344 // same type or for a type that is compatible according to the base language
22345 // rules.
22346 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22347 OMPDeclareMapperDecl *PrevDMD = nullptr;
22348 bool InCompoundScope = true;
22349 if (S != nullptr) {
22350 // Find previous declaration with the same name not referenced in other
22351 // declarations.
22352 FunctionScopeInfo *ParentFn = getEnclosingFunction();
22353 InCompoundScope =
22354 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22355 LookupName(Lookup, S);
22356 FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22357 /*AllowInlineNamespace=*/false);
22358 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
22359 LookupResult::Filter Filter = Lookup.makeFilter();
22360 while (Filter.hasNext()) {
22361 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
22362 if (InCompoundScope) {
22363 auto I = UsedAsPrevious.find(PrevDecl);
22364 if (I == UsedAsPrevious.end())
22365 UsedAsPrevious[PrevDecl] = false;
22366 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
22367 UsedAsPrevious[D] = true;
22368 }
22369 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22370 PrevDecl->getLocation();
22371 }
22372 Filter.done();
22373 if (InCompoundScope) {
22374 for (const auto &PrevData : UsedAsPrevious) {
22375 if (!PrevData.second) {
22376 PrevDMD = PrevData.first;
22377 break;
22378 }
22379 }
22380 }
22381 } else if (PrevDeclInScope) {
22382 auto *PrevDMDInScope = PrevDMD =
22383 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
22384 do {
22385 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
22386 PrevDMDInScope->getLocation();
22387 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
22388 } while (PrevDMDInScope != nullptr);
22389 }
22390 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
22391 bool Invalid = false;
22392 if (I != PreviousRedeclTypes.end()) {
22393 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
22394 << MapperType << Name;
22395 Diag(I->second, diag::note_previous_definition);
22396 Invalid = true;
22397 }
22398 // Build expressions for implicit maps of data members with 'default'
22399 // mappers.
22400 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses.begin(),
22401 Clauses.end());
22402 if (LangOpts.OpenMP >= 50)
22403 processImplicitMapsWithDefaultMappers(*this, DSAStack, ClausesWithImplicit);
22404 auto *DMD =
22405 OMPDeclareMapperDecl::Create(Context, DC, StartLoc, Name, MapperType, VN,
22406 ClausesWithImplicit, PrevDMD);
22407 if (S)
22408 PushOnScopeChains(DMD, S);
22409 else
22410 DC->addDecl(DMD);
22411 DMD->setAccess(AS);
22412 if (Invalid)
22413 DMD->setInvalidDecl();
22414
22415 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22416 VD->setDeclContext(DMD);
22417 VD->setLexicalDeclContext(DMD);
22418 DMD->addDecl(VD);
22419 DMD->setMapperVarRef(MapperVarRef);
22420
22421 return DeclGroupPtrTy::make(DeclGroupRef(DMD));
22422 }
22423
22424 ExprResult
ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope * S,QualType MapperType,SourceLocation StartLoc,DeclarationName VN)22425 Sema::ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType,
22426 SourceLocation StartLoc,
22427 DeclarationName VN) {
22428 TypeSourceInfo *TInfo =
22429 Context.getTrivialTypeSourceInfo(MapperType, StartLoc);
22430 auto *VD = VarDecl::Create(Context, Context.getTranslationUnitDecl(),
22431 StartLoc, StartLoc, VN.getAsIdentifierInfo(),
22432 MapperType, TInfo, SC_None);
22433 if (S)
22434 PushOnScopeChains(VD, S, /*AddToContext=*/false);
22435 Expr *E = buildDeclRefExpr(*this, VD, MapperType, StartLoc);
22436 DSAStack->addDeclareMapperVarRef(E);
22437 return E;
22438 }
22439
ActOnOpenMPIteratorVarDecl(VarDecl * VD)22440 void Sema::ActOnOpenMPIteratorVarDecl(VarDecl *VD) {
22441 if (DSAStack->getDeclareMapperVarRef())
22442 DSAStack->addIteratorVarDecl(VD);
22443 }
22444
isOpenMPDeclareMapperVarDeclAllowed(const VarDecl * VD) const22445 bool Sema::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const {
22446 assert(LangOpts.OpenMP && "Expected OpenMP mode.");
22447 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
22448 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
22449 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
22450 return true;
22451 if (VD->isUsableInConstantExpressions(Context))
22452 return true;
22453 if (LangOpts.OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
22454 return true;
22455 return false;
22456 }
22457 return true;
22458 }
22459
getOpenMPDeclareMapperVarName() const22460 const ValueDecl *Sema::getOpenMPDeclareMapperVarName() const {
22461 assert(LangOpts.OpenMP && "Expected OpenMP mode.");
22462 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
22463 }
22464
ActOnOpenMPNumTeamsClause(Expr * NumTeams,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)22465 OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams,
22466 SourceLocation StartLoc,
22467 SourceLocation LParenLoc,
22468 SourceLocation EndLoc) {
22469 Expr *ValExpr = NumTeams;
22470 Stmt *HelperValStmt = nullptr;
22471
22472 // OpenMP [teams Constrcut, Restrictions]
22473 // The num_teams expression must evaluate to a positive integer value.
22474 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_teams,
22475 /*StrictlyPositive=*/true))
22476 return nullptr;
22477
22478 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22479 OpenMPDirectiveKind CaptureRegion =
22480 getOpenMPCaptureRegionForClause(DKind, OMPC_num_teams, LangOpts.OpenMP);
22481 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
22482 ValExpr = MakeFullExpr(ValExpr).get();
22483 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22484 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
22485 HelperValStmt = buildPreInits(Context, Captures);
22486 }
22487
22488 return new (Context) OMPNumTeamsClause(ValExpr, HelperValStmt, CaptureRegion,
22489 StartLoc, LParenLoc, EndLoc);
22490 }
22491
ActOnOpenMPThreadLimitClause(Expr * ThreadLimit,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)22492 OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
22493 SourceLocation StartLoc,
22494 SourceLocation LParenLoc,
22495 SourceLocation EndLoc) {
22496 Expr *ValExpr = ThreadLimit;
22497 Stmt *HelperValStmt = nullptr;
22498
22499 // OpenMP [teams Constrcut, Restrictions]
22500 // The thread_limit expression must evaluate to a positive integer value.
22501 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_thread_limit,
22502 /*StrictlyPositive=*/true))
22503 return nullptr;
22504
22505 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22506 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
22507 DKind, OMPC_thread_limit, LangOpts.OpenMP);
22508 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
22509 ValExpr = MakeFullExpr(ValExpr).get();
22510 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22511 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
22512 HelperValStmt = buildPreInits(Context, Captures);
22513 }
22514
22515 return new (Context) OMPThreadLimitClause(
22516 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22517 }
22518
ActOnOpenMPPriorityClause(Expr * Priority,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)22519 OMPClause *Sema::ActOnOpenMPPriorityClause(Expr *Priority,
22520 SourceLocation StartLoc,
22521 SourceLocation LParenLoc,
22522 SourceLocation EndLoc) {
22523 Expr *ValExpr = Priority;
22524 Stmt *HelperValStmt = nullptr;
22525 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22526
22527 // OpenMP [2.9.1, task Constrcut]
22528 // The priority-value is a non-negative numerical scalar expression.
22529 if (!isNonNegativeIntegerValue(
22530 ValExpr, *this, OMPC_priority,
22531 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
22532 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22533 return nullptr;
22534
22535 return new (Context) OMPPriorityClause(ValExpr, HelperValStmt, CaptureRegion,
22536 StartLoc, LParenLoc, EndLoc);
22537 }
22538
ActOnOpenMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier,Expr * Grainsize,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ModifierLoc,SourceLocation EndLoc)22539 OMPClause *Sema::ActOnOpenMPGrainsizeClause(
22540 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
22541 SourceLocation StartLoc, SourceLocation LParenLoc,
22542 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22543 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 51) &&
22544 "Unexpected grainsize modifier in OpenMP < 51.");
22545
22546 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
22547 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
22548 OMPC_GRAINSIZE_unknown);
22549 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22550 << Values << getOpenMPClauseName(OMPC_grainsize);
22551 return nullptr;
22552 }
22553
22554 Expr *ValExpr = Grainsize;
22555 Stmt *HelperValStmt = nullptr;
22556 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22557
22558 // OpenMP [2.9.2, taskloop Constrcut]
22559 // The parameter of the grainsize clause must be a positive integer
22560 // expression.
22561 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_grainsize,
22562 /*StrictlyPositive=*/true,
22563 /*BuildCapture=*/true,
22564 DSAStack->getCurrentDirective(),
22565 &CaptureRegion, &HelperValStmt))
22566 return nullptr;
22567
22568 return new (Context)
22569 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22570 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22571 }
22572
ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier,Expr * NumTasks,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ModifierLoc,SourceLocation EndLoc)22573 OMPClause *Sema::ActOnOpenMPNumTasksClause(
22574 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
22575 SourceLocation StartLoc, SourceLocation LParenLoc,
22576 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22577 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 51) &&
22578 "Unexpected num_tasks modifier in OpenMP < 51.");
22579
22580 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
22581 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
22582 OMPC_NUMTASKS_unknown);
22583 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22584 << Values << getOpenMPClauseName(OMPC_num_tasks);
22585 return nullptr;
22586 }
22587
22588 Expr *ValExpr = NumTasks;
22589 Stmt *HelperValStmt = nullptr;
22590 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22591
22592 // OpenMP [2.9.2, taskloop Constrcut]
22593 // The parameter of the num_tasks clause must be a positive integer
22594 // expression.
22595 if (!isNonNegativeIntegerValue(
22596 ValExpr, *this, OMPC_num_tasks,
22597 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
22598 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22599 return nullptr;
22600
22601 return new (Context)
22602 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22603 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22604 }
22605
ActOnOpenMPHintClause(Expr * Hint,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)22606 OMPClause *Sema::ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,
22607 SourceLocation LParenLoc,
22608 SourceLocation EndLoc) {
22609 // OpenMP [2.13.2, critical construct, Description]
22610 // ... where hint-expression is an integer constant expression that evaluates
22611 // to a valid lock hint.
22612 ExprResult HintExpr =
22613 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
22614 if (HintExpr.isInvalid())
22615 return nullptr;
22616 return new (Context)
22617 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
22618 }
22619
22620 /// Tries to find omp_event_handle_t type.
findOMPEventHandleT(Sema & S,SourceLocation Loc,DSAStackTy * Stack)22621 static bool findOMPEventHandleT(Sema &S, SourceLocation Loc,
22622 DSAStackTy *Stack) {
22623 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
22624 if (!OMPEventHandleT.isNull())
22625 return true;
22626 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
22627 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
22628 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
22629 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
22630 return false;
22631 }
22632 Stack->setOMPEventHandleT(PT.get());
22633 return true;
22634 }
22635
ActOnOpenMPDetachClause(Expr * Evt,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)22636 OMPClause *Sema::ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc,
22637 SourceLocation LParenLoc,
22638 SourceLocation EndLoc) {
22639 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
22640 !Evt->isInstantiationDependent() &&
22641 !Evt->containsUnexpandedParameterPack()) {
22642 if (!findOMPEventHandleT(*this, Evt->getExprLoc(), DSAStack))
22643 return nullptr;
22644 // OpenMP 5.0, 2.10.1 task Construct.
22645 // event-handle is a variable of the omp_event_handle_t type.
22646 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
22647 if (!Ref) {
22648 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22649 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22650 return nullptr;
22651 }
22652 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
22653 if (!VD) {
22654 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22655 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22656 return nullptr;
22657 }
22658 if (!Context.hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
22659 VD->getType()) ||
22660 VD->getType().isConstant(Context)) {
22661 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22662 << "omp_event_handle_t" << 1 << VD->getType()
22663 << Evt->getSourceRange();
22664 return nullptr;
22665 }
22666 // OpenMP 5.0, 2.10.1 task Construct
22667 // [detach clause]... The event-handle will be considered as if it was
22668 // specified on a firstprivate clause.
22669 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
22670 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
22671 DVar.RefExpr) {
22672 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
22673 << getOpenMPClauseName(DVar.CKind)
22674 << getOpenMPClauseName(OMPC_firstprivate);
22675 reportOriginalDsa(*this, DSAStack, VD, DVar);
22676 return nullptr;
22677 }
22678 }
22679
22680 return new (Context) OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
22681 }
22682
ActOnOpenMPDistScheduleClause(OpenMPDistScheduleClauseKind Kind,Expr * ChunkSize,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation KindLoc,SourceLocation CommaLoc,SourceLocation EndLoc)22683 OMPClause *Sema::ActOnOpenMPDistScheduleClause(
22684 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
22685 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
22686 SourceLocation EndLoc) {
22687 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
22688 std::string Values;
22689 Values += "'";
22690 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
22691 Values += "'";
22692 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22693 << Values << getOpenMPClauseName(OMPC_dist_schedule);
22694 return nullptr;
22695 }
22696 Expr *ValExpr = ChunkSize;
22697 Stmt *HelperValStmt = nullptr;
22698 if (ChunkSize) {
22699 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
22700 !ChunkSize->isInstantiationDependent() &&
22701 !ChunkSize->containsUnexpandedParameterPack()) {
22702 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
22703 ExprResult Val =
22704 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
22705 if (Val.isInvalid())
22706 return nullptr;
22707
22708 ValExpr = Val.get();
22709
22710 // OpenMP [2.7.1, Restrictions]
22711 // chunk_size must be a loop invariant integer expression with a positive
22712 // value.
22713 if (std::optional<llvm::APSInt> Result =
22714 ValExpr->getIntegerConstantExpr(Context)) {
22715 if (Result->isSigned() && !Result->isStrictlyPositive()) {
22716 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
22717 << "dist_schedule" << ChunkSize->getSourceRange();
22718 return nullptr;
22719 }
22720 } else if (getOpenMPCaptureRegionForClause(
22721 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
22722 LangOpts.OpenMP) != OMPD_unknown &&
22723 !CurContext->isDependentContext()) {
22724 ValExpr = MakeFullExpr(ValExpr).get();
22725 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22726 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
22727 HelperValStmt = buildPreInits(Context, Captures);
22728 }
22729 }
22730 }
22731
22732 return new (Context)
22733 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
22734 Kind, ValExpr, HelperValStmt);
22735 }
22736
ActOnOpenMPDefaultmapClause(OpenMPDefaultmapClauseModifier M,OpenMPDefaultmapClauseKind Kind,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation MLoc,SourceLocation KindLoc,SourceLocation EndLoc)22737 OMPClause *Sema::ActOnOpenMPDefaultmapClause(
22738 OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind,
22739 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
22740 SourceLocation KindLoc, SourceLocation EndLoc) {
22741 if (getLangOpts().OpenMP < 50) {
22742 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
22743 Kind != OMPC_DEFAULTMAP_scalar) {
22744 std::string Value;
22745 SourceLocation Loc;
22746 Value += "'";
22747 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
22748 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22749 OMPC_DEFAULTMAP_MODIFIER_tofrom);
22750 Loc = MLoc;
22751 } else {
22752 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22753 OMPC_DEFAULTMAP_scalar);
22754 Loc = KindLoc;
22755 }
22756 Value += "'";
22757 Diag(Loc, diag::err_omp_unexpected_clause_value)
22758 << Value << getOpenMPClauseName(OMPC_defaultmap);
22759 return nullptr;
22760 }
22761 } else {
22762 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
22763 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
22764 (LangOpts.OpenMP >= 50 && KindLoc.isInvalid());
22765 if (!isDefaultmapKind || !isDefaultmapModifier) {
22766 StringRef KindValue = "'scalar', 'aggregate', 'pointer'";
22767 if (LangOpts.OpenMP == 50) {
22768 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
22769 "'firstprivate', 'none', 'default'";
22770 if (!isDefaultmapKind && isDefaultmapModifier) {
22771 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22772 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22773 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22774 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22775 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22776 } else {
22777 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22778 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22779 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22780 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22781 }
22782 } else {
22783 StringRef ModifierValue =
22784 "'alloc', 'from', 'to', 'tofrom', "
22785 "'firstprivate', 'none', 'default', 'present'";
22786 if (!isDefaultmapKind && isDefaultmapModifier) {
22787 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22788 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22789 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22790 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22791 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22792 } else {
22793 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22794 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22795 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22796 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22797 }
22798 }
22799 return nullptr;
22800 }
22801
22802 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
22803 // At most one defaultmap clause for each category can appear on the
22804 // directive.
22805 if (DSAStack->checkDefaultmapCategory(Kind)) {
22806 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
22807 return nullptr;
22808 }
22809 }
22810 if (Kind == OMPC_DEFAULTMAP_unknown) {
22811 // Variable category is not specified - mark all categories.
22812 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
22813 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
22814 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
22815 } else {
22816 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
22817 }
22818
22819 return new (Context)
22820 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
22821 }
22822
ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo & DTCI)22823 bool Sema::ActOnStartOpenMPDeclareTargetContext(
22824 DeclareTargetContextInfo &DTCI) {
22825 DeclContext *CurLexicalContext = getCurLexicalContext();
22826 if (!CurLexicalContext->isFileContext() &&
22827 !CurLexicalContext->isExternCContext() &&
22828 !CurLexicalContext->isExternCXXContext() &&
22829 !isa<CXXRecordDecl>(CurLexicalContext) &&
22830 !isa<ClassTemplateDecl>(CurLexicalContext) &&
22831 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
22832 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
22833 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
22834 return false;
22835 }
22836 DeclareTargetNesting.push_back(DTCI);
22837 return true;
22838 }
22839
22840 const Sema::DeclareTargetContextInfo
ActOnOpenMPEndDeclareTargetDirective()22841 Sema::ActOnOpenMPEndDeclareTargetDirective() {
22842 assert(!DeclareTargetNesting.empty() &&
22843 "check isInOpenMPDeclareTargetContext() first!");
22844 return DeclareTargetNesting.pop_back_val();
22845 }
22846
ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo & DTCI)22847 void Sema::ActOnFinishedOpenMPDeclareTargetContext(
22848 DeclareTargetContextInfo &DTCI) {
22849 for (auto &It : DTCI.ExplicitlyMapped)
22850 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
22851 }
22852
DiagnoseUnterminatedOpenMPDeclareTarget()22853 void Sema::DiagnoseUnterminatedOpenMPDeclareTarget() {
22854 if (DeclareTargetNesting.empty())
22855 return;
22856 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
22857 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
22858 << getOpenMPDirectiveName(DTCI.Kind);
22859 }
22860
lookupOpenMPDeclareTargetName(Scope * CurScope,CXXScopeSpec & ScopeSpec,const DeclarationNameInfo & Id)22861 NamedDecl *Sema::lookupOpenMPDeclareTargetName(Scope *CurScope,
22862 CXXScopeSpec &ScopeSpec,
22863 const DeclarationNameInfo &Id) {
22864 LookupResult Lookup(*this, Id, LookupOrdinaryName);
22865 LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
22866
22867 if (Lookup.isAmbiguous())
22868 return nullptr;
22869 Lookup.suppressDiagnostics();
22870
22871 if (!Lookup.isSingleResult()) {
22872 VarOrFuncDeclFilterCCC CCC(*this);
22873 if (TypoCorrection Corrected =
22874 CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, CCC,
22875 CTK_ErrorRecovery)) {
22876 diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest)
22877 << Id.getName());
22878 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
22879 return nullptr;
22880 }
22881
22882 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
22883 return nullptr;
22884 }
22885
22886 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
22887 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
22888 !isa<FunctionTemplateDecl>(ND)) {
22889 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
22890 return nullptr;
22891 }
22892 return ND;
22893 }
22894
ActOnOpenMPDeclareTargetName(NamedDecl * ND,SourceLocation Loc,OMPDeclareTargetDeclAttr::MapTypeTy MT,DeclareTargetContextInfo & DTCI)22895 void Sema::ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc,
22896 OMPDeclareTargetDeclAttr::MapTypeTy MT,
22897 DeclareTargetContextInfo &DTCI) {
22898 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
22899 isa<FunctionTemplateDecl>(ND)) &&
22900 "Expected variable, function or function template.");
22901
22902 // Diagnose marking after use as it may lead to incorrect diagnosis and
22903 // codegen.
22904 if (LangOpts.OpenMP >= 50 &&
22905 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
22906 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
22907
22908 // Explicit declare target lists have precedence.
22909 const unsigned Level = -1;
22910
22911 auto *VD = cast<ValueDecl>(ND);
22912 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22913 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22914 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
22915 (*ActiveAttr)->getLevel() == Level) {
22916 Diag(Loc, diag::err_omp_device_type_mismatch)
22917 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
22918 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
22919 (*ActiveAttr)->getDevType());
22920 return;
22921 }
22922 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
22923 (*ActiveAttr)->getLevel() == Level) {
22924 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
22925 return;
22926 }
22927
22928 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
22929 return;
22930
22931 Expr *IndirectE = nullptr;
22932 bool IsIndirect = false;
22933 if (DTCI.Indirect) {
22934 IndirectE = *DTCI.Indirect;
22935 if (!IndirectE)
22936 IsIndirect = true;
22937 }
22938 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22939 Context, MT, DTCI.DT, IndirectE, IsIndirect, Level,
22940 SourceRange(Loc, Loc));
22941 ND->addAttr(A);
22942 if (ASTMutationListener *ML = Context.getASTMutationListener())
22943 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
22944 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
22945 }
22946
checkDeclInTargetContext(SourceLocation SL,SourceRange SR,Sema & SemaRef,Decl * D)22947 static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
22948 Sema &SemaRef, Decl *D) {
22949 if (!D || !isa<VarDecl>(D))
22950 return;
22951 auto *VD = cast<VarDecl>(D);
22952 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
22953 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
22954 if (SemaRef.LangOpts.OpenMP >= 50 &&
22955 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
22956 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
22957 VD->hasGlobalStorage()) {
22958 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
22959 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
22960 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
22961 // If a lambda declaration and definition appears between a
22962 // declare target directive and the matching end declare target
22963 // directive, all variables that are captured by the lambda
22964 // expression must also appear in a to clause.
22965 SemaRef.Diag(VD->getLocation(),
22966 diag::err_omp_lambda_capture_in_declare_target_not_to);
22967 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
22968 << VD << 0 << SR;
22969 return;
22970 }
22971 }
22972 if (MapTy)
22973 return;
22974 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
22975 SemaRef.Diag(SL, diag::note_used_here) << SR;
22976 }
22977
checkValueDeclInTarget(SourceLocation SL,SourceRange SR,Sema & SemaRef,DSAStackTy * Stack,ValueDecl * VD)22978 static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR,
22979 Sema &SemaRef, DSAStackTy *Stack,
22980 ValueDecl *VD) {
22981 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
22982 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
22983 /*FullCheck=*/false);
22984 }
22985
checkDeclIsAllowedInOpenMPTarget(Expr * E,Decl * D,SourceLocation IdLoc)22986 void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
22987 SourceLocation IdLoc) {
22988 if (!D || D->isInvalidDecl())
22989 return;
22990 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
22991 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
22992 if (auto *VD = dyn_cast<VarDecl>(D)) {
22993 // Only global variables can be marked as declare target.
22994 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22995 !VD->isStaticDataMember())
22996 return;
22997 // 2.10.6: threadprivate variable cannot appear in a declare target
22998 // directive.
22999 if (DSAStack->isThreadPrivate(VD)) {
23000 Diag(SL, diag::err_omp_threadprivate_in_target);
23001 reportOriginalDsa(*this, DSAStack, VD, DSAStack->getTopDSA(VD, false));
23002 return;
23003 }
23004 }
23005 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
23006 D = FTD->getTemplatedDecl();
23007 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
23008 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
23009 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
23010 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
23011 Diag(IdLoc, diag::err_omp_function_in_link_clause);
23012 Diag(FD->getLocation(), diag::note_defined_here) << FD;
23013 return;
23014 }
23015 }
23016 if (auto *VD = dyn_cast<ValueDecl>(D)) {
23017 // Problem if any with var declared with incomplete type will be reported
23018 // as normal, so no need to check it here.
23019 if ((E || !VD->getType()->isIncompleteType()) &&
23020 !checkValueDeclInTarget(SL, SR, *this, DSAStack, VD))
23021 return;
23022 if (!E && isInOpenMPDeclareTargetContext()) {
23023 // Checking declaration inside declare target region.
23024 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
23025 isa<FunctionTemplateDecl>(D)) {
23026 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23027 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23028 unsigned Level = DeclareTargetNesting.size();
23029 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
23030 return;
23031 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23032 Expr *IndirectE = nullptr;
23033 bool IsIndirect = false;
23034 if (DTCI.Indirect) {
23035 IndirectE = *DTCI.Indirect;
23036 if (!IndirectE)
23037 IsIndirect = true;
23038 }
23039 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23040 Context,
23041 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
23042 : OMPDeclareTargetDeclAttr::MT_To,
23043 DTCI.DT, IndirectE, IsIndirect, Level,
23044 SourceRange(DTCI.Loc, DTCI.Loc));
23045 D->addAttr(A);
23046 if (ASTMutationListener *ML = Context.getASTMutationListener())
23047 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
23048 }
23049 return;
23050 }
23051 }
23052 if (!E)
23053 return;
23054 checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), *this, D);
23055 }
23056
ActOnOpenMPToClause(ArrayRef<OpenMPMotionModifierKind> MotionModifiers,ArrayRef<SourceLocation> MotionModifiersLoc,CXXScopeSpec & MapperIdScopeSpec,DeclarationNameInfo & MapperId,SourceLocation ColonLoc,ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs,ArrayRef<Expr * > UnresolvedMappers)23057 OMPClause *Sema::ActOnOpenMPToClause(
23058 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23059 ArrayRef<SourceLocation> MotionModifiersLoc,
23060 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23061 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23062 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23063 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
23064 OMPC_MOTION_MODIFIER_unknown};
23065 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
23066
23067 // Process motion-modifiers, flag errors for duplicate modifiers.
23068 unsigned Count = 0;
23069 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23070 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23071 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23072 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23073 continue;
23074 }
23075 assert(Count < NumberOfOMPMotionModifiers &&
23076 "Modifiers exceed the allowed number of motion modifiers");
23077 Modifiers[Count] = MotionModifiers[I];
23078 ModifiersLoc[Count] = MotionModifiersLoc[I];
23079 ++Count;
23080 }
23081
23082 MappableVarListInfo MVLI(VarList);
23083 checkMappableExpressionList(*this, DSAStack, OMPC_to, MVLI, Locs.StartLoc,
23084 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23085 if (MVLI.ProcessedVarList.empty())
23086 return nullptr;
23087
23088 return OMPToClause::Create(
23089 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23090 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23091 MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
23092 }
23093
ActOnOpenMPFromClause(ArrayRef<OpenMPMotionModifierKind> MotionModifiers,ArrayRef<SourceLocation> MotionModifiersLoc,CXXScopeSpec & MapperIdScopeSpec,DeclarationNameInfo & MapperId,SourceLocation ColonLoc,ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs,ArrayRef<Expr * > UnresolvedMappers)23094 OMPClause *Sema::ActOnOpenMPFromClause(
23095 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23096 ArrayRef<SourceLocation> MotionModifiersLoc,
23097 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23098 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23099 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23100 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
23101 OMPC_MOTION_MODIFIER_unknown};
23102 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
23103
23104 // Process motion-modifiers, flag errors for duplicate modifiers.
23105 unsigned Count = 0;
23106 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23107 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23108 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23109 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23110 continue;
23111 }
23112 assert(Count < NumberOfOMPMotionModifiers &&
23113 "Modifiers exceed the allowed number of motion modifiers");
23114 Modifiers[Count] = MotionModifiers[I];
23115 ModifiersLoc[Count] = MotionModifiersLoc[I];
23116 ++Count;
23117 }
23118
23119 MappableVarListInfo MVLI(VarList);
23120 checkMappableExpressionList(*this, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
23121 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23122 if (MVLI.ProcessedVarList.empty())
23123 return nullptr;
23124
23125 return OMPFromClause::Create(
23126 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23127 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23128 MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
23129 }
23130
ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs)23131 OMPClause *Sema::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
23132 const OMPVarListLocTy &Locs) {
23133 MappableVarListInfo MVLI(VarList);
23134 SmallVector<Expr *, 8> PrivateCopies;
23135 SmallVector<Expr *, 8> Inits;
23136
23137 for (Expr *RefExpr : VarList) {
23138 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
23139 SourceLocation ELoc;
23140 SourceRange ERange;
23141 Expr *SimpleRefExpr = RefExpr;
23142 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23143 if (Res.second) {
23144 // It will be analyzed later.
23145 MVLI.ProcessedVarList.push_back(RefExpr);
23146 PrivateCopies.push_back(nullptr);
23147 Inits.push_back(nullptr);
23148 }
23149 ValueDecl *D = Res.first;
23150 if (!D)
23151 continue;
23152
23153 QualType Type = D->getType();
23154 Type = Type.getNonReferenceType().getUnqualifiedType();
23155
23156 auto *VD = dyn_cast<VarDecl>(D);
23157
23158 // Item should be a pointer or reference to pointer.
23159 if (!Type->isPointerType()) {
23160 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
23161 << 0 << RefExpr->getSourceRange();
23162 continue;
23163 }
23164
23165 // Build the private variable and the expression that refers to it.
23166 auto VDPrivate =
23167 buildVarDecl(*this, ELoc, Type, D->getName(),
23168 D->hasAttrs() ? &D->getAttrs() : nullptr,
23169 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
23170 if (VDPrivate->isInvalidDecl())
23171 continue;
23172
23173 CurContext->addDecl(VDPrivate);
23174 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
23175 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
23176
23177 // Add temporary variable to initialize the private copy of the pointer.
23178 VarDecl *VDInit =
23179 buildVarDecl(*this, RefExpr->getExprLoc(), Type, ".devptr.temp");
23180 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
23181 *this, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
23182 AddInitializerToDecl(VDPrivate,
23183 DefaultLvalueConversion(VDInitRefExpr).get(),
23184 /*DirectInit=*/false);
23185
23186 // If required, build a capture to implement the privatization initialized
23187 // with the current list item value.
23188 DeclRefExpr *Ref = nullptr;
23189 if (!VD)
23190 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
23191 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23192 PrivateCopies.push_back(VDPrivateRefExpr);
23193 Inits.push_back(VDInitRefExpr);
23194
23195 // We need to add a data sharing attribute for this variable to make sure it
23196 // is correctly captured. A variable that shows up in a use_device_ptr has
23197 // similar properties of a first private variable.
23198 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23199
23200 // Create a mappable component for the list item. List items in this clause
23201 // only need a component.
23202 MVLI.VarBaseDeclarations.push_back(D);
23203 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23204 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
23205 /*IsNonContiguous=*/false);
23206 }
23207
23208 if (MVLI.ProcessedVarList.empty())
23209 return nullptr;
23210
23211 return OMPUseDevicePtrClause::Create(
23212 Context, Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
23213 MVLI.VarBaseDeclarations, MVLI.VarComponents);
23214 }
23215
ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs)23216 OMPClause *Sema::ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList,
23217 const OMPVarListLocTy &Locs) {
23218 MappableVarListInfo MVLI(VarList);
23219
23220 for (Expr *RefExpr : VarList) {
23221 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
23222 SourceLocation ELoc;
23223 SourceRange ERange;
23224 Expr *SimpleRefExpr = RefExpr;
23225 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23226 /*AllowArraySection=*/true);
23227 if (Res.second) {
23228 // It will be analyzed later.
23229 MVLI.ProcessedVarList.push_back(RefExpr);
23230 }
23231 ValueDecl *D = Res.first;
23232 if (!D)
23233 continue;
23234 auto *VD = dyn_cast<VarDecl>(D);
23235
23236 // If required, build a capture to implement the privatization initialized
23237 // with the current list item value.
23238 DeclRefExpr *Ref = nullptr;
23239 if (!VD)
23240 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
23241 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23242
23243 // We need to add a data sharing attribute for this variable to make sure it
23244 // is correctly captured. A variable that shows up in a use_device_addr has
23245 // similar properties of a first private variable.
23246 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23247
23248 // Create a mappable component for the list item. List items in this clause
23249 // only need a component.
23250 MVLI.VarBaseDeclarations.push_back(D);
23251 MVLI.VarComponents.emplace_back();
23252 Expr *Component = SimpleRefExpr;
23253 if (VD && (isa<OMPArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23254 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23255 Component = DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
23256 MVLI.VarComponents.back().emplace_back(Component, D,
23257 /*IsNonContiguous=*/false);
23258 }
23259
23260 if (MVLI.ProcessedVarList.empty())
23261 return nullptr;
23262
23263 return OMPUseDeviceAddrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23264 MVLI.VarBaseDeclarations,
23265 MVLI.VarComponents);
23266 }
23267
ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs)23268 OMPClause *Sema::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
23269 const OMPVarListLocTy &Locs) {
23270 MappableVarListInfo MVLI(VarList);
23271 for (Expr *RefExpr : VarList) {
23272 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
23273 SourceLocation ELoc;
23274 SourceRange ERange;
23275 Expr *SimpleRefExpr = RefExpr;
23276 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23277 if (Res.second) {
23278 // It will be analyzed later.
23279 MVLI.ProcessedVarList.push_back(RefExpr);
23280 }
23281 ValueDecl *D = Res.first;
23282 if (!D)
23283 continue;
23284
23285 QualType Type = D->getType();
23286 // item should be a pointer or array or reference to pointer or array
23287 if (!Type.getNonReferenceType()->isPointerType() &&
23288 !Type.getNonReferenceType()->isArrayType()) {
23289 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
23290 << 0 << RefExpr->getSourceRange();
23291 continue;
23292 }
23293
23294 // Check if the declaration in the clause does not show up in any data
23295 // sharing attribute.
23296 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23297 if (isOpenMPPrivate(DVar.CKind)) {
23298 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23299 << getOpenMPClauseName(DVar.CKind)
23300 << getOpenMPClauseName(OMPC_is_device_ptr)
23301 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
23302 reportOriginalDsa(*this, DSAStack, D, DVar);
23303 continue;
23304 }
23305
23306 const Expr *ConflictExpr;
23307 if (DSAStack->checkMappableExprComponentListsForDecl(
23308 D, /*CurrentRegionOnly=*/true,
23309 [&ConflictExpr](
23310 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
23311 OpenMPClauseKind) -> bool {
23312 ConflictExpr = R.front().getAssociatedExpression();
23313 return true;
23314 })) {
23315 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23316 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23317 << ConflictExpr->getSourceRange();
23318 continue;
23319 }
23320
23321 // Store the components in the stack so that they can be used to check
23322 // against other clauses later on.
23323 OMPClauseMappableExprCommon::MappableComponent MC(
23324 SimpleRefExpr, D, /*IsNonContiguous=*/false);
23325 DSAStack->addMappableExpressionComponents(
23326 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
23327
23328 // Record the expression we've just processed.
23329 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
23330
23331 // Create a mappable component for the list item. List items in this clause
23332 // only need a component. We use a null declaration to signal fields in
23333 // 'this'.
23334 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23335 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23336 "Unexpected device pointer expression!");
23337 MVLI.VarBaseDeclarations.push_back(
23338 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23339 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23340 MVLI.VarComponents.back().push_back(MC);
23341 }
23342
23343 if (MVLI.ProcessedVarList.empty())
23344 return nullptr;
23345
23346 return OMPIsDevicePtrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23347 MVLI.VarBaseDeclarations,
23348 MVLI.VarComponents);
23349 }
23350
ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr * > VarList,const OMPVarListLocTy & Locs)23351 OMPClause *Sema::ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr *> VarList,
23352 const OMPVarListLocTy &Locs) {
23353 MappableVarListInfo MVLI(VarList);
23354 for (Expr *RefExpr : VarList) {
23355 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
23356 SourceLocation ELoc;
23357 SourceRange ERange;
23358 Expr *SimpleRefExpr = RefExpr;
23359 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23360 /*AllowArraySection=*/true);
23361 if (Res.second) {
23362 // It will be analyzed later.
23363 MVLI.ProcessedVarList.push_back(RefExpr);
23364 }
23365 ValueDecl *D = Res.first;
23366 if (!D)
23367 continue;
23368
23369 // Check if the declaration in the clause does not show up in any data
23370 // sharing attribute.
23371 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23372 if (isOpenMPPrivate(DVar.CKind)) {
23373 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23374 << getOpenMPClauseName(DVar.CKind)
23375 << getOpenMPClauseName(OMPC_has_device_addr)
23376 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
23377 reportOriginalDsa(*this, DSAStack, D, DVar);
23378 continue;
23379 }
23380
23381 const Expr *ConflictExpr;
23382 if (DSAStack->checkMappableExprComponentListsForDecl(
23383 D, /*CurrentRegionOnly=*/true,
23384 [&ConflictExpr](
23385 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
23386 OpenMPClauseKind) -> bool {
23387 ConflictExpr = R.front().getAssociatedExpression();
23388 return true;
23389 })) {
23390 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23391 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23392 << ConflictExpr->getSourceRange();
23393 continue;
23394 }
23395
23396 // Store the components in the stack so that they can be used to check
23397 // against other clauses later on.
23398 Expr *Component = SimpleRefExpr;
23399 auto *VD = dyn_cast<VarDecl>(D);
23400 if (VD && (isa<OMPArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23401 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23402 Component = DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
23403 OMPClauseMappableExprCommon::MappableComponent MC(
23404 Component, D, /*IsNonContiguous=*/false);
23405 DSAStack->addMappableExpressionComponents(
23406 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
23407
23408 // Record the expression we've just processed.
23409 if (!VD && !CurContext->isDependentContext()) {
23410 DeclRefExpr *Ref =
23411 buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
23412 assert(Ref && "has_device_addr capture failed");
23413 MVLI.ProcessedVarList.push_back(Ref);
23414 } else
23415 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
23416
23417 // Create a mappable component for the list item. List items in this clause
23418 // only need a component. We use a null declaration to signal fields in
23419 // 'this'.
23420 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23421 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23422 "Unexpected device pointer expression!");
23423 MVLI.VarBaseDeclarations.push_back(
23424 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23425 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23426 MVLI.VarComponents.back().push_back(MC);
23427 }
23428
23429 if (MVLI.ProcessedVarList.empty())
23430 return nullptr;
23431
23432 return OMPHasDeviceAddrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23433 MVLI.VarBaseDeclarations,
23434 MVLI.VarComponents);
23435 }
23436
ActOnOpenMPAllocateClause(Expr * Allocator,ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation ColonLoc,SourceLocation LParenLoc,SourceLocation EndLoc)23437 OMPClause *Sema::ActOnOpenMPAllocateClause(
23438 Expr *Allocator, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
23439 SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
23440 if (Allocator) {
23441 // OpenMP [2.11.4 allocate Clause, Description]
23442 // allocator is an expression of omp_allocator_handle_t type.
23443 if (!findOMPAllocatorHandleT(*this, Allocator->getExprLoc(), DSAStack))
23444 return nullptr;
23445
23446 ExprResult AllocatorRes = DefaultLvalueConversion(Allocator);
23447 if (AllocatorRes.isInvalid())
23448 return nullptr;
23449 AllocatorRes = PerformImplicitConversion(AllocatorRes.get(),
23450 DSAStack->getOMPAllocatorHandleT(),
23451 Sema::AA_Initializing,
23452 /*AllowExplicit=*/true);
23453 if (AllocatorRes.isInvalid())
23454 return nullptr;
23455 Allocator = AllocatorRes.get();
23456 } else {
23457 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
23458 // allocate clauses that appear on a target construct or on constructs in a
23459 // target region must specify an allocator expression unless a requires
23460 // directive with the dynamic_allocators clause is present in the same
23461 // compilation unit.
23462 if (LangOpts.OpenMPIsDevice &&
23463 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
23464 targetDiag(StartLoc, diag::err_expected_allocator_expression);
23465 }
23466 // Analyze and build list of variables.
23467 SmallVector<Expr *, 8> Vars;
23468 for (Expr *RefExpr : VarList) {
23469 assert(RefExpr && "NULL expr in OpenMP private clause.");
23470 SourceLocation ELoc;
23471 SourceRange ERange;
23472 Expr *SimpleRefExpr = RefExpr;
23473 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23474 if (Res.second) {
23475 // It will be analyzed later.
23476 Vars.push_back(RefExpr);
23477 }
23478 ValueDecl *D = Res.first;
23479 if (!D)
23480 continue;
23481
23482 auto *VD = dyn_cast<VarDecl>(D);
23483 DeclRefExpr *Ref = nullptr;
23484 if (!VD && !CurContext->isDependentContext())
23485 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
23486 Vars.push_back((VD || CurContext->isDependentContext())
23487 ? RefExpr->IgnoreParens()
23488 : Ref);
23489 }
23490
23491 if (Vars.empty())
23492 return nullptr;
23493
23494 if (Allocator)
23495 DSAStack->addInnerAllocatorExpr(Allocator);
23496 return OMPAllocateClause::Create(Context, StartLoc, LParenLoc, Allocator,
23497 ColonLoc, EndLoc, Vars);
23498 }
23499
ActOnOpenMPNontemporalClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)23500 OMPClause *Sema::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList,
23501 SourceLocation StartLoc,
23502 SourceLocation LParenLoc,
23503 SourceLocation EndLoc) {
23504 SmallVector<Expr *, 8> Vars;
23505 for (Expr *RefExpr : VarList) {
23506 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23507 SourceLocation ELoc;
23508 SourceRange ERange;
23509 Expr *SimpleRefExpr = RefExpr;
23510 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23511 if (Res.second)
23512 // It will be analyzed later.
23513 Vars.push_back(RefExpr);
23514 ValueDecl *D = Res.first;
23515 if (!D)
23516 continue;
23517
23518 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
23519 // A list-item cannot appear in more than one nontemporal clause.
23520 if (const Expr *PrevRef =
23521 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
23522 Diag(ELoc, diag::err_omp_used_in_clause_twice)
23523 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
23524 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23525 << getOpenMPClauseName(OMPC_nontemporal);
23526 continue;
23527 }
23528
23529 Vars.push_back(RefExpr);
23530 }
23531
23532 if (Vars.empty())
23533 return nullptr;
23534
23535 return OMPNontemporalClause::Create(Context, StartLoc, LParenLoc, EndLoc,
23536 Vars);
23537 }
23538
ActOnOpenMPInclusiveClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)23539 OMPClause *Sema::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
23540 SourceLocation StartLoc,
23541 SourceLocation LParenLoc,
23542 SourceLocation EndLoc) {
23543 SmallVector<Expr *, 8> Vars;
23544 for (Expr *RefExpr : VarList) {
23545 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23546 SourceLocation ELoc;
23547 SourceRange ERange;
23548 Expr *SimpleRefExpr = RefExpr;
23549 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23550 /*AllowArraySection=*/true);
23551 if (Res.second)
23552 // It will be analyzed later.
23553 Vars.push_back(RefExpr);
23554 ValueDecl *D = Res.first;
23555 if (!D)
23556 continue;
23557
23558 const DSAStackTy::DSAVarData DVar =
23559 DSAStack->getTopDSA(D, /*FromParent=*/true);
23560 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23561 // A list item that appears in the inclusive or exclusive clause must appear
23562 // in a reduction clause with the inscan modifier on the enclosing
23563 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23564 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
23565 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23566 << RefExpr->getSourceRange();
23567
23568 if (DSAStack->getParentDirective() != OMPD_unknown)
23569 DSAStack->markDeclAsUsedInScanDirective(D);
23570 Vars.push_back(RefExpr);
23571 }
23572
23573 if (Vars.empty())
23574 return nullptr;
23575
23576 return OMPInclusiveClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
23577 }
23578
ActOnOpenMPExclusiveClause(ArrayRef<Expr * > VarList,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)23579 OMPClause *Sema::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
23580 SourceLocation StartLoc,
23581 SourceLocation LParenLoc,
23582 SourceLocation EndLoc) {
23583 SmallVector<Expr *, 8> Vars;
23584 for (Expr *RefExpr : VarList) {
23585 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23586 SourceLocation ELoc;
23587 SourceRange ERange;
23588 Expr *SimpleRefExpr = RefExpr;
23589 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23590 /*AllowArraySection=*/true);
23591 if (Res.second)
23592 // It will be analyzed later.
23593 Vars.push_back(RefExpr);
23594 ValueDecl *D = Res.first;
23595 if (!D)
23596 continue;
23597
23598 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
23599 DSAStackTy::DSAVarData DVar;
23600 if (ParentDirective != OMPD_unknown)
23601 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
23602 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23603 // A list item that appears in the inclusive or exclusive clause must appear
23604 // in a reduction clause with the inscan modifier on the enclosing
23605 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23606 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
23607 DVar.Modifier != OMPC_REDUCTION_inscan) {
23608 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23609 << RefExpr->getSourceRange();
23610 } else {
23611 DSAStack->markDeclAsUsedInScanDirective(D);
23612 }
23613 Vars.push_back(RefExpr);
23614 }
23615
23616 if (Vars.empty())
23617 return nullptr;
23618
23619 return OMPExclusiveClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
23620 }
23621
23622 /// Tries to find omp_alloctrait_t type.
findOMPAlloctraitT(Sema & S,SourceLocation Loc,DSAStackTy * Stack)23623 static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
23624 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
23625 if (!OMPAlloctraitT.isNull())
23626 return true;
23627 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
23628 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
23629 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23630 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
23631 return false;
23632 }
23633 Stack->setOMPAlloctraitT(PT.get());
23634 return true;
23635 }
23636
ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc,ArrayRef<UsesAllocatorsData> Data)23637 OMPClause *Sema::ActOnOpenMPUsesAllocatorClause(
23638 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
23639 ArrayRef<UsesAllocatorsData> Data) {
23640 // OpenMP [2.12.5, target Construct]
23641 // allocator is an identifier of omp_allocator_handle_t type.
23642 if (!findOMPAllocatorHandleT(*this, StartLoc, DSAStack))
23643 return nullptr;
23644 // OpenMP [2.12.5, target Construct]
23645 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
23646 if (llvm::any_of(
23647 Data,
23648 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
23649 !findOMPAlloctraitT(*this, StartLoc, DSAStack))
23650 return nullptr;
23651 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
23652 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
23653 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
23654 StringRef Allocator =
23655 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
23656 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
23657 PredefinedAllocators.insert(LookupSingleName(
23658 TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
23659 }
23660
23661 SmallVector<OMPUsesAllocatorsClause::Data, 4> NewData;
23662 for (const UsesAllocatorsData &D : Data) {
23663 Expr *AllocatorExpr = nullptr;
23664 // Check allocator expression.
23665 if (D.Allocator->isTypeDependent()) {
23666 AllocatorExpr = D.Allocator;
23667 } else {
23668 // Traits were specified - need to assign new allocator to the specified
23669 // allocator, so it must be an lvalue.
23670 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
23671 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
23672 bool IsPredefinedAllocator = false;
23673 if (DRE) {
23674 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
23675 getAllocatorKind(*this, DSAStack, AllocatorExpr);
23676 IsPredefinedAllocator =
23677 AllocatorTy !=
23678 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
23679 }
23680 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
23681 QualType AllocatorExprType = AllocatorExpr->getType();
23682 bool IsTypeCompatible = IsPredefinedAllocator;
23683 IsTypeCompatible = IsTypeCompatible ||
23684 Context.hasSameUnqualifiedType(AllocatorExprType,
23685 OMPAllocatorHandleT);
23686 IsTypeCompatible =
23687 IsTypeCompatible ||
23688 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
23689 bool IsNonConstantLValue =
23690 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
23691 if (!DRE || !IsTypeCompatible ||
23692 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
23693 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
23694 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
23695 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
23696 continue;
23697 }
23698 // OpenMP [2.12.5, target Construct]
23699 // Predefined allocators appearing in a uses_allocators clause cannot have
23700 // traits specified.
23701 if (IsPredefinedAllocator && D.AllocatorTraits) {
23702 Diag(D.AllocatorTraits->getExprLoc(),
23703 diag::err_omp_predefined_allocator_with_traits)
23704 << D.AllocatorTraits->getSourceRange();
23705 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
23706 << cast<NamedDecl>(DRE->getDecl())->getName()
23707 << D.Allocator->getSourceRange();
23708 continue;
23709 }
23710 // OpenMP [2.12.5, target Construct]
23711 // Non-predefined allocators appearing in a uses_allocators clause must
23712 // have traits specified.
23713 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
23714 Diag(D.Allocator->getExprLoc(),
23715 diag::err_omp_nonpredefined_allocator_without_traits);
23716 continue;
23717 }
23718 // No allocator traits - just convert it to rvalue.
23719 if (!D.AllocatorTraits)
23720 AllocatorExpr = DefaultLvalueConversion(AllocatorExpr).get();
23721 DSAStack->addUsesAllocatorsDecl(
23722 DRE->getDecl(),
23723 IsPredefinedAllocator
23724 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
23725 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
23726 }
23727 Expr *AllocatorTraitsExpr = nullptr;
23728 if (D.AllocatorTraits) {
23729 if (D.AllocatorTraits->isTypeDependent()) {
23730 AllocatorTraitsExpr = D.AllocatorTraits;
23731 } else {
23732 // OpenMP [2.12.5, target Construct]
23733 // Arrays that contain allocator traits that appear in a uses_allocators
23734 // clause must be constant arrays, have constant values and be defined
23735 // in the same scope as the construct in which the clause appears.
23736 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
23737 // Check that traits expr is a constant array.
23738 QualType TraitTy;
23739 if (const ArrayType *Ty =
23740 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
23741 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
23742 TraitTy = ConstArrayTy->getElementType();
23743 if (TraitTy.isNull() ||
23744 !(Context.hasSameUnqualifiedType(TraitTy,
23745 DSAStack->getOMPAlloctraitT()) ||
23746 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
23747 /*CompareUnqualified=*/true))) {
23748 Diag(D.AllocatorTraits->getExprLoc(),
23749 diag::err_omp_expected_array_alloctraits)
23750 << AllocatorTraitsExpr->getType();
23751 continue;
23752 }
23753 // Do not map by default allocator traits if it is a standalone
23754 // variable.
23755 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
23756 DSAStack->addUsesAllocatorsDecl(
23757 DRE->getDecl(),
23758 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
23759 }
23760 }
23761 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
23762 NewD.Allocator = AllocatorExpr;
23763 NewD.AllocatorTraits = AllocatorTraitsExpr;
23764 NewD.LParenLoc = D.LParenLoc;
23765 NewD.RParenLoc = D.RParenLoc;
23766 }
23767 return OMPUsesAllocatorsClause::Create(Context, StartLoc, LParenLoc, EndLoc,
23768 NewData);
23769 }
23770
ActOnOpenMPAffinityClause(SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation ColonLoc,SourceLocation EndLoc,Expr * Modifier,ArrayRef<Expr * > Locators)23771 OMPClause *Sema::ActOnOpenMPAffinityClause(
23772 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
23773 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
23774 SmallVector<Expr *, 8> Vars;
23775 for (Expr *RefExpr : Locators) {
23776 assert(RefExpr && "NULL expr in OpenMP shared clause.");
23777 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
23778 // It will be analyzed later.
23779 Vars.push_back(RefExpr);
23780 continue;
23781 }
23782
23783 SourceLocation ELoc = RefExpr->getExprLoc();
23784 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
23785
23786 if (!SimpleExpr->isLValue()) {
23787 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23788 << 1 << 0 << RefExpr->getSourceRange();
23789 continue;
23790 }
23791
23792 ExprResult Res;
23793 {
23794 Sema::TentativeAnalysisScope Trap(*this);
23795 Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
23796 }
23797 if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr) &&
23798 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
23799 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23800 << 1 << 0 << RefExpr->getSourceRange();
23801 continue;
23802 }
23803 Vars.push_back(SimpleExpr);
23804 }
23805
23806 return OMPAffinityClause::Create(Context, StartLoc, LParenLoc, ColonLoc,
23807 EndLoc, Modifier, Vars);
23808 }
23809
ActOnOpenMPBindClause(OpenMPBindClauseKind Kind,SourceLocation KindLoc,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)23810 OMPClause *Sema::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind,
23811 SourceLocation KindLoc,
23812 SourceLocation StartLoc,
23813 SourceLocation LParenLoc,
23814 SourceLocation EndLoc) {
23815 if (Kind == OMPC_BIND_unknown) {
23816 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23817 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
23818 /*Last=*/unsigned(OMPC_BIND_unknown))
23819 << getOpenMPClauseName(OMPC_bind);
23820 return nullptr;
23821 }
23822
23823 return OMPBindClause::Create(Context, Kind, KindLoc, StartLoc, LParenLoc,
23824 EndLoc);
23825 }
23826
ActOnOpenMPXDynCGroupMemClause(Expr * Size,SourceLocation StartLoc,SourceLocation LParenLoc,SourceLocation EndLoc)23827 OMPClause *Sema::ActOnOpenMPXDynCGroupMemClause(Expr *Size,
23828 SourceLocation StartLoc,
23829 SourceLocation LParenLoc,
23830 SourceLocation EndLoc) {
23831 Expr *ValExpr = Size;
23832 Stmt *HelperValStmt = nullptr;
23833
23834 // OpenMP [2.5, Restrictions]
23835 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
23836 // value.
23837 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_ompx_dyn_cgroup_mem,
23838 /*StrictlyPositive=*/false))
23839 return nullptr;
23840
23841 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23842 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
23843 DKind, OMPC_ompx_dyn_cgroup_mem, LangOpts.OpenMP);
23844 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
23845 ValExpr = MakeFullExpr(ValExpr).get();
23846 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23847 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
23848 HelperValStmt = buildPreInits(Context, Captures);
23849 }
23850
23851 return new (Context) OMPXDynCGroupMemClause(
23852 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23853 }
23854