clang 19.0.0git
SemaOpenMP.cpp
Go to the documentation of this file.
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"
18#include "clang/AST/Decl.h"
19#include "clang/AST/DeclCXX.h"
22#include "clang/AST/StmtCXX.h"
32#include "clang/Sema/Lookup.h"
34#include "clang/Sema/Scope.h"
37#include "llvm/ADT/IndexedMap.h"
38#include "llvm/ADT/PointerEmbeddedInt.h"
39#include "llvm/ADT/STLExtras.h"
40#include "llvm/ADT/SmallSet.h"
41#include "llvm/ADT/StringExtras.h"
42#include "llvm/Frontend/OpenMP/OMPAssume.h"
43#include "llvm/Frontend/OpenMP/OMPConstants.h"
44#include <optional>
45#include <set>
46
47using namespace clang;
48using namespace llvm::omp;
49
50//===----------------------------------------------------------------------===//
51// Stack of data-sharing attributes for variables
52//===----------------------------------------------------------------------===//
53
55 Sema &SemaRef, Expr *E,
57 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
58
59namespace {
60/// Default data sharing attributes, which can be applied to directive.
61enum DefaultDataSharingAttributes {
62 DSA_unspecified = 0, /// Data sharing attribute not specified.
63 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
64 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
65 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
66 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
67};
68
69/// Stack for tracking declarations used in OpenMP directives and
70/// clauses and their data-sharing attributes.
71class DSAStackTy {
72public:
73 struct DSAVarData {
74 OpenMPDirectiveKind DKind = OMPD_unknown;
75 OpenMPClauseKind CKind = OMPC_unknown;
76 unsigned Modifier = 0;
77 const Expr *RefExpr = nullptr;
78 DeclRefExpr *PrivateCopy = nullptr;
79 SourceLocation ImplicitDSALoc;
80 bool AppliedToPointee = false;
81 DSAVarData() = default;
82 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
83 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
84 SourceLocation ImplicitDSALoc, unsigned Modifier,
85 bool AppliedToPointee)
86 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
87 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
88 AppliedToPointee(AppliedToPointee) {}
89 };
90 using OperatorOffsetTy =
92 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
93 /// Kind of the declaration used in the uses_allocators clauses.
94 enum class UsesAllocatorsDeclKind {
95 /// Predefined allocator
96 PredefinedAllocator,
97 /// User-defined allocator
98 UserDefinedAllocator,
99 /// The declaration that represent allocator trait
100 AllocatorTrait,
101 };
102
103private:
104 struct DSAInfo {
105 OpenMPClauseKind Attributes = OMPC_unknown;
106 unsigned Modifier = 0;
107 /// Pointer to a reference expression and a flag which shows that the
108 /// variable is marked as lastprivate(true) or not (false).
109 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
110 DeclRefExpr *PrivateCopy = nullptr;
111 /// true if the attribute is applied to the pointee, not the variable
112 /// itself.
113 bool AppliedToPointee = false;
114 };
115 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
116 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
117 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
118 using LoopControlVariablesMapTy =
119 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
120 /// Struct that associates a component with the clause kind where they are
121 /// found.
122 struct MappedExprComponentTy {
124 OpenMPClauseKind Kind = OMPC_unknown;
125 };
126 using MappedExprComponentsTy =
127 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
128 using CriticalsWithHintsTy =
129 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
130 struct ReductionData {
131 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
132 SourceRange ReductionRange;
133 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
134 ReductionData() = default;
135 void set(BinaryOperatorKind BO, SourceRange RR) {
136 ReductionRange = RR;
137 ReductionOp = BO;
138 }
139 void set(const Expr *RefExpr, SourceRange RR) {
140 ReductionRange = RR;
141 ReductionOp = RefExpr;
142 }
143 };
144 using DeclReductionMapTy =
145 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
146 struct DefaultmapInfo {
147 OpenMPDefaultmapClauseModifier ImplicitBehavior =
149 SourceLocation SLoc;
150 DefaultmapInfo() = default;
152 : ImplicitBehavior(M), SLoc(Loc) {}
153 };
154
155 struct SharingMapTy {
156 DeclSAMapTy SharingMap;
157 DeclReductionMapTy ReductionMap;
158 UsedRefMapTy AlignedMap;
159 UsedRefMapTy NontemporalMap;
160 MappedExprComponentsTy MappedExprComponents;
161 LoopControlVariablesMapTy LCVMap;
162 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
163 SourceLocation DefaultAttrLoc;
164 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1];
165 OpenMPDirectiveKind Directive = OMPD_unknown;
166 /// GenericLoopDirective with bind clause is mapped to other directives,
167 /// like for, distribute and simd. Presently, set MappedDirective to
168 /// OMPLoop. This may also be used in a similar way for other constructs.
169 OpenMPDirectiveKind MappedDirective = OMPD_unknown;
170 DeclarationNameInfo DirectiveName;
171 Scope *CurScope = nullptr;
172 DeclContext *Context = nullptr;
173 SourceLocation ConstructLoc;
174 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
175 /// get the data (loop counters etc.) about enclosing loop-based construct.
176 /// This data is required during codegen.
177 DoacrossClauseMapTy DoacrossDepends;
178 /// First argument (Expr *) contains optional argument of the
179 /// 'ordered' clause, the second one is true if the regions has 'ordered'
180 /// clause, false otherwise.
181 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
182 bool RegionHasOrderConcurrent = false;
183 unsigned AssociatedLoops = 1;
184 bool HasMutipleLoops = false;
185 const Decl *PossiblyLoopCounter = nullptr;
186 bool NowaitRegion = false;
187 bool UntiedRegion = false;
188 bool CancelRegion = false;
189 bool LoopStart = false;
190 bool BodyComplete = false;
191 SourceLocation PrevScanLocation;
192 SourceLocation PrevOrderedLocation;
193 SourceLocation InnerTeamsRegionLoc;
194 /// Reference to the taskgroup task_reduction reference expression.
195 Expr *TaskgroupReductionRef = nullptr;
196 llvm::DenseSet<QualType> MappedClassesQualTypes;
197 SmallVector<Expr *, 4> InnerUsedAllocators;
198 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
199 /// List of globals marked as declare target link in this target region
200 /// (isOpenMPTargetExecutionDirective(Directive) == true).
201 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
202 /// List of decls used in inclusive/exclusive clauses of the scan directive.
203 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
204 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
205 UsesAllocatorsDecls;
206 /// Data is required on creating capture fields for implicit
207 /// default first|private clause.
208 struct ImplicitDefaultFDInfoTy {
209 /// Field decl.
210 const FieldDecl *FD = nullptr;
211 /// Nesting stack level
212 size_t StackLevel = 0;
213 /// Capture variable decl.
214 VarDecl *VD = nullptr;
215 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
216 VarDecl *VD)
217 : FD(FD), StackLevel(StackLevel), VD(VD) {}
218 };
219 /// List of captured fields
221 ImplicitDefaultFirstprivateFDs;
222 Expr *DeclareMapperVar = nullptr;
223 SmallVector<VarDecl *, 16> IteratorVarDecls;
224 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
225 Scope *CurScope, SourceLocation Loc)
226 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
227 ConstructLoc(Loc) {}
228 SharingMapTy() = default;
229 };
230
231 using StackTy = SmallVector<SharingMapTy, 4>;
232
233 /// Stack of used declaration and their data-sharing attributes.
234 DeclSAMapTy Threadprivates;
235 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
237 /// true, if check for DSA must be from parent directive, false, if
238 /// from current directive.
239 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
240 Sema &SemaRef;
241 bool ForceCapturing = false;
242 /// true if all the variables in the target executable directives must be
243 /// captured by reference.
244 bool ForceCaptureByReferenceInTargetExecutable = false;
245 CriticalsWithHintsTy Criticals;
246 unsigned IgnoredStackElements = 0;
247
248 /// Iterators over the stack iterate in order from innermost to outermost
249 /// directive.
250 using const_iterator = StackTy::const_reverse_iterator;
251 const_iterator begin() const {
252 return Stack.empty() ? const_iterator()
253 : Stack.back().first.rbegin() + IgnoredStackElements;
254 }
255 const_iterator end() const {
256 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
257 }
258 using iterator = StackTy::reverse_iterator;
259 iterator begin() {
260 return Stack.empty() ? iterator()
261 : Stack.back().first.rbegin() + IgnoredStackElements;
262 }
263 iterator end() {
264 return Stack.empty() ? iterator() : Stack.back().first.rend();
265 }
266
267 // Convenience operations to get at the elements of the stack.
268
269 bool isStackEmpty() const {
270 return Stack.empty() ||
271 Stack.back().second != CurrentNonCapturingFunctionScope ||
272 Stack.back().first.size() <= IgnoredStackElements;
273 }
274 size_t getStackSize() const {
275 return isStackEmpty() ? 0
276 : Stack.back().first.size() - IgnoredStackElements;
277 }
278
279 SharingMapTy *getTopOfStackOrNull() {
280 size_t Size = getStackSize();
281 if (Size == 0)
282 return nullptr;
283 return &Stack.back().first[Size - 1];
284 }
285 const SharingMapTy *getTopOfStackOrNull() const {
286 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
287 }
288 SharingMapTy &getTopOfStack() {
289 assert(!isStackEmpty() && "no current directive");
290 return *getTopOfStackOrNull();
291 }
292 const SharingMapTy &getTopOfStack() const {
293 return const_cast<DSAStackTy &>(*this).getTopOfStack();
294 }
295
296 SharingMapTy *getSecondOnStackOrNull() {
297 size_t Size = getStackSize();
298 if (Size <= 1)
299 return nullptr;
300 return &Stack.back().first[Size - 2];
301 }
302 const SharingMapTy *getSecondOnStackOrNull() const {
303 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
304 }
305
306 /// Get the stack element at a certain level (previously returned by
307 /// \c getNestingLevel).
308 ///
309 /// Note that nesting levels count from outermost to innermost, and this is
310 /// the reverse of our iteration order where new inner levels are pushed at
311 /// the front of the stack.
312 SharingMapTy &getStackElemAtLevel(unsigned Level) {
313 assert(Level < getStackSize() && "no such stack element");
314 return Stack.back().first[Level];
315 }
316 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
317 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
318 }
319
320 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
321
322 /// Checks if the variable is a local for OpenMP region.
323 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
324
325 /// Vector of previously declared requires directives
327 /// omp_allocator_handle_t type.
328 QualType OMPAllocatorHandleT;
329 /// omp_depend_t type.
330 QualType OMPDependT;
331 /// omp_event_handle_t type.
332 QualType OMPEventHandleT;
333 /// omp_alloctrait_t type.
334 QualType OMPAlloctraitT;
335 /// Expression for the predefined allocators.
336 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
337 nullptr};
338 /// Vector of previously encountered target directives
339 SmallVector<SourceLocation, 2> TargetLocations;
340 SourceLocation AtomicLocation;
341 /// Vector of declare variant construct traits.
343
344public:
345 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
346
347 /// Sets omp_allocator_handle_t type.
348 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
349 /// Gets omp_allocator_handle_t type.
350 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
351 /// Sets omp_alloctrait_t type.
352 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
353 /// Gets omp_alloctrait_t type.
354 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
355 /// Sets the given default allocator.
356 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
357 Expr *Allocator) {
358 OMPPredefinedAllocators[AllocatorKind] = Allocator;
359 }
360 /// Returns the specified default allocator.
361 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
362 return OMPPredefinedAllocators[AllocatorKind];
363 }
364 /// Sets omp_depend_t type.
365 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
366 /// Gets omp_depend_t type.
367 QualType getOMPDependT() const { return OMPDependT; }
368
369 /// Sets omp_event_handle_t type.
370 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
371 /// Gets omp_event_handle_t type.
372 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
373
374 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
375 OpenMPClauseKind getClauseParsingMode() const {
376 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
377 return ClauseKindMode;
378 }
379 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
380
381 bool isBodyComplete() const {
382 const SharingMapTy *Top = getTopOfStackOrNull();
383 return Top && Top->BodyComplete;
384 }
385 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
386
387 bool isForceVarCapturing() const { return ForceCapturing; }
388 void setForceVarCapturing(bool V) { ForceCapturing = V; }
389
390 void setForceCaptureByReferenceInTargetExecutable(bool V) {
391 ForceCaptureByReferenceInTargetExecutable = V;
392 }
393 bool isForceCaptureByReferenceInTargetExecutable() const {
394 return ForceCaptureByReferenceInTargetExecutable;
395 }
396
397 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
398 Scope *CurScope, SourceLocation Loc) {
399 assert(!IgnoredStackElements &&
400 "cannot change stack while ignoring elements");
401 if (Stack.empty() ||
402 Stack.back().second != CurrentNonCapturingFunctionScope)
403 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
404 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
405 Stack.back().first.back().DefaultAttrLoc = Loc;
406 }
407
408 void pop() {
409 assert(!IgnoredStackElements &&
410 "cannot change stack while ignoring elements");
411 assert(!Stack.back().first.empty() &&
412 "Data-sharing attributes stack is empty!");
413 Stack.back().first.pop_back();
414 }
415
416 /// RAII object to temporarily leave the scope of a directive when we want to
417 /// logically operate in its parent.
418 class ParentDirectiveScope {
419 DSAStackTy &Self;
420 bool Active;
421
422 public:
423 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
424 : Self(Self), Active(false) {
425 if (Activate)
426 enable();
427 }
428 ~ParentDirectiveScope() { disable(); }
429 void disable() {
430 if (Active) {
431 --Self.IgnoredStackElements;
432 Active = false;
433 }
434 }
435 void enable() {
436 if (!Active) {
437 ++Self.IgnoredStackElements;
438 Active = true;
439 }
440 }
441 };
442
443 /// Marks that we're started loop parsing.
444 void loopInit() {
445 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
446 "Expected loop-based directive.");
447 getTopOfStack().LoopStart = true;
448 }
449 /// Start capturing of the variables in the loop context.
450 void loopStart() {
451 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
452 "Expected loop-based directive.");
453 getTopOfStack().LoopStart = false;
454 }
455 /// true, if variables are captured, false otherwise.
456 bool isLoopStarted() const {
457 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
458 "Expected loop-based directive.");
459 return !getTopOfStack().LoopStart;
460 }
461 /// Marks (or clears) declaration as possibly loop counter.
462 void resetPossibleLoopCounter(const Decl *D = nullptr) {
463 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
464 }
465 /// Gets the possible loop counter decl.
466 const Decl *getPossiblyLoopCunter() const {
467 return getTopOfStack().PossiblyLoopCounter;
468 }
469 /// Start new OpenMP region stack in new non-capturing function.
470 void pushFunction() {
471 assert(!IgnoredStackElements &&
472 "cannot change stack while ignoring elements");
473 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
474 assert(!isa<CapturingScopeInfo>(CurFnScope));
475 CurrentNonCapturingFunctionScope = CurFnScope;
476 }
477 /// Pop region stack for non-capturing function.
478 void popFunction(const FunctionScopeInfo *OldFSI) {
479 assert(!IgnoredStackElements &&
480 "cannot change stack while ignoring elements");
481 if (!Stack.empty() && Stack.back().second == OldFSI) {
482 assert(Stack.back().first.empty());
483 Stack.pop_back();
484 }
485 CurrentNonCapturingFunctionScope = nullptr;
486 for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
487 if (!isa<CapturingScopeInfo>(FSI)) {
488 CurrentNonCapturingFunctionScope = FSI;
489 break;
490 }
491 }
492 }
493
494 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
495 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
496 }
497 const std::pair<const OMPCriticalDirective *, llvm::APSInt>
498 getCriticalWithHint(const DeclarationNameInfo &Name) const {
499 auto I = Criticals.find(Name.getAsString());
500 if (I != Criticals.end())
501 return I->second;
502 return std::make_pair(nullptr, llvm::APSInt());
503 }
504 /// If 'aligned' declaration for given variable \a D was not seen yet,
505 /// add it and return NULL; otherwise return previous occurrence's expression
506 /// for diagnostics.
507 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
508 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
509 /// add it and return NULL; otherwise return previous occurrence's expression
510 /// for diagnostics.
511 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
512
513 /// Register specified variable as loop control variable.
514 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
515 /// Check if the specified variable is a loop control variable for
516 /// current 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 isLoopControlVariable(const ValueDecl *D) const;
520 /// Check if the specified variable is a loop control variable for
521 /// parent 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 isParentLoopControlVariable(const ValueDecl *D) const;
525 /// Check if the specified variable is a loop control variable for
526 /// current region.
527 /// \return The index of the loop control variable in the list of associated
528 /// for-loops (from outer to inner).
529 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
530 unsigned Level) const;
531 /// Get the loop control variable for the I-th loop (or nullptr) in
532 /// parent directive.
533 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
534
535 /// Marks the specified decl \p D as used in scan directive.
536 void markDeclAsUsedInScanDirective(ValueDecl *D) {
537 if (SharingMapTy *Stack = getSecondOnStackOrNull())
538 Stack->UsedInScanDirective.insert(D);
539 }
540
541 /// Checks if the specified declaration was used in the inner scan directive.
542 bool isUsedInScanDirective(ValueDecl *D) const {
543 if (const SharingMapTy *Stack = getTopOfStackOrNull())
544 return Stack->UsedInScanDirective.contains(D);
545 return false;
546 }
547
548 /// Adds explicit data sharing attribute to the specified declaration.
549 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
550 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
551 bool AppliedToPointee = false);
552
553 /// Adds additional information for the reduction items with the reduction id
554 /// represented as an operator.
555 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
557 /// Adds additional information for the reduction items with the reduction id
558 /// represented as reduction identifier.
559 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
560 const Expr *ReductionRef);
561 /// Returns the location and reduction operation from the innermost parent
562 /// region for the given \p D.
563 const DSAVarData
564 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
566 Expr *&TaskgroupDescriptor) const;
567 /// Returns the location and reduction operation from the innermost parent
568 /// region for the given \p D.
569 const DSAVarData
570 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
571 const Expr *&ReductionRef,
572 Expr *&TaskgroupDescriptor) const;
573 /// Return reduction reference expression for the current taskgroup or
574 /// parallel/worksharing directives with task reductions.
575 Expr *getTaskgroupReductionRef() const {
576 assert((getTopOfStack().Directive == OMPD_taskgroup ||
577 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
578 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
579 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
580 "taskgroup reference expression requested for non taskgroup or "
581 "parallel/worksharing directive.");
582 return getTopOfStack().TaskgroupReductionRef;
583 }
584 /// Checks if the given \p VD declaration is actually a taskgroup reduction
585 /// descriptor variable at the \p Level of OpenMP regions.
586 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
587 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
588 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
589 ->getDecl() == VD;
590 }
591
592 /// Returns data sharing attributes from top of the stack for the
593 /// specified declaration.
594 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
595 /// Returns data-sharing attributes for the specified declaration.
596 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
597 /// Returns data-sharing attributes for the specified declaration.
598 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
599 /// Checks if the specified variables has data-sharing attributes which
600 /// match specified \a CPred predicate in any directive which matches \a DPred
601 /// predicate.
602 const DSAVarData
603 hasDSA(ValueDecl *D,
604 const llvm::function_ref<bool(OpenMPClauseKind, bool,
605 DefaultDataSharingAttributes)>
606 CPred,
607 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
608 bool FromParent) const;
609 /// Checks if the specified variables has data-sharing attributes which
610 /// match specified \a CPred predicate in any innermost directive which
611 /// matches \a DPred predicate.
612 const DSAVarData
613 hasInnermostDSA(ValueDecl *D,
614 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
615 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
616 bool FromParent) const;
617 /// Checks if the specified variables has explicit data-sharing
618 /// attributes which match specified \a CPred predicate at the specified
619 /// OpenMP region.
620 bool
621 hasExplicitDSA(const ValueDecl *D,
622 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
623 unsigned Level, bool NotLastprivate = false) const;
624
625 /// Returns true if the directive at level \Level matches in the
626 /// specified \a DPred predicate.
627 bool hasExplicitDirective(
628 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
629 unsigned Level) const;
630
631 /// Finds a directive which matches specified \a DPred predicate.
632 bool hasDirective(
633 const llvm::function_ref<bool(
635 DPred,
636 bool FromParent) const;
637
638 /// Returns currently analyzed directive.
639 OpenMPDirectiveKind getCurrentDirective() const {
640 const SharingMapTy *Top = getTopOfStackOrNull();
641 return Top ? Top->Directive : OMPD_unknown;
642 }
643 OpenMPDirectiveKind getMappedDirective() const {
644 const SharingMapTy *Top = getTopOfStackOrNull();
645 return Top ? Top->MappedDirective : OMPD_unknown;
646 }
647 void setCurrentDirective(OpenMPDirectiveKind NewDK) {
648 SharingMapTy *Top = getTopOfStackOrNull();
649 assert(Top &&
650 "Before calling setCurrentDirective Top of Stack not to be NULL.");
651 // Store the old into MappedDirective & assign argument NewDK to Directive.
652 Top->Directive = NewDK;
653 }
654 void setMappedDirective(OpenMPDirectiveKind NewDK) {
655 SharingMapTy *Top = getTopOfStackOrNull();
656 assert(Top &&
657 "Before calling setMappedDirective Top of Stack not to be NULL.");
658 // Store the old into MappedDirective & assign argument NewDK to Directive.
659 Top->MappedDirective = NewDK;
660 }
661 /// Returns directive kind at specified level.
662 OpenMPDirectiveKind getDirective(unsigned Level) const {
663 assert(!isStackEmpty() && "No directive at specified level.");
664 return getStackElemAtLevel(Level).Directive;
665 }
666 /// Returns the capture region at the specified level.
667 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
668 unsigned OpenMPCaptureLevel) const {
670 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
671 return CaptureRegions[OpenMPCaptureLevel];
672 }
673 /// Returns parent directive.
674 OpenMPDirectiveKind getParentDirective() const {
675 const SharingMapTy *Parent = getSecondOnStackOrNull();
676 return Parent ? Parent->Directive : OMPD_unknown;
677 }
678
679 /// Add requires decl to internal vector
680 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
681
682 /// Checks if the defined 'requires' directive has specified type of clause.
683 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
684 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
685 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
686 return isa<ClauseType>(C);
687 });
688 });
689 }
690
691 /// Checks for a duplicate clause amongst previously declared requires
692 /// directives
693 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
694 bool IsDuplicate = false;
695 for (OMPClause *CNew : ClauseList) {
696 for (const OMPRequiresDecl *D : RequiresDecls) {
697 for (const OMPClause *CPrev : D->clauselists()) {
698 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
699 SemaRef.Diag(CNew->getBeginLoc(),
700 diag::err_omp_requires_clause_redeclaration)
701 << getOpenMPClauseName(CNew->getClauseKind());
702 SemaRef.Diag(CPrev->getBeginLoc(),
703 diag::note_omp_requires_previous_clause)
704 << getOpenMPClauseName(CPrev->getClauseKind());
705 IsDuplicate = true;
706 }
707 }
708 }
709 }
710 return IsDuplicate;
711 }
712
713 /// Add location of previously encountered target to internal vector
714 void addTargetDirLocation(SourceLocation LocStart) {
715 TargetLocations.push_back(LocStart);
716 }
717
718 /// Add location for the first encountered atomicc directive.
719 void addAtomicDirectiveLoc(SourceLocation Loc) {
720 if (AtomicLocation.isInvalid())
721 AtomicLocation = Loc;
722 }
723
724 /// Returns the location of the first encountered atomic directive in the
725 /// module.
726 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
727
728 // Return previously encountered target region locations.
729 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
730 return TargetLocations;
731 }
732
733 /// Set default data sharing attribute to none.
734 void setDefaultDSANone(SourceLocation Loc) {
735 getTopOfStack().DefaultAttr = DSA_none;
736 getTopOfStack().DefaultAttrLoc = Loc;
737 }
738 /// Set default data sharing attribute to shared.
739 void setDefaultDSAShared(SourceLocation Loc) {
740 getTopOfStack().DefaultAttr = DSA_shared;
741 getTopOfStack().DefaultAttrLoc = Loc;
742 }
743 /// Set default data sharing attribute to private.
744 void setDefaultDSAPrivate(SourceLocation Loc) {
745 getTopOfStack().DefaultAttr = DSA_private;
746 getTopOfStack().DefaultAttrLoc = Loc;
747 }
748 /// Set default data sharing attribute to firstprivate.
749 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
750 getTopOfStack().DefaultAttr = DSA_firstprivate;
751 getTopOfStack().DefaultAttrLoc = Loc;
752 }
753 /// Set default data mapping attribute to Modifier:Kind
754 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
756 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
757 DMI.ImplicitBehavior = M;
758 DMI.SLoc = Loc;
759 }
760 /// Check whether the implicit-behavior has been set in defaultmap
761 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
762 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
763 return getTopOfStack()
764 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
765 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
766 getTopOfStack()
767 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
768 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
769 getTopOfStack()
770 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
771 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
772 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
774 }
775
776 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
777 return ConstructTraits;
778 }
779 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
780 bool ScopeEntry) {
781 if (ScopeEntry)
782 ConstructTraits.append(Traits.begin(), Traits.end());
783 else
784 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
785 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
786 assert(Top == Trait && "Something left a trait on the stack!");
787 (void)Trait;
788 (void)Top;
789 }
790 }
791
792 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
793 return getStackSize() <= Level ? DSA_unspecified
794 : getStackElemAtLevel(Level).DefaultAttr;
795 }
796 DefaultDataSharingAttributes getDefaultDSA() const {
797 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
798 }
799 SourceLocation getDefaultDSALocation() const {
800 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
801 }
803 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
804 return isStackEmpty()
806 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
807 }
809 getDefaultmapModifierAtLevel(unsigned Level,
810 OpenMPDefaultmapClauseKind Kind) const {
811 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
812 }
813 bool isDefaultmapCapturedByRef(unsigned Level,
814 OpenMPDefaultmapClauseKind Kind) const {
816 getDefaultmapModifierAtLevel(Level, Kind);
817 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
818 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
819 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
820 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
821 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom);
822 }
823 return true;
824 }
825 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
827 switch (Kind) {
828 case OMPC_DEFAULTMAP_scalar:
829 case OMPC_DEFAULTMAP_pointer:
830 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
831 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
832 (M == OMPC_DEFAULTMAP_MODIFIER_default);
833 case OMPC_DEFAULTMAP_aggregate:
834 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
835 default:
836 break;
837 }
838 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
839 }
840 bool mustBeFirstprivateAtLevel(unsigned Level,
841 OpenMPDefaultmapClauseKind Kind) const {
843 getDefaultmapModifierAtLevel(Level, Kind);
844 return mustBeFirstprivateBase(M, Kind);
845 }
846 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
847 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
848 return mustBeFirstprivateBase(M, Kind);
849 }
850
851 /// Checks if the specified variable is a threadprivate.
852 bool isThreadPrivate(VarDecl *D) {
853 const DSAVarData DVar = getTopDSA(D, false);
854 return isOpenMPThreadPrivate(DVar.CKind);
855 }
856
857 /// Marks current region as ordered (it has an 'ordered' clause).
858 void setOrderedRegion(bool IsOrdered, const Expr *Param,
859 OMPOrderedClause *Clause) {
860 if (IsOrdered)
861 getTopOfStack().OrderedRegion.emplace(Param, Clause);
862 else
863 getTopOfStack().OrderedRegion.reset();
864 }
865 /// Returns true, if region is ordered (has associated 'ordered' clause),
866 /// false - otherwise.
867 bool isOrderedRegion() const {
868 if (const SharingMapTy *Top = getTopOfStackOrNull())
869 return Top->OrderedRegion.has_value();
870 return false;
871 }
872 /// Returns optional parameter for the ordered region.
873 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
874 if (const SharingMapTy *Top = getTopOfStackOrNull())
875 if (Top->OrderedRegion)
876 return *Top->OrderedRegion;
877 return std::make_pair(nullptr, nullptr);
878 }
879 /// Returns true, if parent region is ordered (has associated
880 /// 'ordered' clause), false - otherwise.
881 bool isParentOrderedRegion() const {
882 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
883 return Parent->OrderedRegion.has_value();
884 return false;
885 }
886 /// Returns optional parameter for the ordered region.
887 std::pair<const Expr *, OMPOrderedClause *>
888 getParentOrderedRegionParam() const {
889 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
890 if (Parent->OrderedRegion)
891 return *Parent->OrderedRegion;
892 return std::make_pair(nullptr, nullptr);
893 }
894 /// Marks current region as having an 'order' clause.
895 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
896 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
897 }
898 /// Returns true, if parent region is order (has associated
899 /// 'order' clause), false - otherwise.
900 bool isParentOrderConcurrent() const {
901 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
902 return Parent->RegionHasOrderConcurrent;
903 return false;
904 }
905 /// Marks current region as nowait (it has a 'nowait' clause).
906 void setNowaitRegion(bool IsNowait = true) {
907 getTopOfStack().NowaitRegion = IsNowait;
908 }
909 /// Returns true, if parent region is nowait (has associated
910 /// 'nowait' clause), false - otherwise.
911 bool isParentNowaitRegion() const {
912 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
913 return Parent->NowaitRegion;
914 return false;
915 }
916 /// Marks current region as untied (it has a 'untied' clause).
917 void setUntiedRegion(bool IsUntied = true) {
918 getTopOfStack().UntiedRegion = IsUntied;
919 }
920 /// Return true if current region is untied.
921 bool isUntiedRegion() const {
922 const SharingMapTy *Top = getTopOfStackOrNull();
923 return Top ? Top->UntiedRegion : false;
924 }
925 /// Marks parent region as cancel region.
926 void setParentCancelRegion(bool Cancel = true) {
927 if (SharingMapTy *Parent = getSecondOnStackOrNull())
928 Parent->CancelRegion |= Cancel;
929 }
930 /// Return true if current region has inner cancel construct.
931 bool isCancelRegion() const {
932 const SharingMapTy *Top = getTopOfStackOrNull();
933 return Top ? Top->CancelRegion : false;
934 }
935
936 /// Mark that parent region already has scan directive.
937 void setParentHasScanDirective(SourceLocation Loc) {
938 if (SharingMapTy *Parent = getSecondOnStackOrNull())
939 Parent->PrevScanLocation = Loc;
940 }
941 /// Return true if current region has inner cancel construct.
942 bool doesParentHasScanDirective() const {
943 const SharingMapTy *Top = getSecondOnStackOrNull();
944 return Top ? Top->PrevScanLocation.isValid() : false;
945 }
946 /// Return true if current region has inner cancel construct.
947 SourceLocation getParentScanDirectiveLoc() const {
948 const SharingMapTy *Top = getSecondOnStackOrNull();
949 return Top ? Top->PrevScanLocation : SourceLocation();
950 }
951 /// Mark that parent region already has ordered directive.
952 void setParentHasOrderedDirective(SourceLocation Loc) {
953 if (SharingMapTy *Parent = getSecondOnStackOrNull())
954 Parent->PrevOrderedLocation = Loc;
955 }
956 /// Return true if current region has inner ordered construct.
957 bool doesParentHasOrderedDirective() const {
958 const SharingMapTy *Top = getSecondOnStackOrNull();
959 return Top ? Top->PrevOrderedLocation.isValid() : false;
960 }
961 /// Returns the location of the previously specified ordered directive.
962 SourceLocation getParentOrderedDirectiveLoc() const {
963 const SharingMapTy *Top = getSecondOnStackOrNull();
964 return Top ? Top->PrevOrderedLocation : SourceLocation();
965 }
966
967 /// Set collapse value for the region.
968 void setAssociatedLoops(unsigned Val) {
969 getTopOfStack().AssociatedLoops = Val;
970 if (Val > 1)
971 getTopOfStack().HasMutipleLoops = true;
972 }
973 /// Return collapse value for region.
974 unsigned getAssociatedLoops() const {
975 const SharingMapTy *Top = getTopOfStackOrNull();
976 return Top ? Top->AssociatedLoops : 0;
977 }
978 /// Returns true if the construct is associated with multiple loops.
979 bool hasMutipleLoops() const {
980 const SharingMapTy *Top = getTopOfStackOrNull();
981 return Top ? Top->HasMutipleLoops : false;
982 }
983
984 /// Marks current target region as one with closely nested teams
985 /// region.
986 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
987 if (SharingMapTy *Parent = getSecondOnStackOrNull())
988 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
989 }
990 /// Returns true, if current region has closely nested teams region.
991 bool hasInnerTeamsRegion() const {
992 return getInnerTeamsRegionLoc().isValid();
993 }
994 /// Returns location of the nested teams region (if any).
995 SourceLocation getInnerTeamsRegionLoc() const {
996 const SharingMapTy *Top = getTopOfStackOrNull();
997 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
998 }
999
1000 Scope *getCurScope() const {
1001 const SharingMapTy *Top = getTopOfStackOrNull();
1002 return Top ? Top->CurScope : nullptr;
1003 }
1004 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
1005 SourceLocation getConstructLoc() const {
1006 const SharingMapTy *Top = getTopOfStackOrNull();
1007 return Top ? Top->ConstructLoc : SourceLocation();
1008 }
1009
1010 /// Do the check specified in \a Check to all component lists and return true
1011 /// if any issue is found.
1012 bool checkMappableExprComponentListsForDecl(
1013 const ValueDecl *VD, bool CurrentRegionOnly,
1014 const llvm::function_ref<
1017 Check) const {
1018 if (isStackEmpty())
1019 return false;
1020 auto SI = begin();
1021 auto SE = end();
1022
1023 if (SI == SE)
1024 return false;
1025
1026 if (CurrentRegionOnly)
1027 SE = std::next(SI);
1028 else
1029 std::advance(SI, 1);
1030
1031 for (; SI != SE; ++SI) {
1032 auto MI = SI->MappedExprComponents.find(VD);
1033 if (MI != SI->MappedExprComponents.end())
1035 MI->second.Components)
1036 if (Check(L, MI->second.Kind))
1037 return true;
1038 }
1039 return false;
1040 }
1041
1042 /// Do the check specified in \a Check to all component lists at a given level
1043 /// and return true if any issue is found.
1044 bool checkMappableExprComponentListsForDeclAtLevel(
1045 const ValueDecl *VD, unsigned Level,
1046 const llvm::function_ref<
1049 Check) const {
1050 if (getStackSize() <= Level)
1051 return false;
1052
1053 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1054 auto MI = StackElem.MappedExprComponents.find(VD);
1055 if (MI != StackElem.MappedExprComponents.end())
1057 MI->second.Components)
1058 if (Check(L, MI->second.Kind))
1059 return true;
1060 return false;
1061 }
1062
1063 /// Create a new mappable expression component list associated with a given
1064 /// declaration and initialize it with the provided list of components.
1065 void addMappableExpressionComponents(
1066 const ValueDecl *VD,
1068 OpenMPClauseKind WhereFoundClauseKind) {
1069 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1070 // Create new entry and append the new components there.
1071 MEC.Components.resize(MEC.Components.size() + 1);
1072 MEC.Components.back().append(Components.begin(), Components.end());
1073 MEC.Kind = WhereFoundClauseKind;
1074 }
1075
1076 unsigned getNestingLevel() const {
1077 assert(!isStackEmpty());
1078 return getStackSize() - 1;
1079 }
1080 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1081 SharingMapTy *Parent = getSecondOnStackOrNull();
1082 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1083 Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1084 }
1085 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1086 getDoacrossDependClauses() const {
1087 const SharingMapTy &StackElem = getTopOfStack();
1088 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1089 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1090 return llvm::make_range(Ref.begin(), Ref.end());
1091 }
1092 return llvm::make_range(StackElem.DoacrossDepends.end(),
1093 StackElem.DoacrossDepends.end());
1094 }
1095
1096 // Store types of classes which have been explicitly mapped
1097 void addMappedClassesQualTypes(QualType QT) {
1098 SharingMapTy &StackElem = getTopOfStack();
1099 StackElem.MappedClassesQualTypes.insert(QT);
1100 }
1101
1102 // Return set of mapped classes types
1103 bool isClassPreviouslyMapped(QualType QT) const {
1104 const SharingMapTy &StackElem = getTopOfStack();
1105 return StackElem.MappedClassesQualTypes.contains(QT);
1106 }
1107
1108 /// Adds global declare target to the parent target region.
1109 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1110 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1111 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1112 "Expected declare target link global.");
1113 for (auto &Elem : *this) {
1114 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1115 Elem.DeclareTargetLinkVarDecls.push_back(E);
1116 return;
1117 }
1118 }
1119 }
1120
1121 /// Returns the list of globals with declare target link if current directive
1122 /// is target.
1123 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1124 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1125 "Expected target executable directive.");
1126 return getTopOfStack().DeclareTargetLinkVarDecls;
1127 }
1128
1129 /// Adds list of allocators expressions.
1130 void addInnerAllocatorExpr(Expr *E) {
1131 getTopOfStack().InnerUsedAllocators.push_back(E);
1132 }
1133 /// Return list of used allocators.
1134 ArrayRef<Expr *> getInnerAllocators() const {
1135 return getTopOfStack().InnerUsedAllocators;
1136 }
1137 /// Marks the declaration as implicitly firstprivate nin the task-based
1138 /// regions.
1139 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1140 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1141 }
1142 /// Checks if the decl is implicitly firstprivate in the task-based region.
1143 bool isImplicitTaskFirstprivate(Decl *D) const {
1144 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1145 }
1146
1147 /// Marks decl as used in uses_allocators clause as the allocator.
1148 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1149 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1150 }
1151 /// Checks if specified decl is used in uses allocator clause as the
1152 /// allocator.
1153 std::optional<UsesAllocatorsDeclKind>
1154 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1155 const SharingMapTy &StackElem = getTopOfStack();
1156 auto I = StackElem.UsesAllocatorsDecls.find(D);
1157 if (I == StackElem.UsesAllocatorsDecls.end())
1158 return std::nullopt;
1159 return I->getSecond();
1160 }
1161 std::optional<UsesAllocatorsDeclKind>
1162 isUsesAllocatorsDecl(const Decl *D) const {
1163 const SharingMapTy &StackElem = getTopOfStack();
1164 auto I = StackElem.UsesAllocatorsDecls.find(D);
1165 if (I == StackElem.UsesAllocatorsDecls.end())
1166 return std::nullopt;
1167 return I->getSecond();
1168 }
1169
1170 void addDeclareMapperVarRef(Expr *Ref) {
1171 SharingMapTy &StackElem = getTopOfStack();
1172 StackElem.DeclareMapperVar = Ref;
1173 }
1174 const Expr *getDeclareMapperVarRef() const {
1175 const SharingMapTy *Top = getTopOfStackOrNull();
1176 return Top ? Top->DeclareMapperVar : nullptr;
1177 }
1178
1179 /// Add a new iterator variable.
1180 void addIteratorVarDecl(VarDecl *VD) {
1181 SharingMapTy &StackElem = getTopOfStack();
1182 StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl());
1183 }
1184 /// Check if variable declaration is an iterator VarDecl.
1185 bool isIteratorVarDecl(const VarDecl *VD) const {
1186 const SharingMapTy *Top = getTopOfStackOrNull();
1187 if (!Top)
1188 return false;
1189
1190 return llvm::is_contained(Top->IteratorVarDecls, VD->getCanonicalDecl());
1191 }
1192 /// get captured field from ImplicitDefaultFirstprivateFDs
1193 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1194 const_iterator I = begin();
1195 const_iterator EndI = end();
1196 size_t StackLevel = getStackSize();
1197 for (; I != EndI; ++I) {
1198 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1199 break;
1200 StackLevel--;
1201 }
1202 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1203 if (I == EndI)
1204 return nullptr;
1205 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1206 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1207 return IFD.VD;
1208 return nullptr;
1209 }
1210 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1211 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1212 const_iterator I = begin();
1213 const_iterator EndI = end();
1214 for (; I != EndI; ++I)
1215 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1216 break;
1217 if (I == EndI)
1218 return false;
1219 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1220 if (IFD.VD == VD)
1221 return true;
1222 return false;
1223 }
1224 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1225 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1226 iterator I = begin();
1227 const_iterator EndI = end();
1228 size_t StackLevel = getStackSize();
1229 for (; I != EndI; ++I) {
1230 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1231 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1232 break;
1233 }
1234 StackLevel--;
1235 }
1236 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1237 }
1238};
1239
1240bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1241 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1242}
1243
1244bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1245 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1246 DKind == OMPD_unknown;
1247}
1248
1249} // namespace
1250
1251static const Expr *getExprAsWritten(const Expr *E) {
1252 if (const auto *FE = dyn_cast<FullExpr>(E))
1253 E = FE->getSubExpr();
1254
1255 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1256 E = MTE->getSubExpr();
1257
1258 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1259 E = Binder->getSubExpr();
1260
1261 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1262 E = ICE->getSubExprAsWritten();
1263 return E->IgnoreParens();
1264}
1265
1267 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1268}
1269
1270static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1271 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1272 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1273 D = ME->getMemberDecl();
1274 const auto *VD = dyn_cast<VarDecl>(D);
1275 const auto *FD = dyn_cast<FieldDecl>(D);
1276 if (VD != nullptr) {
1277 VD = VD->getCanonicalDecl();
1278 D = VD;
1279 } else {
1280 assert(FD);
1281 FD = FD->getCanonicalDecl();
1282 D = FD;
1283 }
1284 return D;
1285}
1286
1288 return const_cast<ValueDecl *>(
1289 getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1290}
1291
1292DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1293 ValueDecl *D) const {
1294 D = getCanonicalDecl(D);
1295 auto *VD = dyn_cast<VarDecl>(D);
1296 const auto *FD = dyn_cast<FieldDecl>(D);
1297 DSAVarData DVar;
1298 if (Iter == end()) {
1299 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1300 // in a region but not in construct]
1301 // File-scope or namespace-scope variables referenced in called routines
1302 // in the region are shared unless they appear in a threadprivate
1303 // directive.
1304 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1305 DVar.CKind = OMPC_shared;
1306
1307 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1308 // in a region but not in construct]
1309 // Variables with static storage duration that are declared in called
1310 // routines in the region are shared.
1311 if (VD && VD->hasGlobalStorage())
1312 DVar.CKind = OMPC_shared;
1313
1314 // Non-static data members are shared by default.
1315 if (FD)
1316 DVar.CKind = OMPC_shared;
1317
1318 return DVar;
1319 }
1320
1321 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1322 // in a Construct, C/C++, predetermined, p.1]
1323 // Variables with automatic storage duration that are declared in a scope
1324 // inside the construct are private.
1325 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1326 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1327 DVar.CKind = OMPC_private;
1328 return DVar;
1329 }
1330
1331 DVar.DKind = Iter->Directive;
1332 // Explicitly specified attributes and local variables with predetermined
1333 // attributes.
1334 if (Iter->SharingMap.count(D)) {
1335 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1336 DVar.RefExpr = Data.RefExpr.getPointer();
1337 DVar.PrivateCopy = Data.PrivateCopy;
1338 DVar.CKind = Data.Attributes;
1339 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1340 DVar.Modifier = Data.Modifier;
1341 DVar.AppliedToPointee = Data.AppliedToPointee;
1342 return DVar;
1343 }
1344
1345 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1346 // in a Construct, C/C++, implicitly determined, p.1]
1347 // In a parallel or task construct, the data-sharing attributes of these
1348 // variables are determined by the default clause, if present.
1349 switch (Iter->DefaultAttr) {
1350 case DSA_shared:
1351 DVar.CKind = OMPC_shared;
1352 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1353 return DVar;
1354 case DSA_none:
1355 return DVar;
1356 case DSA_firstprivate:
1357 if (VD && VD->getStorageDuration() == SD_Static &&
1358 VD->getDeclContext()->isFileContext()) {
1359 DVar.CKind = OMPC_unknown;
1360 } else {
1361 DVar.CKind = OMPC_firstprivate;
1362 }
1363 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1364 return DVar;
1365 case DSA_private:
1366 // each variable with static storage duration that is declared
1367 // in a namespace or global scope and referenced in the construct,
1368 // and that does not have a predetermined data-sharing attribute
1369 if (VD && VD->getStorageDuration() == SD_Static &&
1370 VD->getDeclContext()->isFileContext()) {
1371 DVar.CKind = OMPC_unknown;
1372 } else {
1373 DVar.CKind = OMPC_private;
1374 }
1375 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1376 return DVar;
1377 case DSA_unspecified:
1378 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1379 // in a Construct, implicitly determined, p.2]
1380 // In a parallel construct, if no default clause is present, these
1381 // variables are shared.
1382 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1383 if ((isOpenMPParallelDirective(DVar.DKind) &&
1384 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1385 isOpenMPTeamsDirective(DVar.DKind)) {
1386 DVar.CKind = OMPC_shared;
1387 return DVar;
1388 }
1389
1390 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1391 // in a Construct, implicitly determined, p.4]
1392 // In a task construct, if no default clause is present, a variable that in
1393 // the enclosing context is determined to be shared by all implicit tasks
1394 // bound to the current team is shared.
1395 if (isOpenMPTaskingDirective(DVar.DKind)) {
1396 DSAVarData DVarTemp;
1397 const_iterator I = Iter, E = end();
1398 do {
1399 ++I;
1400 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1401 // Referenced in a Construct, implicitly determined, p.6]
1402 // In a task construct, if no default clause is present, a variable
1403 // whose data-sharing attribute is not determined by the rules above is
1404 // firstprivate.
1405 DVarTemp = getDSA(I, D);
1406 if (DVarTemp.CKind != OMPC_shared) {
1407 DVar.RefExpr = nullptr;
1408 DVar.CKind = OMPC_firstprivate;
1409 return DVar;
1410 }
1411 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1412 DVar.CKind =
1413 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1414 return DVar;
1415 }
1416 }
1417 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1418 // in a Construct, implicitly determined, p.3]
1419 // For constructs other than task, if no default clause is present, these
1420 // variables inherit their data-sharing attributes from the enclosing
1421 // context.
1422 return getDSA(++Iter, D);
1423}
1424
1425const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1426 const Expr *NewDE) {
1427 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1428 D = getCanonicalDecl(D);
1429 SharingMapTy &StackElem = getTopOfStack();
1430 auto It = StackElem.AlignedMap.find(D);
1431 if (It == StackElem.AlignedMap.end()) {
1432 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1433 StackElem.AlignedMap[D] = NewDE;
1434 return nullptr;
1435 }
1436 assert(It->second && "Unexpected nullptr expr in the aligned map");
1437 return It->second;
1438}
1439
1440const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1441 const Expr *NewDE) {
1442 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1443 D = getCanonicalDecl(D);
1444 SharingMapTy &StackElem = getTopOfStack();
1445 auto It = StackElem.NontemporalMap.find(D);
1446 if (It == StackElem.NontemporalMap.end()) {
1447 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1448 StackElem.NontemporalMap[D] = NewDE;
1449 return nullptr;
1450 }
1451 assert(It->second && "Unexpected nullptr expr in the aligned map");
1452 return It->second;
1453}
1454
1455void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1456 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1457 D = getCanonicalDecl(D);
1458 SharingMapTy &StackElem = getTopOfStack();
1459 StackElem.LCVMap.try_emplace(
1460 D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1461}
1462
1463const DSAStackTy::LCDeclInfo
1464DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1465 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1466 D = getCanonicalDecl(D);
1467 const SharingMapTy &StackElem = getTopOfStack();
1468 auto It = StackElem.LCVMap.find(D);
1469 if (It != StackElem.LCVMap.end())
1470 return It->second;
1471 return {0, nullptr};
1472}
1473
1474const DSAStackTy::LCDeclInfo
1475DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1476 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1477 D = getCanonicalDecl(D);
1478 for (unsigned I = Level + 1; I > 0; --I) {
1479 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1480 auto It = StackElem.LCVMap.find(D);
1481 if (It != StackElem.LCVMap.end())
1482 return It->second;
1483 }
1484 return {0, nullptr};
1485}
1486
1487const DSAStackTy::LCDeclInfo
1488DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1489 const SharingMapTy *Parent = getSecondOnStackOrNull();
1490 assert(Parent && "Data-sharing attributes stack is empty");
1491 D = getCanonicalDecl(D);
1492 auto It = Parent->LCVMap.find(D);
1493 if (It != Parent->LCVMap.end())
1494 return It->second;
1495 return {0, nullptr};
1496}
1497
1498const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1499 const SharingMapTy *Parent = getSecondOnStackOrNull();
1500 assert(Parent && "Data-sharing attributes stack is empty");
1501 if (Parent->LCVMap.size() < I)
1502 return nullptr;
1503 for (const auto &Pair : Parent->LCVMap)
1504 if (Pair.second.first == I)
1505 return Pair.first;
1506 return nullptr;
1507}
1508
1509void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1510 DeclRefExpr *PrivateCopy, unsigned Modifier,
1511 bool AppliedToPointee) {
1512 D = getCanonicalDecl(D);
1513 if (A == OMPC_threadprivate) {
1514 DSAInfo &Data = Threadprivates[D];
1515 Data.Attributes = A;
1516 Data.RefExpr.setPointer(E);
1517 Data.PrivateCopy = nullptr;
1518 Data.Modifier = Modifier;
1519 } else {
1520 DSAInfo &Data = getTopOfStack().SharingMap[D];
1521 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1522 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1523 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1524 (isLoopControlVariable(D).first && A == OMPC_private));
1525 Data.Modifier = Modifier;
1526 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1527 Data.RefExpr.setInt(/*IntVal=*/true);
1528 return;
1529 }
1530 const bool IsLastprivate =
1531 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1532 Data.Attributes = A;
1533 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1534 Data.PrivateCopy = PrivateCopy;
1535 Data.AppliedToPointee = AppliedToPointee;
1536 if (PrivateCopy) {
1537 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1538 Data.Modifier = Modifier;
1539 Data.Attributes = A;
1540 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1541 Data.PrivateCopy = nullptr;
1542 Data.AppliedToPointee = AppliedToPointee;
1543 }
1544 }
1545}
1546
1547/// Build a variable declaration for OpenMP loop iteration variable.
1549 StringRef Name, const AttrVec *Attrs = nullptr,
1550 DeclRefExpr *OrigRef = nullptr) {
1551 DeclContext *DC = SemaRef.CurContext;
1552 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1553 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
1554 auto *Decl =
1555 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
1556 if (Attrs) {
1557 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1558 I != E; ++I)
1559 Decl->addAttr(*I);
1560 }
1561 Decl->setImplicit();
1562 if (OrigRef) {
1563 Decl->addAttr(
1564 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1565 }
1566 return Decl;
1567}
1568
1570 SourceLocation Loc,
1571 bool RefersToCapture = false) {
1572 D->setReferenced();
1573 D->markUsed(S.Context);
1575 SourceLocation(), D, RefersToCapture, Loc, Ty,
1576 VK_LValue);
1577}
1578
1579void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1580 BinaryOperatorKind BOK) {
1581 D = getCanonicalDecl(D);
1582 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1583 assert(
1584 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1585 "Additional reduction info may be specified only for reduction items.");
1586 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1587 assert(ReductionData.ReductionRange.isInvalid() &&
1588 (getTopOfStack().Directive == OMPD_taskgroup ||
1589 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1590 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1591 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1592 "Additional reduction info may be specified only once for reduction "
1593 "items.");
1594 ReductionData.set(BOK, SR);
1595 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1596 if (!TaskgroupReductionRef) {
1597 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1598 SemaRef.Context.VoidPtrTy, ".task_red.");
1599 TaskgroupReductionRef =
1600 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1601 }
1602}
1603
1604void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1605 const Expr *ReductionRef) {
1606 D = getCanonicalDecl(D);
1607 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1608 assert(
1609 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1610 "Additional reduction info may be specified only for reduction items.");
1611 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1612 assert(ReductionData.ReductionRange.isInvalid() &&
1613 (getTopOfStack().Directive == OMPD_taskgroup ||
1614 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1615 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1616 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1617 "Additional reduction info may be specified only once for reduction "
1618 "items.");
1619 ReductionData.set(ReductionRef, SR);
1620 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1621 if (!TaskgroupReductionRef) {
1622 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1623 SemaRef.Context.VoidPtrTy, ".task_red.");
1624 TaskgroupReductionRef =
1625 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1626 }
1627}
1628
1629const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1630 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1631 Expr *&TaskgroupDescriptor) const {
1632 D = getCanonicalDecl(D);
1633 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1634 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1635 const DSAInfo &Data = I->SharingMap.lookup(D);
1636 if (Data.Attributes != OMPC_reduction ||
1637 Data.Modifier != OMPC_REDUCTION_task)
1638 continue;
1639 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1640 if (!ReductionData.ReductionOp ||
1641 ReductionData.ReductionOp.is<const Expr *>())
1642 return DSAVarData();
1643 SR = ReductionData.ReductionRange;
1644 BOK = ReductionData.ReductionOp.get<ReductionData::BOKPtrType>();
1645 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1646 "expression for the descriptor is not "
1647 "set.");
1648 TaskgroupDescriptor = I->TaskgroupReductionRef;
1649 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1650 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1651 /*AppliedToPointee=*/false);
1652 }
1653 return DSAVarData();
1654}
1655
1656const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1657 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1658 Expr *&TaskgroupDescriptor) const {
1659 D = getCanonicalDecl(D);
1660 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1661 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1662 const DSAInfo &Data = I->SharingMap.lookup(D);
1663 if (Data.Attributes != OMPC_reduction ||
1664 Data.Modifier != OMPC_REDUCTION_task)
1665 continue;
1666 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1667 if (!ReductionData.ReductionOp ||
1668 !ReductionData.ReductionOp.is<const Expr *>())
1669 return DSAVarData();
1670 SR = ReductionData.ReductionRange;
1671 ReductionRef = ReductionData.ReductionOp.get<const Expr *>();
1672 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1673 "expression for the descriptor is not "
1674 "set.");
1675 TaskgroupDescriptor = I->TaskgroupReductionRef;
1676 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1677 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1678 /*AppliedToPointee=*/false);
1679 }
1680 return DSAVarData();
1681}
1682
1683bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1684 D = D->getCanonicalDecl();
1685 for (const_iterator E = end(); I != E; ++I) {
1686 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1687 isOpenMPTargetExecutionDirective(I->Directive)) {
1688 if (I->CurScope) {
1689 Scope *TopScope = I->CurScope->getParent();
1690 Scope *CurScope = getCurScope();
1691 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1692 CurScope = CurScope->getParent();
1693 return CurScope != TopScope;
1694 }
1695 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1696 if (I->Context == DC)
1697 return true;
1698 return false;
1699 }
1700 }
1701 return false;
1702}
1703
1705 bool AcceptIfMutable = true,
1706 bool *IsClassType = nullptr) {
1707 ASTContext &Context = SemaRef.getASTContext();
1708 Type = Type.getNonReferenceType().getCanonicalType();
1709 bool IsConstant = Type.isConstant(Context);
1710 Type = Context.getBaseElementType(Type);
1711 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1713 : nullptr;
1714 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1715 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1716 RD = CTD->getTemplatedDecl();
1717 if (IsClassType)
1718 *IsClassType = RD;
1719 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1720 RD->hasDefinition() && RD->hasMutableFields());
1721}
1722
1723static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1725 SourceLocation ELoc,
1726 bool AcceptIfMutable = true,
1727 bool ListItemNotVar = false) {
1728 ASTContext &Context = SemaRef.getASTContext();
1729 bool IsClassType;
1730 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
1731 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1732 : IsClassType ? diag::err_omp_const_not_mutable_variable
1733 : diag::err_omp_const_variable;
1734 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseName(CKind);
1735 if (!ListItemNotVar && D) {
1736 const VarDecl *VD = dyn_cast<VarDecl>(D);
1737 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1739 SemaRef.Diag(D->getLocation(),
1740 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1741 << D;
1742 }
1743 return true;
1744 }
1745 return false;
1746}
1747
1748const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1749 bool FromParent) {
1750 D = getCanonicalDecl(D);
1751 DSAVarData DVar;
1752
1753 auto *VD = dyn_cast<VarDecl>(D);
1754 auto TI = Threadprivates.find(D);
1755 if (TI != Threadprivates.end()) {
1756 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1757 DVar.CKind = OMPC_threadprivate;
1758 DVar.Modifier = TI->getSecond().Modifier;
1759 return DVar;
1760 }
1761 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1762 DVar.RefExpr = buildDeclRefExpr(
1763 SemaRef, VD, D->getType().getNonReferenceType(),
1764 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1765 DVar.CKind = OMPC_threadprivate;
1766 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1767 return DVar;
1768 }
1769 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1770 // in a Construct, C/C++, predetermined, p.1]
1771 // Variables appearing in threadprivate directives are threadprivate.
1772 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1773 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1774 SemaRef.getLangOpts().OpenMPUseTLS &&
1775 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1776 (VD && VD->getStorageClass() == SC_Register &&
1777 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1778 DVar.RefExpr = buildDeclRefExpr(
1779 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1780 DVar.CKind = OMPC_threadprivate;
1781 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1782 return DVar;
1783 }
1784 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1785 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1786 !isLoopControlVariable(D).first) {
1787 const_iterator IterTarget =
1788 std::find_if(begin(), end(), [](const SharingMapTy &Data) {
1789 return isOpenMPTargetExecutionDirective(Data.Directive);
1790 });
1791 if (IterTarget != end()) {
1792 const_iterator ParentIterTarget = IterTarget + 1;
1793 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1794 if (isOpenMPLocal(VD, Iter)) {
1795 DVar.RefExpr =
1796 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1797 D->getLocation());
1798 DVar.CKind = OMPC_threadprivate;
1799 return DVar;
1800 }
1801 }
1802 if (!isClauseParsingMode() || IterTarget != begin()) {
1803 auto DSAIter = IterTarget->SharingMap.find(D);
1804 if (DSAIter != IterTarget->SharingMap.end() &&
1805 isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1806 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1807 DVar.CKind = OMPC_threadprivate;
1808 return DVar;
1809 }
1810 const_iterator End = end();
1811 if (!SemaRef.isOpenMPCapturedByRef(D,
1812 std::distance(ParentIterTarget, End),
1813 /*OpenMPCaptureLevel=*/0)) {
1814 DVar.RefExpr =
1815 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1816 IterTarget->ConstructLoc);
1817 DVar.CKind = OMPC_threadprivate;
1818 return DVar;
1819 }
1820 }
1821 }
1822 }
1823
1824 if (isStackEmpty())
1825 // Not in OpenMP execution region and top scope was already checked.
1826 return DVar;
1827
1828 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1829 // in a Construct, C/C++, predetermined, p.4]
1830 // Static data members are shared.
1831 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1832 // in a Construct, C/C++, predetermined, p.7]
1833 // Variables with static storage duration that are declared in a scope
1834 // inside the construct are shared.
1835 if (VD && VD->isStaticDataMember()) {
1836 // Check for explicitly specified attributes.
1837 const_iterator I = begin();
1838 const_iterator EndI = end();
1839 if (FromParent && I != EndI)
1840 ++I;
1841 if (I != EndI) {
1842 auto It = I->SharingMap.find(D);
1843 if (It != I->SharingMap.end()) {
1844 const DSAInfo &Data = It->getSecond();
1845 DVar.RefExpr = Data.RefExpr.getPointer();
1846 DVar.PrivateCopy = Data.PrivateCopy;
1847 DVar.CKind = Data.Attributes;
1848 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1849 DVar.DKind = I->Directive;
1850 DVar.Modifier = Data.Modifier;
1851 DVar.AppliedToPointee = Data.AppliedToPointee;
1852 return DVar;
1853 }
1854 }
1855
1856 DVar.CKind = OMPC_shared;
1857 return DVar;
1858 }
1859
1860 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1861 // The predetermined shared attribute for const-qualified types having no
1862 // mutable members was removed after OpenMP 3.1.
1863 if (SemaRef.LangOpts.OpenMP <= 31) {
1864 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1865 // in a Construct, C/C++, predetermined, p.6]
1866 // Variables with const qualified type having no mutable member are
1867 // shared.
1868 if (isConstNotMutableType(SemaRef, D->getType())) {
1869 // Variables with const-qualified type having no mutable member may be
1870 // listed in a firstprivate clause, even if they are static data members.
1871 DSAVarData DVarTemp = hasInnermostDSA(
1872 D,
1873 [](OpenMPClauseKind C, bool) {
1874 return C == OMPC_firstprivate || C == OMPC_shared;
1875 },
1876 MatchesAlways, FromParent);
1877 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1878 return DVarTemp;
1879
1880 DVar.CKind = OMPC_shared;
1881 return DVar;
1882 }
1883 }
1884
1885 // Explicitly specified attributes and local variables with predetermined
1886 // attributes.
1887 const_iterator I = begin();
1888 const_iterator EndI = end();
1889 if (FromParent && I != EndI)
1890 ++I;
1891 if (I == EndI)
1892 return DVar;
1893 auto It = I->SharingMap.find(D);
1894 if (It != I->SharingMap.end()) {
1895 const DSAInfo &Data = It->getSecond();
1896 DVar.RefExpr = Data.RefExpr.getPointer();
1897 DVar.PrivateCopy = Data.PrivateCopy;
1898 DVar.CKind = Data.Attributes;
1899 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1900 DVar.DKind = I->Directive;
1901 DVar.Modifier = Data.Modifier;
1902 DVar.AppliedToPointee = Data.AppliedToPointee;
1903 }
1904
1905 return DVar;
1906}
1907
1908const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1909 bool FromParent) const {
1910 if (isStackEmpty()) {
1911 const_iterator I;
1912 return getDSA(I, D);
1913 }
1914 D = getCanonicalDecl(D);
1915 const_iterator StartI = begin();
1916 const_iterator EndI = end();
1917 if (FromParent && StartI != EndI)
1918 ++StartI;
1919 return getDSA(StartI, D);
1920}
1921
1922const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1923 unsigned Level) const {
1924 if (getStackSize() <= Level)
1925 return DSAVarData();
1926 D = getCanonicalDecl(D);
1927 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1928 return getDSA(StartI, D);
1929}
1930
1931const DSAStackTy::DSAVarData
1932DSAStackTy::hasDSA(ValueDecl *D,
1933 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1934 DefaultDataSharingAttributes)>
1935 CPred,
1936 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1937 bool FromParent) const {
1938 if (isStackEmpty())
1939 return {};
1940 D = getCanonicalDecl(D);
1941 const_iterator I = begin();
1942 const_iterator EndI = end();
1943 if (FromParent && I != EndI)
1944 ++I;
1945 for (; I != EndI; ++I) {
1946 if (!DPred(I->Directive) &&
1947 !isImplicitOrExplicitTaskingRegion(I->Directive))
1948 continue;
1949 const_iterator NewI = I;
1950 DSAVarData DVar = getDSA(NewI, D);
1951 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1952 return DVar;
1953 }
1954 return {};
1955}
1956
1957const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1958 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1959 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1960 bool FromParent) const {
1961 if (isStackEmpty())
1962 return {};
1963 D = getCanonicalDecl(D);
1964 const_iterator StartI = begin();
1965 const_iterator EndI = end();
1966 if (FromParent && StartI != EndI)
1967 ++StartI;
1968 if (StartI == EndI || !DPred(StartI->Directive))
1969 return {};
1970 const_iterator NewI = StartI;
1971 DSAVarData DVar = getDSA(NewI, D);
1972 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1973 ? DVar
1974 : DSAVarData();
1975}
1976
1977bool DSAStackTy::hasExplicitDSA(
1978 const ValueDecl *D,
1979 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1980 unsigned Level, bool NotLastprivate) const {
1981 if (getStackSize() <= Level)
1982 return false;
1983 D = getCanonicalDecl(D);
1984 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1985 auto I = StackElem.SharingMap.find(D);
1986 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1987 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1988 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1989 return true;
1990 // Check predetermined rules for the loop control variables.
1991 auto LI = StackElem.LCVMap.find(D);
1992 if (LI != StackElem.LCVMap.end())
1993 return CPred(OMPC_private, /*AppliedToPointee=*/false);
1994 return false;
1995}
1996
1997bool DSAStackTy::hasExplicitDirective(
1998 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1999 unsigned Level) const {
2000 if (getStackSize() <= Level)
2001 return false;
2002 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2003 return DPred(StackElem.Directive);
2004}
2005
2006bool DSAStackTy::hasDirective(
2007 const llvm::function_ref<bool(OpenMPDirectiveKind,
2009 DPred,
2010 bool FromParent) const {
2011 // We look only in the enclosing region.
2012 size_t Skip = FromParent ? 2 : 1;
2013 for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
2014 I != E; ++I) {
2015 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2016 return true;
2017 }
2018 return false;
2019}
2020
2021void Sema::InitDataSharingAttributesStack() {
2022 VarDataSharingAttributesStack = new DSAStackTy(*this);
2023}
2024
2025#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2026
2027void Sema::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2028
2029void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2030 DSAStack->popFunction(OldFSI);
2031}
2032
2034 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2035 "Expected OpenMP device compilation.");
2037}
2038
2039namespace {
2040/// Status of the function emission on the host/device.
2041enum class FunctionEmissionStatus {
2042 Emitted,
2043 Discarded,
2044 Unknown,
2045};
2046} // anonymous namespace
2047
2050 const FunctionDecl *FD) {
2051 assert(LangOpts.OpenMP && LangOpts.OpenMPIsTargetDevice &&
2052 "Expected OpenMP device compilation.");
2053
2055 if (FD) {
2057 switch (FES) {
2060 break;
2062 // TODO: We should always delay diagnostics here in case a target
2063 // region is in a function we do not emit. However, as the
2064 // current diagnostics are associated with the function containing
2065 // the target region and we do not emit that one, we would miss out
2066 // on diagnostics for the target region itself. We need to anchor
2067 // the diagnostics with the new generated function *or* ensure we
2068 // emit diagnostics associated with the surrounding function.
2069 Kind = isOpenMPDeviceDelayedContext(*this)
2072 break;
2076 break;
2078 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2079 break;
2080 }
2081 }
2082
2083 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this);
2084}
2085
2087 unsigned DiagID,
2088 const FunctionDecl *FD) {
2089 assert(LangOpts.OpenMP && !LangOpts.OpenMPIsTargetDevice &&
2090 "Expected OpenMP host compilation.");
2091
2093 if (FD) {
2095 switch (FES) {
2098 break;
2101 break;
2106 break;
2107 }
2108 }
2109
2110 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this);
2111}
2112
2115 if (LO.OpenMP <= 45) {
2117 return OMPC_DEFAULTMAP_scalar;
2118 return OMPC_DEFAULTMAP_aggregate;
2119 }
2121 return OMPC_DEFAULTMAP_pointer;
2123 return OMPC_DEFAULTMAP_scalar;
2124 return OMPC_DEFAULTMAP_aggregate;
2125}
2126
2127bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2128 unsigned OpenMPCaptureLevel) const {
2129 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2130
2131 ASTContext &Ctx = getASTContext();
2132 bool IsByRef = true;
2133
2134 // Find the directive that is associated with the provided scope.
2135 D = cast<ValueDecl>(D->getCanonicalDecl());
2136 QualType Ty = D->getType();
2137
2138 bool IsVariableUsedInMapClause = false;
2139 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2140 // This table summarizes how a given variable should be passed to the device
2141 // given its type and the clauses where it appears. This table is based on
2142 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2143 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2144 //
2145 // =========================================================================
2146 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2147 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2148 // =========================================================================
2149 // | scl | | | | - | | bycopy|
2150 // | scl | | - | x | - | - | bycopy|
2151 // | scl | | x | - | - | - | null |
2152 // | scl | x | | | - | | byref |
2153 // | scl | x | - | x | - | - | bycopy|
2154 // | scl | x | x | - | - | - | null |
2155 // | scl | | - | - | - | x | byref |
2156 // | scl | x | - | - | - | x | byref |
2157 //
2158 // | agg | n.a. | | | - | | byref |
2159 // | agg | n.a. | - | x | - | - | byref |
2160 // | agg | n.a. | x | - | - | - | null |
2161 // | agg | n.a. | - | - | - | x | byref |
2162 // | agg | n.a. | - | - | - | x[] | byref |
2163 //
2164 // | ptr | n.a. | | | - | | bycopy|
2165 // | ptr | n.a. | - | x | - | - | bycopy|
2166 // | ptr | n.a. | x | - | - | - | null |
2167 // | ptr | n.a. | - | - | - | x | byref |
2168 // | ptr | n.a. | - | - | - | x[] | bycopy|
2169 // | ptr | n.a. | - | - | x | | bycopy|
2170 // | ptr | n.a. | - | - | x | x | bycopy|
2171 // | ptr | n.a. | - | - | x | x[] | bycopy|
2172 // =========================================================================
2173 // Legend:
2174 // scl - scalar
2175 // ptr - pointer
2176 // agg - aggregate
2177 // x - applies
2178 // - - invalid in this combination
2179 // [] - mapped with an array section
2180 // byref - should be mapped by reference
2181 // byval - should be mapped by value
2182 // null - initialize a local variable to null on the device
2183 //
2184 // Observations:
2185 // - All scalar declarations that show up in a map clause have to be passed
2186 // by reference, because they may have been mapped in the enclosing data
2187 // environment.
2188 // - If the scalar value does not fit the size of uintptr, it has to be
2189 // passed by reference, regardless the result in the table above.
2190 // - For pointers mapped by value that have either an implicit map or an
2191 // array section, the runtime library may pass the NULL value to the
2192 // device instead of the value passed to it by the compiler.
2193
2194 if (Ty->isReferenceType())
2195 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2196
2197 // Locate map clauses and see if the variable being captured is referred to
2198 // in any of those clauses. Here we only care about variables, not fields,
2199 // because fields are part of aggregates.
2200 bool IsVariableAssociatedWithSection = false;
2201
2202 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2203 D, Level,
2204 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2206 MapExprComponents,
2207 OpenMPClauseKind WhereFoundClauseKind) {
2208 // Both map and has_device_addr clauses information influences how a
2209 // variable is captured. E.g. is_device_ptr does not require changing
2210 // the default behavior.
2211 if (WhereFoundClauseKind != OMPC_map &&
2212 WhereFoundClauseKind != OMPC_has_device_addr)
2213 return false;
2214
2215 auto EI = MapExprComponents.rbegin();
2216 auto EE = MapExprComponents.rend();
2217
2218 assert(EI != EE && "Invalid map expression!");
2219
2220 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2221 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2222
2223 ++EI;
2224 if (EI == EE)
2225 return false;
2226 auto Last = std::prev(EE);
2227 const auto *UO =
2228 dyn_cast<UnaryOperator>(Last->getAssociatedExpression());
2229 if ((UO && UO->getOpcode() == UO_Deref) ||
2230 isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) ||
2231 isa<OMPArraySectionExpr>(Last->getAssociatedExpression()) ||
2232 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2233 isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) {
2234 IsVariableAssociatedWithSection = true;
2235 // There is nothing more we need to know about this variable.
2236 return true;
2237 }
2238
2239 // Keep looking for more map info.
2240 return false;
2241 });
2242
2243 if (IsVariableUsedInMapClause) {
2244 // If variable is identified in a map clause it is always captured by
2245 // reference except if it is a pointer that is dereferenced somehow.
2246 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2247 } else {
2248 // By default, all the data that has a scalar type is mapped by copy
2249 // (except for reduction variables).
2250 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2251 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2252 !Ty->isAnyPointerType()) ||
2253 !Ty->isScalarType() ||
2254 DSAStack->isDefaultmapCapturedByRef(
2256 DSAStack->hasExplicitDSA(
2257 D,
2258 [](OpenMPClauseKind K, bool AppliedToPointee) {
2259 return K == OMPC_reduction && !AppliedToPointee;
2260 },
2261 Level);
2262 }
2263 }
2264
2265 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2266 IsByRef =
2267 ((IsVariableUsedInMapClause &&
2268 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2269 OMPD_target) ||
2270 !(DSAStack->hasExplicitDSA(
2271 D,
2272 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2273 return K == OMPC_firstprivate ||
2274 (K == OMPC_reduction && AppliedToPointee);
2275 },
2276 Level, /*NotLastprivate=*/true) ||
2277 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2278 // If the variable is artificial and must be captured by value - try to
2279 // capture by value.
2280 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2281 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2282 // If the variable is implicitly firstprivate and scalar - capture by
2283 // copy
2284 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2285 DSAStack->getDefaultDSA() == DSA_private) &&
2286 !DSAStack->hasExplicitDSA(
2287 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2288 Level) &&
2289 !DSAStack->isLoopControlVariable(D, Level).first);
2290 }
2291
2292 // When passing data by copy, we need to make sure it fits the uintptr size
2293 // and alignment, because the runtime library only deals with uintptr types.
2294 // If it does not fit the uintptr size, we need to pass the data by reference
2295 // instead.
2296 if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) >
2298 Ctx.getAlignOfGlobalVarInChars(Ty, dyn_cast<VarDecl>(D)) >
2299 Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2300 IsByRef = true;
2301 }
2302
2303 return IsByRef;
2304}
2305
2306unsigned Sema::getOpenMPNestingLevel() const {
2307 assert(getLangOpts().OpenMP);
2308 return DSAStack->getNestingLevel();
2309}
2310
2312 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2313 DSAStack->isUntiedRegion();
2314}
2315
2317 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2318 !DSAStack->isClauseParsingMode()) ||
2319 DSAStack->hasDirective(
2321 SourceLocation) -> bool {
2323 },
2324 false);
2325}
2326
2328 // Only rebuild for Field.
2329 if (!dyn_cast<FieldDecl>(D))
2330 return false;
2331 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2332 D,
2333 [](OpenMPClauseKind C, bool AppliedToPointee,
2334 DefaultDataSharingAttributes DefaultAttr) {
2335 return isOpenMPPrivate(C) && !AppliedToPointee &&
2336 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2337 },
2338 [](OpenMPDirectiveKind) { return true; },
2339 DSAStack->isClauseParsingMode());
2340 if (DVarPrivate.CKind != OMPC_unknown)
2341 return true;
2342 return false;
2343}
2344
2346 Expr *CaptureExpr, bool WithInit,
2347 DeclContext *CurContext,
2348 bool AsExpression);
2349
2351 unsigned StopAt) {
2352 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2353 D = getCanonicalDecl(D);
2354
2355 auto *VD = dyn_cast<VarDecl>(D);
2356 // Do not capture constexpr variables.
2357 if (VD && VD->isConstexpr())
2358 return nullptr;
2359
2360 // If we want to determine whether the variable should be captured from the
2361 // perspective of the current capturing scope, and we've already left all the
2362 // capturing scopes of the top directive on the stack, check from the
2363 // perspective of its parent directive (if any) instead.
2364 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2365 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2366
2367 // If we are attempting to capture a global variable in a directive with
2368 // 'target' we return true so that this global is also mapped to the device.
2369 //
2370 if (VD && !VD->hasLocalStorage() &&
2373 DSAStackTy::DSAVarData DVarTop =
2374 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2375 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2376 return VD;
2377 // If the declaration is enclosed in a 'declare target' directive,
2378 // then it should not be captured.
2379 //
2380 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2381 return nullptr;
2382 CapturedRegionScopeInfo *CSI = nullptr;
2383 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2384 llvm::reverse(FunctionScopes),
2385 CheckScopeInfo ? (FunctionScopes.size() - (StopAt + 1)) : 0)) {
2386 if (!isa<CapturingScopeInfo>(FSI))
2387 return nullptr;
2388 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2389 if (RSI->CapRegionKind == CR_OpenMP) {
2390 CSI = RSI;
2391 break;
2392 }
2393 }
2394 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2397 DSAStack->getDirective(CSI->OpenMPLevel));
2398 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2399 return VD;
2400 }
2402 // Try to mark variable as declare target if it is used in capturing
2403 // regions.
2404 if (LangOpts.OpenMP <= 45 &&
2405 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2407 return nullptr;
2408 }
2409 }
2410
2411 if (CheckScopeInfo) {
2412 bool OpenMPFound = false;
2413 for (unsigned I = StopAt + 1; I > 0; --I) {
2414 FunctionScopeInfo *FSI = FunctionScopes[I - 1];
2415 if (!isa<CapturingScopeInfo>(FSI))
2416 return nullptr;
2417 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2418 if (RSI->CapRegionKind == CR_OpenMP) {
2419 OpenMPFound = true;
2420 break;
2421 }
2422 }
2423 if (!OpenMPFound)
2424 return nullptr;
2425 }
2426
2427 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2428 (!DSAStack->isClauseParsingMode() ||
2429 DSAStack->getParentDirective() != OMPD_unknown)) {
2430 auto &&Info = DSAStack->isLoopControlVariable(D);
2431 if (Info.first ||
2432 (VD && VD->hasLocalStorage() &&
2433 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2434 (VD && DSAStack->isForceVarCapturing()))
2435 return VD ? VD : Info.second;
2436 DSAStackTy::DSAVarData DVarTop =
2437 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2438 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2439 (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee))
2440 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2441 // Threadprivate variables must not be captured.
2442 if (isOpenMPThreadPrivate(DVarTop.CKind))
2443 return nullptr;
2444 // The variable is not private or it is the variable in the directive with
2445 // default(none) clause and not used in any clause.
2446 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2447 D,
2448 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2449 return isOpenMPPrivate(C) && !AppliedToPointee;
2450 },
2451 [](OpenMPDirectiveKind) { return true; },
2452 DSAStack->isClauseParsingMode());
2453 // Global shared must not be captured.
2454 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2455 ((DSAStack->getDefaultDSA() != DSA_none &&
2456 DSAStack->getDefaultDSA() != DSA_private &&
2457 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2458 DVarTop.CKind == OMPC_shared))
2459 return nullptr;
2460 auto *FD = dyn_cast<FieldDecl>(D);
2461 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2462 !DVarPrivate.PrivateCopy) {
2463 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2464 D,
2465 [](OpenMPClauseKind C, bool AppliedToPointee,
2466 DefaultDataSharingAttributes DefaultAttr) {
2467 return isOpenMPPrivate(C) && !AppliedToPointee &&
2468 (DefaultAttr == DSA_firstprivate ||
2469 DefaultAttr == DSA_private);
2470 },
2471 [](OpenMPDirectiveKind) { return true; },
2472 DSAStack->isClauseParsingMode());
2473 if (DVarPrivate.CKind == OMPC_unknown)
2474 return nullptr;
2475
2476 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2477 if (VD)
2478 return VD;
2479 if (getCurrentThisType().isNull())
2480 return nullptr;
2482 /*IsImplicit=*/true);
2483 const CXXScopeSpec CS = CXXScopeSpec();
2484 Expr *ME = BuildMemberExpr(ThisExpr, /*IsArrow=*/true, SourceLocation(),
2487 /*HadMultipleCandidates=*/false,
2491 *this, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2492 CurContext->getParent(), /*AsExpression=*/false);
2493 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2494 *this, CD, CD->getType().getNonReferenceType(), SourceLocation());
2495 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2496 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2497 return VD;
2498 }
2499 if (DVarPrivate.CKind != OMPC_unknown ||
2500 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2501 DSAStack->getDefaultDSA() == DSA_private ||
2502 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2503 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2504 }
2505 return nullptr;
2506}
2507
2508void Sema::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2509 unsigned Level) const {
2510 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2511}
2512
2514 assert(LangOpts.OpenMP && "OpenMP must be enabled.");
2515 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2516 DSAStack->loopInit();
2517}
2518
2520 assert(LangOpts.OpenMP && "OpenMP must be enabled.");
2521 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2522 DSAStack->resetPossibleLoopCounter();
2523 DSAStack->loopStart();
2524 }
2525}
2526
2528 unsigned CapLevel) const {
2529 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2530 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2531 (!DSAStack->isClauseParsingMode() ||
2532 DSAStack->getParentDirective() != OMPD_unknown)) {
2533 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2534 D,
2535 [](OpenMPClauseKind C, bool AppliedToPointee,
2536 DefaultDataSharingAttributes DefaultAttr) {
2537 return isOpenMPPrivate(C) && !AppliedToPointee &&
2538 DefaultAttr == DSA_private;
2539 },
2540 [](OpenMPDirectiveKind) { return true; },
2541 DSAStack->isClauseParsingMode());
2542 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2543 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2544 !DSAStack->isLoopControlVariable(D).first)
2545 return OMPC_private;
2546 }
2547 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2548 bool IsTriviallyCopyable =
2550 !D->getType()
2554 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2556 getOpenMPCaptureRegions(CaptureRegions, DKind);
2557 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2558 (IsTriviallyCopyable ||
2559 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2560 if (DSAStack->hasExplicitDSA(
2561 D,
2562 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2563 Level, /*NotLastprivate=*/true))
2564 return OMPC_firstprivate;
2565 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2566 if (DVar.CKind != OMPC_shared &&
2567 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2568 DSAStack->addImplicitTaskFirstprivate(Level, D);
2569 return OMPC_firstprivate;
2570 }
2571 }
2572 }
2573 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2574 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2575 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2576 DSAStack->resetPossibleLoopCounter(D);
2577 DSAStack->loopStart();
2578 return OMPC_private;
2579 }
2580 if ((DSAStack->getPossiblyLoopCunter() == D->getCanonicalDecl() ||
2581 DSAStack->isLoopControlVariable(D).first) &&
2582 !DSAStack->hasExplicitDSA(
2583 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2584 Level) &&
2585 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2586 return OMPC_private;
2587 }
2588 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2589 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2590 DSAStack->isForceVarCapturing() &&
2591 !DSAStack->hasExplicitDSA(
2592 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2593 Level))
2594 return OMPC_private;
2595 }
2596 // User-defined allocators are private since they must be defined in the
2597 // context of target region.
2598 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2599 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2600 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2601 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2602 return OMPC_private;
2603 return (DSAStack->hasExplicitDSA(
2604 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2605 Level) ||
2606 (DSAStack->isClauseParsingMode() &&
2607 DSAStack->getClauseParsingMode() == OMPC_private) ||
2608 // Consider taskgroup reduction descriptor variable a private
2609 // to avoid possible capture in the region.
2610 (DSAStack->hasExplicitDirective(
2611 [](OpenMPDirectiveKind K) {
2612 return K == OMPD_taskgroup ||
2613 ((isOpenMPParallelDirective(K) ||
2614 isOpenMPWorksharingDirective(K)) &&
2615 !isOpenMPSimdDirective(K));
2616 },
2617 Level) &&
2618 DSAStack->isTaskgroupReductionRef(D, Level)))
2619 ? OMPC_private
2620 : OMPC_unknown;
2621}
2622
2624 unsigned Level) {
2625 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2626 D = getCanonicalDecl(D);
2627 OpenMPClauseKind OMPC = OMPC_unknown;
2628 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2629 const unsigned NewLevel = I - 1;
2630 if (DSAStack->hasExplicitDSA(
2631 D,
2632 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2633 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2634 OMPC = K;
2635 return true;
2636 }
2637 return false;
2638 },
2639 NewLevel))
2640 break;
2641 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2642 D, NewLevel,
2644 OpenMPClauseKind) { return true; })) {
2645 OMPC = OMPC_map;
2646 break;
2647 }
2648 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2649 NewLevel)) {
2650 OMPC = OMPC_map;
2651 if (DSAStack->mustBeFirstprivateAtLevel(
2653 OMPC = OMPC_firstprivate;
2654 break;
2655 }
2656 }
2657 if (OMPC != OMPC_unknown)
2658 FD->addAttr(OMPCaptureKindAttr::CreateImplicit(Context, unsigned(OMPC)));
2659}
2660
2661bool Sema::isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level,
2662 unsigned CaptureLevel) const {
2663 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2664 // Return true if the current level is no longer enclosed in a target region.
2665
2667 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2668 const auto *VD = dyn_cast<VarDecl>(D);
2669 return VD && !VD->hasLocalStorage() &&
2670 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2671 Level) &&
2672 Regions[CaptureLevel] != OMPD_task;
2673}
2674
2676 unsigned CaptureLevel) const {
2677 assert(LangOpts.OpenMP && "OpenMP is not allowed");
2678 // Return true if the current level is no longer enclosed in a target region.
2679
2680 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2681 if (!VD->hasLocalStorage()) {
2683 return true;
2684 DSAStackTy::DSAVarData TopDVar =
2685 DSAStack->getTopDSA(D, /*FromParent=*/false);
2686 unsigned NumLevels =
2687 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2688 if (Level == 0)
2689 // non-file scope static variale with default(firstprivate)
2690 // should be gloabal captured.
2691 return (NumLevels == CaptureLevel + 1 &&
2692 (TopDVar.CKind != OMPC_shared ||
2693 DSAStack->getDefaultDSA() == DSA_firstprivate));
2694 do {
2695 --Level;
2696 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2697 if (DVar.CKind != OMPC_shared)
2698 return true;
2699 } while (Level > 0);
2700 }
2701 }
2702 return true;
2703}
2704
2705void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; }
2706
2708 OMPTraitInfo &TI) {
2709 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2710}
2711
2714 "Not in OpenMP declare variant scope!");
2715
2716 OMPDeclareVariantScopes.pop_back();
2717}
2718
2720 const FunctionDecl *Callee,
2721 SourceLocation Loc) {
2722 assert(LangOpts.OpenMP && "Expected OpenMP compilation mode.");
2723 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2724 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2725 // Ignore host functions during device analyzis.
2726 if (LangOpts.OpenMPIsTargetDevice &&
2727 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2728 return;
2729 // Ignore nohost functions during host analyzis.
2730 if (!LangOpts.OpenMPIsTargetDevice && DevTy &&
2731 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2732 return;
2733 const FunctionDecl *FD = Callee->getMostRecentDecl();
2734 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2735 if (LangOpts.OpenMPIsTargetDevice && DevTy &&
2736 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2737 // Diagnose host function called during device codegen.
2738 StringRef HostDevTy =
2739 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2740 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2741 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2742 diag::note_omp_marked_device_type_here)
2743 << HostDevTy;
2744 return;
2745 }
2746 if (!LangOpts.OpenMPIsTargetDevice && !LangOpts.OpenMPOffloadMandatory &&
2747 DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2748 // In OpenMP 5.2 or later, if the function has a host variant then allow
2749 // that to be called instead
2750 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2751 for (OMPDeclareVariantAttr *A :
2752 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2753 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2754 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2755 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2756 OMPDeclareTargetDeclAttr::getDeviceType(
2757 VariantFD->getMostRecentDecl());
2758 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2759 return true;
2760 }
2761 return false;
2762 };
2763 if (getLangOpts().OpenMP >= 52 &&
2764 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2765 return;
2766 // Diagnose nohost function called during host codegen.
2767 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2768 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2769 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2770 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2771 diag::note_omp_marked_device_type_here)
2772 << NoHostDevTy;
2773 }
2774}
2775
2777 const DeclarationNameInfo &DirName,
2778 Scope *CurScope, SourceLocation Loc) {
2779 DSAStack->push(DKind, DirName, CurScope, Loc);
2782}
2783
2785 DSAStack->setClauseParsingMode(K);
2786}
2787
2789 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2791}
2792
2793static std::pair<ValueDecl *, bool>
2794getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2795 SourceRange &ERange, bool AllowArraySection = false,
2796 StringRef DiagType = "");
2797
2798/// Check consistency of the reduction clauses.
2799static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2800 ArrayRef<OMPClause *> Clauses) {
2801 bool InscanFound = false;
2802 SourceLocation InscanLoc;
2803 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2804 // A reduction clause without the inscan reduction-modifier may not appear on
2805 // a construct on which a reduction clause with the inscan reduction-modifier
2806 // appears.
2807 for (OMPClause *C : Clauses) {
2808 if (C->getClauseKind() != OMPC_reduction)
2809 continue;
2810 auto *RC = cast<OMPReductionClause>(C);
2811 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2812 InscanFound = true;
2813 InscanLoc = RC->getModifierLoc();
2814 continue;
2815 }
2816 if (RC->getModifier() == OMPC_REDUCTION_task) {
2817 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2818 // A reduction clause with the task reduction-modifier may only appear on
2819 // a parallel construct, a worksharing construct or a combined or
2820 // composite construct for which any of the aforementioned constructs is a
2821 // constituent construct and simd or loop are not constituent constructs.
2822 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2823 if (!(isOpenMPParallelDirective(CurDir) ||
2825 isOpenMPSimdDirective(CurDir))
2826 S.Diag(RC->getModifierLoc(),
2827 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2828 continue;
2829 }
2830 }
2831 if (InscanFound) {
2832 for (OMPClause *C : Clauses) {
2833 if (C->getClauseKind() != OMPC_reduction)
2834 continue;
2835 auto *RC = cast<OMPReductionClause>(C);
2836 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2837 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2838 ? RC->getBeginLoc()
2839 : RC->getModifierLoc(),
2840 diag::err_omp_inscan_reduction_expected);
2841 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2842 continue;
2843 }
2844 for (Expr *Ref : RC->varlists()) {
2845 assert(Ref && "NULL expr in OpenMP nontemporal clause.");
2846 SourceLocation ELoc;
2847 SourceRange ERange;
2848 Expr *SimpleRefExpr = Ref;
2849 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2850 /*AllowArraySection=*/true);
2851 ValueDecl *D = Res.first;
2852 if (!D)
2853 continue;
2854 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2855 S.Diag(Ref->getExprLoc(),
2856 diag::err_omp_reduction_not_inclusive_exclusive)
2857 << Ref->getSourceRange();
2858 }
2859 }
2860 }
2861 }
2862}
2863
2864static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2865 ArrayRef<OMPClause *> Clauses);
2866static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2867 bool WithInit);
2868
2869static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2870 const ValueDecl *D,
2871 const DSAStackTy::DSAVarData &DVar,
2872 bool IsLoopIterVar = false);
2873
2874void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
2875 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2876 // A variable of class type (or array thereof) that appears in a lastprivate
2877 // clause requires an accessible, unambiguous default constructor for the
2878 // class type, unless the list item is also specified in a firstprivate
2879 // clause.
2880 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2881 for (OMPClause *C : D->clauses()) {
2882 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
2883 SmallVector<Expr *, 8> PrivateCopies;
2884 for (Expr *DE : Clause->varlists()) {
2885 if (DE->isValueDependent() || DE->isTypeDependent()) {
2886 PrivateCopies.push_back(nullptr);
2887 continue;
2888 }
2889 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2890 auto *VD = cast<VarDecl>(DRE->getDecl());
2892 const DSAStackTy::DSAVarData DVar =
2893 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2894 if (DVar.CKind == OMPC_lastprivate) {
2895 // Generate helper private variable and initialize it with the
2896 // default value. The address of the original variable is replaced
2897 // by the address of the new private variable in CodeGen. This new
2898 // variable is not added to IdResolver, so the code in the OpenMP
2899 // region uses original variable for proper diagnostics.
2900 VarDecl *VDPrivate = buildVarDecl(
2901 *this, DE->getExprLoc(), Type.getUnqualifiedType(),
2902 VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2903 ActOnUninitializedDecl(VDPrivate);
2904 if (VDPrivate->isInvalidDecl()) {
2905 PrivateCopies.push_back(nullptr);
2906 continue;
2907 }
2908 PrivateCopies.push_back(buildDeclRefExpr(
2909 *this, VDPrivate, DE->getType(), DE->getExprLoc()));
2910 } else {
2911 // The variable is also a firstprivate, so initialization sequence
2912 // for private copy is generated already.
2913 PrivateCopies.push_back(nullptr);
2914 }
2915 }
2916 Clause->setPrivateCopies(PrivateCopies);
2917 continue;
2918 }
2919 // Finalize nontemporal clause by handling private copies, if any.
2920 if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
2921 SmallVector<Expr *, 8> PrivateRefs;
2922 for (Expr *RefExpr : Clause->varlists()) {
2923 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2924 SourceLocation ELoc;
2925 SourceRange ERange;
2926 Expr *SimpleRefExpr = RefExpr;
2927 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
2928 if (Res.second)
2929 // It will be analyzed later.
2930 PrivateRefs.push_back(RefExpr);
2931 ValueDecl *D = Res.first;
2932 if (!D)
2933 continue;
2934
2935 const DSAStackTy::DSAVarData DVar =
2936 DSAStack->getTopDSA(D, /*FromParent=*/false);
2937 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2938 : SimpleRefExpr);
2939 }
2940 Clause->setPrivateRefs(PrivateRefs);
2941 continue;
2942 }
2943 if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
2944 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2945 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2946 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
2947 if (!DRE)
2948 continue;
2949 ValueDecl *VD = DRE->getDecl();
2950 if (!VD || !isa<VarDecl>(VD))
2951 continue;
2952 DSAStackTy::DSAVarData DVar =
2953 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2954 // OpenMP [2.12.5, target Construct]
2955 // Memory allocators that appear in a uses_allocators clause cannot
2956 // appear in other data-sharing attribute clauses or data-mapping
2957 // attribute clauses in the same construct.
2958 Expr *MapExpr = nullptr;
2959 if (DVar.RefExpr ||
2960 DSAStack->checkMappableExprComponentListsForDecl(
2961 VD, /*CurrentRegionOnly=*/true,
2962 [VD, &MapExpr](
2964 MapExprComponents,
2966 auto MI = MapExprComponents.rbegin();
2967 auto ME = MapExprComponents.rend();
2968 if (MI != ME &&
2969 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2970 VD->getCanonicalDecl()) {
2971 MapExpr = MI->getAssociatedExpression();
2972 return true;
2973 }
2974 return false;
2975 })) {
2976 Diag(D.Allocator->getExprLoc(),
2977 diag::err_omp_allocator_used_in_clauses)
2978 << D.Allocator->getSourceRange();
2979 if (DVar.RefExpr)
2980 reportOriginalDsa(*this, DSAStack, VD, DVar);
2981 else
2982 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2983 << MapExpr->getSourceRange();
2984 }
2985 }
2986 continue;
2987 }
2988 }
2989 // Check allocate clauses.
2991 checkAllocateClauses(*this, DSAStack, D->clauses());
2992 checkReductionClauses(*this, DSAStack, D->clauses());
2993 }
2994
2995 DSAStack->pop();
2996 DiscardCleanupsInEvaluationContext();
2997 PopExpressionEvaluationContext();
2998}
2999
3001 Expr *NumIterations, Sema &SemaRef,
3002 Scope *S, DSAStackTy *Stack);
3003
3004namespace {
3005
3006class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3007private:
3008 Sema &SemaRef;
3009
3010public:
3011 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3012 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3013 NamedDecl *ND = Candidate.getCorrectionDecl();
3014 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3015 return VD->hasGlobalStorage() &&
3016 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3017 SemaRef.getCurScope());
3018 }
3019 return false;
3020 }
3021
3022 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3023 return std::make_unique<VarDeclFilterCCC>(*this);
3024 }
3025};
3026
3027class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3028private:
3029 Sema &SemaRef;
3030
3031public:
3032 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3033 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3034 NamedDecl *ND = Candidate.getCorrectionDecl();
3035 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3036 isa<FunctionDecl>(ND))) {
3037 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3038 SemaRef.getCurScope());
3039 }
3040 return false;
3041 }
3042
3043 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3044 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3045 }
3046};
3047
3048} // namespace
3049
3051 CXXScopeSpec &ScopeSpec,
3052 const DeclarationNameInfo &Id,
3053 OpenMPDirectiveKind Kind) {
3054 LookupResult Lookup(*this, Id, LookupOrdinaryName);
3055 LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
3056
3057 if (Lookup.isAmbiguous())
3058 return ExprError();
3059
3060 VarDecl *VD;
3061 if (!Lookup.isSingleResult()) {
3062 VarDeclFilterCCC CCC(*this);
3063 if (TypoCorrection Corrected =
3064 CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, CCC,
3066 diagnoseTypo(Corrected,
3067 PDiag(Lookup.empty()
3068 ? diag::err_undeclared_var_use_suggest
3069 : diag::err_omp_expected_var_arg_suggest)
3070 << Id.getName());
3071 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3072 } else {
3073 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3074 : diag::err_omp_expected_var_arg)
3075 << Id.getName();
3076 return ExprError();
3077 }
3078 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3079 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3080 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3081 return ExprError();
3082 }
3083 Lookup.suppressDiagnostics();
3084
3085 // OpenMP [2.9.2, Syntax, C/C++]
3086 // Variables must be file-scope, namespace-scope, or static block-scope.
3087 if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
3088 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3089 << getOpenMPDirectiveName(Kind) << !VD->isStaticLocal();
3090 bool IsDecl =
3092 Diag(VD->getLocation(),
3093 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3094 << VD;
3095 return ExprError();
3096 }
3097
3098 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3099 NamedDecl *ND = CanonicalVD;
3100 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3101 // A threadprivate directive for file-scope variables must appear outside
3102 // any definition or declaration.
3103 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3104 !getCurLexicalContext()->isTranslationUnit()) {
3105 Diag(Id.getLoc(), diag::err_omp_var_scope)
3106 << getOpenMPDirectiveName(Kind) << VD;
3107 bool IsDecl =
3109 Diag(VD->getLocation(),
3110 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3111 << VD;
3112 return ExprError();
3113 }
3114 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3115 // A threadprivate directive for static class member variables must appear
3116 // in the class definition, in the same scope in which the member
3117 // variables are declared.
3118 if (CanonicalVD->isStaticDataMember() &&
3119 !CanonicalVD->getDeclContext()->Equals(getCurLexicalContext())) {
3120 Diag(Id.getLoc(), diag::err_omp_var_scope)
3121 << getOpenMPDirectiveName(Kind) << VD;
3122 bool IsDecl =
3124 Diag(VD->getLocation(),
3125 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3126 << VD;
3127 return ExprError();
3128 }
3129 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3130 // A threadprivate directive for namespace-scope variables must appear
3131 // outside any definition or declaration other than the namespace
3132 // definition itself.
3133 if (CanonicalVD->getDeclContext()->isNamespace() &&
3134 (!getCurLexicalContext()->isFileContext() ||
3135 !getCurLexicalContext()->Encloses(CanonicalVD->getDeclContext()))) {
3136 Diag(Id.getLoc(), diag::err_omp_var_scope)
3137 << getOpenMPDirectiveName(Kind) << VD;
3138 bool IsDecl =
3140 Diag(VD->getLocation(),
3141 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3142 << VD;
3143 return ExprError();
3144 }
3145 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3146 // A threadprivate directive for static block-scope variables must appear
3147 // in the scope of the variable and not in a nested scope.
3148 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3149 !isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
3150 Diag(Id.getLoc(), diag::err_omp_var_scope)
3151 << getOpenMPDirectiveName(Kind) << VD;
3152 bool IsDecl =
3154 Diag(VD->getLocation(),
3155 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3156 << VD;
3157 return ExprError();
3158 }
3159
3160 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3161 // A threadprivate directive must lexically precede all references to any
3162 // of the variables in its list.
3163 if (Kind == OMPD_threadprivate && VD->isUsed() &&
3164 !DSAStack->isThreadPrivate(VD)) {
3165 Diag(Id.getLoc(), diag::err_omp_var_used)
3166 << getOpenMPDirectiveName(Kind) << VD;
3167 return ExprError();
3168 }
3169
3170 QualType ExprType = VD->getType().getNonReferenceType();
3172 SourceLocation(), VD,
3173 /*RefersToEnclosingVariableOrCapture=*/false,
3174 Id.getLoc(), ExprType, VK_LValue);
3175}
3176
3179 ArrayRef<Expr *> VarList) {
3180 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3181 CurContext->addDecl(D);
3183 }
3184 return nullptr;
3185}
3186
3187namespace {
3188class LocalVarRefChecker final
3189 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3190 Sema &SemaRef;
3191
3192public:
3193 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3194 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3195 if (VD->hasLocalStorage()) {
3196 SemaRef.Diag(E->getBeginLoc(),
3197 diag::err_omp_local_var_in_threadprivate_init)
3198 << E->getSourceRange();
3199 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3200 << VD << VD->getSourceRange();
3201 return true;
3202 }
3203 }
3204 return false;
3205 }
3206 bool VisitStmt(const Stmt *S) {
3207 for (const Stmt *Child : S->children()) {
3208 if (Child && Visit(Child))
3209 return true;
3210 }
3211 return false;
3212 }
3213 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3214};
3215} // namespace
3216
3220 for (Expr *RefExpr : VarList) {
3221 auto *DE = cast<DeclRefExpr>(RefExpr);
3222 auto *VD = cast<VarDecl>(DE->getDecl());
3223 SourceLocation ILoc = DE->getExprLoc();
3224
3225 // Mark variable as used.
3226 VD->setReferenced();
3227 VD->markUsed(Context);
3228
3229 QualType QType = VD->getType();
3230 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3231 // It will be analyzed later.
3232 Vars.push_back(DE);
3233 continue;
3234 }
3235
3236 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3237 // A threadprivate variable must not have an incomplete type.
3238 if (RequireCompleteType(ILoc, VD->getType(),
3239 diag::err_omp_threadprivate_incomplete_type)) {
3240 continue;
3241 }
3242
3243 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3244 // A threadprivate variable must not have a reference type.
3245 if (VD->getType()->isReferenceType()) {
3246 Diag(ILoc, diag::err_omp_ref_type_arg)
3247 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
3248 bool IsDecl =
3250 Diag(VD->getLocation(),
3251 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3252 << VD;
3253 continue;
3254 }
3255
3256 // Check if this is a TLS variable. If TLS is not being supported, produce
3257 // the corresponding diagnostic.
3258 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3259 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3260 getLangOpts().OpenMPUseTLS &&
3261 getASTContext().getTargetInfo().isTLSSupported())) ||
3262 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3263 !VD->isLocalVarDecl())) {
3264 Diag(ILoc, diag::err_omp_var_thread_local)
3265 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3266 bool IsDecl =
3268 Diag(VD->getLocation(),
3269 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3270 << VD;
3271 continue;
3272 }
3273
3274 // Check if initial value of threadprivate variable reference variable with
3275 // local storage (it is not supported by runtime).
3276 if (const Expr *Init = VD->getAnyInitializer()) {
3277 LocalVarRefChecker Checker(*this);
3278 if (Checker.Visit(Init))
3279 continue;
3280 }
3281
3282 Vars.push_back(RefExpr);
3283 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3284 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3285 Context, SourceRange(Loc, Loc)));
3287 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3288 }
3289 OMPThreadPrivateDecl *D = nullptr;
3290 if (!Vars.empty()) {
3292 Vars);
3293 D->setAccess(AS_public);
3294 }
3295 return D;
3296}
3297
3298static OMPAllocateDeclAttr::AllocatorTypeTy
3299getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3300 if (!Allocator)
3301 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3302 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3303 Allocator->isInstantiationDependent() ||
3304 Allocator->containsUnexpandedParameterPack())
3305 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3306 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3307 llvm::FoldingSetNodeID AEId;
3308 const Expr *AE = Allocator->IgnoreParenImpCasts();
3309 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3310 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3311 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3312 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3313 llvm::FoldingSetNodeID DAEId;
3314 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3315 /*Canonical=*/true);
3316 if (AEId == DAEId) {
3317 AllocatorKindRes = AllocatorKind;
3318 break;
3319 }
3320 }
3321 return AllocatorKindRes;
3322}
3323
3325 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3326 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3327 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3328 return false;
3329 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3330 Expr *PrevAllocator = A->getAllocator();
3331 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3332 getAllocatorKind(S, Stack, PrevAllocator);
3333 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3334 if (AllocatorsMatch &&
3335 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3336 Allocator && PrevAllocator) {
3337 const Expr *AE = Allocator->IgnoreParenImpCasts();
3338 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3339 llvm::FoldingSetNodeID AEId, PAEId;
3340 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3341 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3342 AllocatorsMatch = AEId == PAEId;
3343 }
3344 if (!AllocatorsMatch) {
3345 SmallString<256> AllocatorBuffer;
3346 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3347 if (Allocator)
3348 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3349 SmallString<256> PrevAllocatorBuffer;
3350 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3351 if (PrevAllocator)
3352 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3353 S.getPrintingPolicy());
3354
3355 SourceLocation AllocatorLoc =
3356 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3357 SourceRange AllocatorRange =
3358 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3359 SourceLocation PrevAllocatorLoc =
3360 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3361 SourceRange PrevAllocatorRange =
3362 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3363 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3364 << (Allocator ? 1 : 0) << AllocatorStream.str()
3365 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3366 << AllocatorRange;
3367 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3368 << PrevAllocatorRange;
3369 return true;
3370 }
3371 return false;
3372}
3373
3374static void
3376 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3377 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3378 if (VD->hasAttr<OMPAllocateDeclAttr>())
3379 return;
3380 if (Alignment &&
3381 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3382 Alignment->isInstantiationDependent() ||
3383 Alignment->containsUnexpandedParameterPack()))
3384 // Apply later when we have a usable value.
3385 return;
3386 if (Allocator &&
3387 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3388 Allocator->isInstantiationDependent() ||
3389 Allocator->containsUnexpandedParameterPack()))
3390 return;
3391 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3392 Allocator, Alignment, SR);
3393 VD->addAttr(A);
3395 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3396}
3397
3400 ArrayRef<OMPClause *> Clauses,
3401 DeclContext *Owner) {
3402 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3403 Expr *Alignment = nullptr;
3404 Expr *Allocator = nullptr;
3405 if (Clauses.empty()) {
3406 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3407 // allocate directives that appear in a target region must specify an
3408 // allocator clause unless a requires directive with the dynamic_allocators
3409 // clause is present in the same compilation unit.
3410 if (LangOpts.OpenMPIsTargetDevice &&
3411 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3412 targetDiag(Loc, diag::err_expected_allocator_clause);
3413 } else {
3414 for (const OMPClause *C : Clauses)
3415 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3416 Allocator = AC->getAllocator();
3417 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3418 Alignment = AC->getAlignment();
3419 else
3420 llvm_unreachable("Unexpected clause on allocate directive");
3421 }
3422 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3423 getAllocatorKind(*this, DSAStack, Allocator);
3425 for (Expr *RefExpr : VarList) {
3426 auto *DE = cast<DeclRefExpr>(RefExpr);
3427 auto *VD = cast<VarDecl>(DE->getDecl());
3428
3429 // Check if this is a TLS variable or global register.
3430 if (VD->getTLSKind() != VarDecl::TLS_None ||
3431 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3432 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3433 !VD->isLocalVarDecl()))
3434 continue;
3435
3436 // If the used several times in the allocate directive, the same allocator
3437 // must be used.
3438 if (checkPreviousOMPAllocateAttribute(*this, DSAStack, RefExpr, VD,
3439 AllocatorKind, Allocator))
3440 continue;
3441
3442 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3443 // If a list item has a static storage type, the allocator expression in the
3444 // allocator clause must be a constant expression that evaluates to one of
3445 // the predefined memory allocator values.
3446 if (Allocator && VD->hasGlobalStorage()) {
3447 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3448 Diag(Allocator->getExprLoc(),
3449 diag::err_omp_expected_predefined_allocator)
3450 << Allocator->getSourceRange();
3451 bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
3453 Diag(VD->getLocation(),
3454 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3455 << VD;
3456 continue;
3457 }
3458 }
3459
3460 Vars.push_back(RefExpr);
3461 applyOMPAllocateAttribute(*this, VD, AllocatorKind, Allocator, Alignment,
3462 DE->getSourceRange());
3463 }
3464 if (Vars.empty())
3465 return nullptr;
3466 if (!Owner)
3467 Owner = getCurLexicalContext();
3468 auto *D = OMPAllocateDecl::Create(Context, Owner, Loc, Vars, Clauses);
3469 D->setAccess(AS_public);
3470 Owner->addDecl(D);
3472}
3473
3476 ArrayRef<OMPClause *> ClauseList) {
3477 OMPRequiresDecl *D = nullptr;
3478 if (!CurContext->isFileContext()) {
3479 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3480 } else {
3481 D = CheckOMPRequiresDecl(Loc, ClauseList);
3482 if (D) {
3483 CurContext->addDecl(D);
3484 DSAStack->addRequiresDecl(D);
3485 }
3486 }
3488}
3489
3491 OpenMPDirectiveKind DKind,
3492 ArrayRef<std::string> Assumptions,
3493 bool SkippedClauses) {
3494 if (!SkippedClauses && Assumptions.empty())
3495 Diag(Loc, diag::err_omp_no_clause_for_directive)
3496 << llvm::omp::getAllAssumeClauseOptions()
3497 << llvm::omp::getOpenMPDirectiveName(DKind);
3498
3499 auto *AA = OMPAssumeAttr::Create(Context, llvm::join(Assumptions, ","), Loc);
3500 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3501 OMPAssumeScoped.push_back(AA);
3502 return;
3503 }
3504
3505 // Global assumes without assumption clauses are ignored.
3506 if (Assumptions.empty())
3507 return;
3508
3509 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3510 "Unexpected omp assumption directive!");
3511 OMPAssumeGlobal.push_back(AA);
3512
3513 // The OMPAssumeGlobal scope above will take care of new declarations but
3514 // we also want to apply the assumption to existing ones, e.g., to
3515 // declarations in included headers. To this end, we traverse all existing
3516 // declaration contexts and annotate function declarations here.
3517 SmallVector<DeclContext *, 8> DeclContexts;
3518 auto *Ctx = CurContext;
3519 while (Ctx->getLexicalParent())
3520 Ctx = Ctx->getLexicalParent();
3521 DeclContexts.push_back(Ctx);
3522 while (!DeclContexts.empty()) {
3523 DeclContext *DC = DeclContexts.pop_back_val();
3524 for (auto *SubDC : DC->decls()) {
3525 if (SubDC->isInvalidDecl())
3526 continue;
3527 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3528 DeclContexts.push_back(CTD->getTemplatedDecl());
3529 llvm::append_range(DeclContexts, CTD->specializations());
3530 continue;
3531 }
3532 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3533 DeclContexts.push_back(DC);
3534 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3535 F->addAttr(AA);
3536 continue;
3537 }
3538 }
3539 }
3540}
3541
3543 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3544 OMPAssumeScoped.pop_back();
3545}
3546
3548 ArrayRef<OMPClause *> ClauseList) {
3549 /// For target specific clauses, the requires directive cannot be
3550 /// specified after the handling of any of the target regions in the
3551 /// current compilation unit.
3552 ArrayRef<SourceLocation> TargetLocations =
3553 DSAStack->getEncounteredTargetLocs();
3554 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3555 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3556 for (const OMPClause *CNew : ClauseList) {
3557 // Check if any of the requires clauses affect target regions.
3558 if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3559 isa<OMPUnifiedAddressClause>(CNew) ||
3560 isa<OMPReverseOffloadClause>(CNew) ||
3561 isa<OMPDynamicAllocatorsClause>(CNew)) {
3562 Diag(Loc, diag::err_omp_directive_before_requires)
3563 << "target" << getOpenMPClauseName(CNew->getClauseKind());
3564 for (SourceLocation TargetLoc : TargetLocations) {
3565 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3566 << "target";
3567 }
3568 } else if (!AtomicLoc.isInvalid() &&
3569 isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3570 Diag(Loc, diag::err_omp_directive_before_requires)
3571 << "atomic" << getOpenMPClauseName(CNew->getClauseKind());
3572 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3573 << "atomic";
3574 }
3575 }
3576 }
3577
3578 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3580 ClauseList);
3581 return nullptr;
3582}
3583
3584static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3585 const ValueDecl *D,
3586 const DSAStackTy::DSAVarData &DVar,
3587 bool IsLoopIterVar) {
3588 if (DVar.RefExpr) {
3589 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3590 << getOpenMPClauseName(DVar.CKind);
3591 return;
3592 }
3593 enum {
3594 PDSA_StaticMemberShared,
3595 PDSA_StaticLocalVarShared,
3596 PDSA_LoopIterVarPrivate,
3597 PDSA_LoopIterVarLinear,
3598 PDSA_LoopIterVarLastprivate,
3599 PDSA_ConstVarShared,
3600 PDSA_GlobalVarShared,
3601 PDSA_TaskVarFirstprivate,
3602 PDSA_LocalVarPrivate,
3603 PDSA_Implicit
3604 } Reason = PDSA_Implicit;
3605 bool ReportHint = false;
3606 auto ReportLoc = D->getLocation();
3607 auto *VD = dyn_cast<VarDecl>(D);
3608 if (IsLoopIterVar) {
3609 if (DVar.CKind == OMPC_private)
3610 Reason = PDSA_LoopIterVarPrivate;
3611 else if (DVar.CKind == OMPC_lastprivate)
3612 Reason = PDSA_LoopIterVarLastprivate;
3613 else
3614 Reason = PDSA_LoopIterVarLinear;
3615 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3616 DVar.CKind == OMPC_firstprivate) {
3617 Reason = PDSA_TaskVarFirstprivate;
3618 ReportLoc = DVar.ImplicitDSALoc;
3619 } else if (VD && VD->isStaticLocal())
3620 Reason = PDSA_StaticLocalVarShared;
3621 else if (VD && VD->isStaticDataMember())
3622 Reason = PDSA_StaticMemberShared;
3623 else if (VD && VD->isFileVarDecl())
3624 Reason = PDSA_GlobalVarShared;
3625 else if (D->getType().isConstant(SemaRef.getASTContext()))
3626 Reason = PDSA_ConstVarShared;
3627 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3628 ReportHint = true;
3629 Reason = PDSA_LocalVarPrivate;
3630 }
3631 if (Reason != PDSA_Implicit) {
3632 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3633 << Reason << ReportHint
3634 << getOpenMPDirectiveName(Stack->getCurrentDirective());
3635 } else if (DVar.ImplicitDSALoc.isValid()) {
3636 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3637 << getOpenMPClauseName(DVar.CKind);
3638 }
3639}
3640
3643 bool IsAggregateOrDeclareTarget) {
3645 switch (M) {
3646 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3647 Kind = OMPC_MAP_alloc;
3648 break;
3649 case OMPC_DEFAULTMAP_MODIFIER_to:
3650 Kind = OMPC_MAP_to;
3651 break;
3652 case OMPC_DEFAULTMAP_MODIFIER_from:
3653 Kind = OMPC_MAP_from;
3654 break;
3655 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3656 Kind = OMPC_MAP_tofrom;
3657 break;
3658 case OMPC_DEFAULTMAP_MODIFIER_present:
3659 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3660 // If implicit-behavior is present, each variable referenced in the
3661 // construct in the category specified by variable-category is treated as if
3662 // it had been listed in a map clause with the map-type of alloc and
3663 // map-type-modifier of present.
3664 Kind = OMPC_MAP_alloc;
3665 break;
3666 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3668 llvm_unreachable("Unexpected defaultmap implicit behavior");
3669 case OMPC_DEFAULTMAP_MODIFIER_none:
3670 case OMPC_DEFAULTMAP_MODIFIER_default:
3672 // IsAggregateOrDeclareTarget could be true if:
3673 // 1. the implicit behavior for aggregate is tofrom
3674 // 2. it's a declare target link
3675 if (IsAggregateOrDeclareTarget) {
3676 Kind = OMPC_MAP_tofrom;
3677 break;
3678 }
3679 llvm_unreachable("Unexpected defaultmap implicit behavior");
3680 }
3681 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3682 return Kind;
3683}
3684
3685namespace {
3686class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3687 DSAStackTy *Stack;
3688 Sema &SemaRef;
3689 bool ErrorFound = false;
3690 bool TryCaptureCXXThisMembers = false;
3691 CapturedStmt *CS = nullptr;
3692 const static unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3693 llvm::SmallVector<Expr *, 4> ImplicitFirstprivate;
3694 llvm::SmallVector<Expr *, 4> ImplicitPrivate;
3695 llvm::SmallVector<Expr *, 4> ImplicitMap[DefaultmapKindNum][OMPC_MAP_delete];
3697 ImplicitMapModifier[DefaultmapKindNum];
3698 Sema::VarsWithInheritedDSAType VarsWithInheritedDSA;
3699 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3700
3701 void VisitSubCaptures(OMPExecutableDirective *S) {
3702 // Check implicitly captured variables.
3703 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3704 return;
3705 if (S->getDirectiveKind() == OMPD_atomic ||
3706 S->getDirectiveKind() == OMPD_critical ||
3707 S->getDirectiveKind() == OMPD_section ||
3708 S->getDirectiveKind() == OMPD_master ||
3709 S->getDirectiveKind() == OMPD_masked ||
3710 S->getDirectiveKind() == OMPD_scope ||
3711 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3712 Visit(S->getAssociatedStmt());
3713 return;
3714 }
3715 visitSubCaptures(S->getInnermostCapturedStmt());
3716 // Try to capture inner this->member references to generate correct mappings
3717 // and diagnostics.
3718 if (TryCaptureCXXThisMembers ||
3719 (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
3720 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3721 [](const CapturedStmt::Capture &C) {
3722 return C.capturesThis();
3723 }))) {
3724 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3725 TryCaptureCXXThisMembers = true;
3726 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3727 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3728 }
3729 // In tasks firstprivates are not captured anymore, need to analyze them
3730 // explicitly.
3731 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3732 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3733 for (OMPClause *C : S->clauses())
3734 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3735 for (Expr *Ref : FC->varlists())
3736 Visit(Ref);
3737 }
3738 }
3739 }
3740
3741public:
3742 void VisitDeclRefExpr(DeclRefExpr *E) {
3743 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3746 return;
3747 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3748 // Check the datasharing rules for the expressions in the clauses.
3749 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3750 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3751 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3752 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3753 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3754 Visit(CED->getInit());
3755 return;
3756 }
3757 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3758 // Do not analyze internal variables and do not enclose them into
3759 // implicit clauses.
3760 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3761 return;
3762 VD = VD->getCanonicalDecl();
3763 // Skip internally declared variables.
3764 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3765 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3766 !Stack->isImplicitTaskFirstprivate(VD))
3767 return;
3768 // Skip allocators in uses_allocators clauses.
3769 if (Stack->isUsesAllocatorsDecl(VD))
3770 return;
3771
3772 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3773 // Check if the variable has explicit DSA set and stop analysis if it so.
3774 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3775 return;
3776
3777 // Skip internally declared static variables.
3778 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3779 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3780 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3781 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3782 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3783 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3784 !Stack->isImplicitTaskFirstprivate(VD))
3785 return;
3786
3787 SourceLocation ELoc = E->getExprLoc();
3788 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3789 // The default(none) clause requires that each variable that is referenced
3790 // in the construct, and does not have a predetermined data-sharing
3791 // attribute, must have its data-sharing attribute explicitly determined
3792 // by being listed in a data-sharing attribute clause.
3793 if (DVar.CKind == OMPC_unknown &&
3794 (Stack->getDefaultDSA() == DSA_none ||
3795 Stack->getDefaultDSA() == DSA_private ||
3796 Stack->getDefaultDSA() == DSA_firstprivate) &&
3797 isImplicitOrExplicitTaskingRegion(DKind) &&
3798 VarsWithInheritedDSA.count(VD) == 0) {
3799 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3800 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3801 Stack->getDefaultDSA() == DSA_private)) {
3802 DSAStackTy::DSAVarData DVar =
3803 Stack->getImplicitDSA(VD, /*FromParent=*/false);
3804 InheritedDSA = DVar.CKind == OMPC_unknown;
3805 }
3806 if (InheritedDSA)
3807 VarsWithInheritedDSA[VD] = E;
3808 if (Stack->getDefaultDSA() == DSA_none)
3809 return;
3810 }
3811
3812 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3813 // If implicit-behavior is none, each variable referenced in the
3814 // construct that does not have a predetermined data-sharing attribute
3815 // and does not appear in a to or link clause on a declare target
3816 // directive must be listed in a data-mapping attribute clause, a
3817 // data-sharing attribute clause (including a data-sharing attribute
3818 // clause on a combined construct where target. is one of the
3819 // constituent constructs), or an is_device_ptr clause.
3820 OpenMPDefaultmapClauseKind ClauseKind =
3822 if (SemaRef.getLangOpts().OpenMP >= 50) {
3823 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3824 OMPC_DEFAULTMAP_MODIFIER_none;
3825 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3826 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3827 // Only check for data-mapping attribute and is_device_ptr here
3828 // since we have already make sure that the declaration does not
3829 // have a data-sharing attribute above
3830 if (!Stack->checkMappableExprComponentListsForDecl(
3831 VD, /*CurrentRegionOnly=*/true,
3833 MapExprComponents,
3835 auto MI = MapExprComponents.rbegin();
3836 auto ME = MapExprComponents.rend();
3837 return MI != ME && MI->getAssociatedDeclaration() == VD;
3838 })) {
3839 VarsWithInheritedDSA[VD] = E;
3840 return;
3841 }
3842 }
3843 }
3844 if (SemaRef.getLangOpts().OpenMP > 50) {
3845 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3846 OMPC_DEFAULTMAP_MODIFIER_present;
3847 if (IsModifierPresent) {
3848 if (!llvm::is_contained(ImplicitMapModifier[ClauseKind],
3849 OMPC_MAP_MODIFIER_present)) {
3850 ImplicitMapModifier[ClauseKind].push_back(
3851 OMPC_MAP_MODIFIER_present);
3852 }
3853 }
3854 }
3855
3857 !Stack->isLoopControlVariable(VD).first) {
3858 if (!Stack->checkMappableExprComponentListsForDecl(
3859 VD, /*CurrentRegionOnly=*/true,
3861 StackComponents,
3863 if (SemaRef.LangOpts.OpenMP >= 50)
3864 return !StackComponents.empty();
3865 // Variable is used if it has been marked as an array, array
3866 // section, array shaping or the variable iself.
3867 return StackComponents.size() == 1 ||
3868 llvm::all_of(
3869 llvm::drop_begin(llvm::reverse(StackComponents)),
3870 [](const OMPClauseMappableExprCommon::
3871 MappableComponent &MC) {
3872 return MC.getAssociatedDeclaration() ==
3873 nullptr &&
3874 (isa<OMPArraySectionExpr>(
3875 MC.getAssociatedExpression()) ||
3876 isa<OMPArrayShapingExpr>(
3877 MC.getAssociatedExpression()) ||
3878 isa<ArraySubscriptExpr>(
3879 MC.getAssociatedExpression()));
3880 });
3881 })) {
3882 bool IsFirstprivate = false;
3883 // By default lambdas are captured as firstprivates.
3884 if (const auto *RD =
3886 IsFirstprivate = RD->isLambda();
3887 IsFirstprivate =
3888 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3889 if (IsFirstprivate) {
3890 ImplicitFirstprivate.emplace_back(E);
3891 } else {
3893 Stack->getDefaultmapModifier(ClauseKind);
3895 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3896 ImplicitMap[ClauseKind][Kind].emplace_back(E);
3897 }
3898 return;
3899 }
3900 }
3901
3902 // OpenMP [2.9.3.6, Restrictions, p.2]
3903 // A list item that appears in a reduction clause of the innermost
3904 // enclosing worksharing or parallel construct may not be accessed in an
3905 // explicit task.
3906 DVar = Stack->hasInnermostDSA(
3907 VD,
3908 [](OpenMPClauseKind C, bool AppliedToPointee) {
3909 return C == OMPC_reduction && !AppliedToPointee;
3910 },
3911 [](OpenMPDirectiveKind K) {
3912 return isOpenMPParallelDirective(K) ||
3914 },
3915 /*FromParent=*/true);
3916 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3917 ErrorFound = true;
3918 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3919 reportOriginalDsa(SemaRef, Stack, VD, DVar);
3920 return;
3921 }
3922
3923 // Define implicit data-sharing attributes for task.
3924 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
3925 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
3926 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3927 DVar.CKind == OMPC_firstprivate) ||
3928 (Stack->getDefaultDSA() == DSA_private &&
3929 DVar.CKind == OMPC_private)) &&
3930 !DVar.RefExpr)) &&
3931 !Stack->isLoopControlVariable(VD).first) {
3932 if (Stack->getDefaultDSA() == DSA_private)
3933 ImplicitPrivate.push_back(E);
3934 else
3935 ImplicitFirstprivate.push_back(E);
3936 return;
3937 }
3938
3939 // Store implicitly used globals with declare target link for parent
3940 // target.
3941 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
3942 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3943 Stack->addToParentTargetRegionLinkGlobals(E);
3944 return;
3945 }
3946 }
3947 }
3948 void VisitMemberExpr(MemberExpr *E) {
3949 if (E->isTypeDependent() || E->isValueDependent() ||
3951 return;
3952 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
3953 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3954 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
3955 if (!FD)
3956 return;
3957 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
3958 // Check if the variable has explicit DSA set and stop analysis if it
3959 // so.
3960 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
3961 return;
3962
3964 !Stack->isLoopControlVariable(FD).first &&
3965 !Stack->checkMappableExprComponentListsForDecl(
3966 FD, /*CurrentRegionOnly=*/true,
3968 StackComponents,
3970 return isa<CXXThisExpr>(
3971 cast<MemberExpr>(
3972 StackComponents.back().getAssociatedExpression())
3973 ->getBase()
3974 ->IgnoreParens());
3975 })) {
3976 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
3977 // A bit-field cannot appear in a map clause.
3978 //
3979 if (FD->isBitField())
3980 return;
3981
3982 // Check to see if the member expression is referencing a class that
3983 // has already been explicitly mapped
3984 if (Stack->isClassPreviouslyMapped(TE->getType()))
3985 return;
3986
3988 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
3989 OpenMPDefaultmapClauseKind ClauseKind =
3992 Modifier, /*IsAggregateOrDeclareTarget*/ true);
3993 ImplicitMap[ClauseKind][Kind].emplace_back(E);
3994 return;
3995 }
3996
3997 SourceLocation ELoc = E->getExprLoc();
3998 // OpenMP [2.9.3.6, Restrictions, p.2]
3999 // A list item that appears in a reduction clause of the innermost
4000 // enclosing worksharing or parallel construct may not be accessed in
4001 // an explicit task.
4002 DVar = Stack->hasInnermostDSA(
4003 FD,
4004 [](OpenMPClauseKind C, bool AppliedToPointee) {
4005 return C == OMPC_reduction && !AppliedToPointee;
4006 },
4007 [](OpenMPDirectiveKind K) {
4008 return isOpenMPParallelDirective(K) ||
4010 },
4011 /*FromParent=*/true);
4012 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4013 ErrorFound = true;
4014 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4015 reportOriginalDsa(SemaRef, Stack, FD, DVar);
4016 return;
4017 }
4018
4019 // Define implicit data-sharing attributes for task.
4020 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4021 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4022 !Stack->isLoopControlVariable(FD).first) {
4023 // Check if there is a captured expression for the current field in the
4024 // region. Do not mark it as firstprivate unless there is no captured
4025 // expression.
4026 // TODO: try to make it firstprivate.
4027 if (DVar.CKind != OMPC_unknown)
4028 ImplicitFirstprivate.push_back(E);
4029 }
4030 return;
4031 }
4034 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4035 Stack->getCurrentDirective(),
4036 /*NoDiagnose=*/true))
4037 return;
4038 const auto *VD = cast<ValueDecl>(
4039 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4040 if (!Stack->checkMappableExprComponentListsForDecl(
4041 VD, /*CurrentRegionOnly=*/true,
4042 [&CurComponents](
4044 StackComponents,
4046 auto CCI = CurComponents.rbegin();
4047 auto CCE = CurComponents.rend();
4048 for (const auto &SC : llvm::reverse(StackComponents)) {
4049 // Do both expressions have the same kind?
4050 if (CCI->getAssociatedExpression()->getStmtClass() !=
4051 SC.getAssociatedExpression()->getStmtClass())
4052 if (!((isa<OMPArraySectionExpr>(
4053 SC.getAssociatedExpression()) ||
4054 isa<OMPArrayShapingExpr>(
4055 SC.getAssociatedExpression())) &&
4056 isa<ArraySubscriptExpr>(
4057 CCI->getAssociatedExpression())))
4058 return false;
4059
4060 const Decl *CCD = CCI->getAssociatedDeclaration();
4061 const Decl *SCD = SC.getAssociatedDeclaration();
4062 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4063 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4064 if (SCD != CCD)
4065 return false;
4066 std::advance(CCI, 1);
4067 if (CCI == CCE)
4068 break;
4069 }
4070 return true;
4071 })) {
4072 Visit(E->getBase());
4073 }
4074 } else if (!TryCaptureCXXThisMembers) {
4075 Visit(E->getBase());
4076 }
4077 }
4078 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4079 for (OMPClause *C : S->clauses()) {
4080 // Skip analysis of arguments of private clauses for task|target
4081 // directives.
4082 if (isa_and_nonnull<OMPPrivateClause>(C))
4083 continue;
4084 // Skip analysis of arguments of implicitly defined firstprivate clause
4085 // for task|target directives.
4086 // Skip analysis of arguments of implicitly defined map clause for target
4087 // directives.
4088 if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
4089 C->isImplicit() &&
4090 !isOpenMPTaskingDirective(Stack->getCurrentDirective()))) {
4091 for (Stmt *CC : C->children()) {
4092 if (CC)
4093 Visit(CC);
4094 }
4095 }
4096 }
4097 // Check implicitly captured variables.
4098 VisitSubCaptures(S);
4099 }
4100
4101 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) {
4102 // Loop transformation directives do not introduce data sharing
4103 VisitStmt(S);
4104 }
4105
4106 void VisitCallExpr(CallExpr *S) {
4107 for (Stmt *C : S->arguments()) {
4108 if (C) {
4109 // Check implicitly captured variables in the task-based directives to
4110 // check if they must be firstprivatized.
4111 Visit(C);
4112 }
4113 }
4114 if (Expr *Callee = S->getCallee()) {
4115 auto *CI = Callee->IgnoreParenImpCasts();
4116 if (auto *CE = dyn_cast<MemberExpr>(CI))
4117 Visit(CE->getBase());
4118 else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4119 Visit(CE);
4120 }
4121 }
4122 void VisitStmt(Stmt *S) {
4123 for (Stmt *C : S->children()) {
4124 if (C) {
4125 // Check implicitly captured variables in the task-based directives to
4126 // check if they must be firstprivatized.
4127 Visit(C);
4128 }
4129 }
4130 }
4131
4132 void visitSubCaptures(CapturedStmt *S) {
4133 for (const CapturedStmt::Capture &Cap : S->captures()) {
4134 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4135 continue;
4136 VarDecl *VD = Cap.getCapturedVar();
4137 // Do not try to map the variable if it or its sub-component was mapped
4138 // already.
4139 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
4140 Stack->checkMappableExprComponentListsForDecl(
4141 VD, /*CurrentRegionOnly=*/true,
4143 OpenMPClauseKind) { return true; }))
4144 continue;
4146 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4147 Cap.getLocation(), /*RefersToCapture=*/true);
4148 Visit(DRE);
4149 }
4150 }
4151 bool isErrorFound() const { return ErrorFound; }
4152 ArrayRef<Expr *> getImplicitFirstprivate() const {
4153 return ImplicitFirstprivate;
4154 }
4155 ArrayRef<Expr *> getImplicitPrivate() const { return ImplicitPrivate; }
4157 OpenMPMapClauseKind MK) const {
4158 return ImplicitMap[DK][MK];
4159 }
4161 getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind) const {
4162 return ImplicitMapModifier[Kind];
4163 }
4164 const Sema::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4165 return VarsWithInheritedDSA;
4166 }
4167
4168 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4169 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4170 // Process declare target link variables for the target directives.
4171 if (isOpenMPTargetExecutionDirective(S->getCurrentDirective())) {
4172 for (DeclRefExpr *E : Stack->getLinkGlobals())
4173 Visit(E);
4174 }
4175 }
4176};
4177} // namespace
4178
4179static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4180 OpenMPDirectiveKind DKind,
4181 bool ScopeEntry) {
4184 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4185 if (isOpenMPTeamsDirective(DKind))
4186 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4187 if (isOpenMPParallelDirective(DKind))
4188 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4190 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4191 if (isOpenMPSimdDirective(DKind))
4192 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4193 Stack->handleConstructTrait(Traits, ScopeEntry);
4194}
4195
4197 switch (DKind) {
4198 case OMPD_parallel:
4199 case OMPD_parallel_for:
4200 case OMPD_parallel_for_simd:
4201 case OMPD_parallel_sections:
4202 case OMPD_parallel_master:
4203 case OMPD_parallel_masked:
4204 case OMPD_parallel_loop:
4205 case OMPD_teams:
4206 case OMPD_teams_distribute:
4207 case OMPD_teams_distribute_simd: {
4208 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4209 QualType KmpInt32PtrTy =
4211 Sema::CapturedParamNameType Params[] = {
4212 std::make_pair(".global_tid.", KmpInt32PtrTy),
4213 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4214 std::make_pair(StringRef(), QualType()) // __context with shared vars
4215 };
4216 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4217 Params);
4218 break;
4219 }
4220 case OMPD_target_teams:
4221 case OMPD_target_parallel:
4222 case OMPD_target_parallel_for:
4223 case OMPD_target_parallel_for_simd:
4224 case OMPD_target_parallel_loop:
4225 case OMPD_target_teams_distribute:
4226 case OMPD_target_teams_distribute_simd: {
4227 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4229 QualType KmpInt32PtrTy =
4231 QualType Args[] = {VoidPtrTy};
4233 EPI.Variadic = true;
4234 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4235 Sema::CapturedParamNameType Params[] = {
4236 std::make_pair(".global_tid.", KmpInt32Ty),
4237 std::make_pair(".part_id.", KmpInt32PtrTy),
4238 std::make_pair(".privates.", VoidPtrTy),
4239 std::make_pair(
4240 ".copy_fn.",
4242 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4243 std::make_pair(StringRef(), QualType()) // __context with shared vars
4244 };
4245 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4246 Params, /*OpenMPCaptureLevel=*/0);
4247 // Mark this captured region as inlined, because we don't use outlined
4248 // function directly.
4250 AlwaysInlineAttr::CreateImplicit(
4251 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4253 if (getLangOpts().OpenMPIsTargetDevice)
4254 ParamsTarget.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4255 ParamsTarget.push_back(
4256 std::make_pair(StringRef(), QualType())); // __context with shared vars;
4257 // Start a captured region for 'target' with no implicit parameters.
4258 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4259 ParamsTarget,
4260 /*OpenMPCaptureLevel=*/1);
4261 Sema::CapturedParamNameType ParamsTeamsOrParallel[] = {
4262 std::make_pair(".global_tid.", KmpInt32PtrTy),
4263 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4264 std::make_pair(StringRef(), QualType()) // __context with shared vars
4265 };
4266 // Start a captured region for 'teams' or 'parallel'. Both regions have
4267 // the same implicit parameters.
4268 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4269 ParamsTeamsOrParallel, /*OpenMPCaptureLevel=*/2);
4270 break;
4271 }
4272 case OMPD_target:
4273 case OMPD_target_simd: {
4274 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4276 QualType KmpInt32PtrTy =
4278 QualType Args[] = {VoidPtrTy};
4280 EPI.Variadic = true;
4281 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4282 Sema::CapturedParamNameType Params[] = {
4283 std::make_pair(".global_tid.", KmpInt32Ty),
4284 std::make_pair(".part_id.", KmpInt32PtrTy),
4285 std::make_pair(".privates.", VoidPtrTy),
4286 std::make_pair(
4287 ".copy_fn.",
4289 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4290 std::make_pair(StringRef(), QualType()) // __context with shared vars
4291 };
4292 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4293 Params, /*OpenMPCaptureLevel=*/0);
4294 // Mark this captured region as inlined, because we don't use outlined
4295 // function directly.
4297 AlwaysInlineAttr::CreateImplicit(
4298 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4300 if (getLangOpts().OpenMPIsTargetDevice)
4301 ParamsTarget.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4302 ParamsTarget.push_back(
4303 std::make_pair(StringRef(), QualType())); // __context with shared vars;
4304 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4305 ParamsTarget,
4306 /*OpenMPCaptureLevel=*/1);
4307 break;
4308 }
4309 case OMPD_atomic:
4310 case OMPD_critical:
4311 case OMPD_section:
4312 case OMPD_master:
4313 case OMPD_masked:
4314 case OMPD_tile:
4315 case OMPD_unroll:
4316 break;
4317 case OMPD_loop:
4318 // TODO: 'loop' may require additional parameters depending on the binding.
4319 // Treat similar to OMPD_simd/OMPD_for for now.
4320 case OMPD_simd:
4321 case OMPD_for:
4322 case OMPD_for_simd:
4323 case OMPD_sections:
4324 case OMPD_single:
4325 case OMPD_taskgroup:
4326 case OMPD_distribute:
4327 case OMPD_distribute_simd:
4328 case OMPD_ordered:
4329 case OMPD_scope:
4330 case OMPD_target_data:
4331 case OMPD_dispatch: {
4332 Sema::CapturedParamNameType Params[] = {
4333 std::make_pair(StringRef(), QualType()) // __context with shared vars
4334 };
4335 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4336 Params);
4337 break;
4338 }
4339 case OMPD_task: {
4340 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4342 QualType KmpInt32PtrTy =
4344 QualType Args[] = {VoidPtrTy};
4346 EPI.Variadic = true;
4347 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4348 Sema::CapturedParamNameType Params[] = {
4349 std::make_pair(".global_tid.", KmpInt32Ty),
4350 std::make_pair(".part_id.", KmpInt32PtrTy),
4351 std::make_pair(".privates.", VoidPtrTy),
4352 std::make_pair(
4353 ".copy_fn.",
4355 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4356 std::make_pair(StringRef(), QualType()) // __context with shared vars
4357 };
4358 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4359 Params);
4360 // Mark this captured region as inlined, because we don't use outlined
4361 // function directly.
4363 AlwaysInlineAttr::CreateImplicit(
4364 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4365 break;
4366 }
4367 case OMPD_taskloop:
4368 case OMPD_taskloop_simd:
4369 case OMPD_master_taskloop:
4370 case OMPD_masked_taskloop:
4371 case OMPD_masked_taskloop_simd:
4372 case OMPD_master_taskloop_simd: {
4373 QualType KmpInt32Ty =
4374 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4375 .withConst();
4376 QualType KmpUInt64Ty =
4377 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4378 .withConst();
4379 QualType KmpInt64Ty =
4380 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4381 .withConst();
4383 QualType KmpInt32PtrTy =
4385 QualType Args[] = {VoidPtrTy};
4387 EPI.Variadic = true;
4388 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4389 Sema::CapturedParamNameType Params[] = {
4390 std::make_pair(".global_tid.", KmpInt32Ty),
4391 std::make_pair(".part_id.", KmpInt32PtrTy),
4392 std::make_pair(".privates.", VoidPtrTy),
4393 std::make_pair(
4394 ".copy_fn.",
4396 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4397 std::make_pair(".lb.", KmpUInt64Ty),
4398 std::make_pair(".ub.", KmpUInt64Ty),
4399 std::make_pair(".st.", KmpInt64Ty),
4400 std::make_pair(".liter.", KmpInt32Ty),
4401 std::make_pair(".reductions.", VoidPtrTy),
4402 std::make_pair(StringRef(), QualType()) // __context with shared vars
4403 };
4404 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4405 Params);
4406 // Mark this captured region as inlined, because we don't use outlined
4407 // function directly.
4409 AlwaysInlineAttr::CreateImplicit(
4410 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4411 break;
4412 }
4413 case OMPD_parallel_masked_taskloop:
4414 case OMPD_parallel_masked_taskloop_simd:
4415 case OMPD_parallel_master_taskloop:
4416 case OMPD_parallel_master_taskloop_simd: {
4417 QualType KmpInt32Ty =
4418 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4419 .withConst();
4420 QualType KmpUInt64Ty =
4421 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4422 .withConst();
4423 QualType KmpInt64Ty =
4424 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4425 .withConst();
4427 QualType KmpInt32PtrTy =
4429 Sema::CapturedParamNameType ParamsParallel[] = {
4430 std::make_pair(".global_tid.", KmpInt32PtrTy),
4431 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4432 std::make_pair(StringRef(), QualType()) // __context with shared vars
4433 };
4434 // Start a captured region for 'parallel'.
4435 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4436 ParamsParallel, /*OpenMPCaptureLevel=*/0);
4437 QualType Args[] = {VoidPtrTy};
4439 EPI.Variadic = true;
4440 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4441 Sema::CapturedParamNameType Params[] = {
4442 std::make_pair(".global_tid.", KmpInt32Ty),
4443 std::make_pair(".part_id.", KmpInt32PtrTy),
4444 std::make_pair(".privates.", VoidPtrTy),
4445 std::make_pair(
4446 ".copy_fn.",
4448 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4449 std::make_pair(".lb.", KmpUInt64Ty),
4450 std::make_pair(".ub.", KmpUInt64Ty),
4451 std::make_pair(".st.", KmpInt64Ty),
4452 std::make_pair(".liter.", KmpInt32Ty),
4453 std::make_pair(".reductions.", VoidPtrTy),
4454 std::make_pair(StringRef(), QualType()) // __context with shared vars
4455 };
4456 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4457 Params, /*OpenMPCaptureLevel=*/1);
4458 // Mark this captured region as inlined, because we don't use outlined
4459 // function directly.
4461 AlwaysInlineAttr::CreateImplicit(
4462 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4463 break;
4464 }
4465 case OMPD_distribute_parallel_for_simd:
4466 case OMPD_distribute_parallel_for: {
4467 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4468 QualType KmpInt32PtrTy =
4470 Sema::CapturedParamNameType Params[] = {
4471 std::make_pair(".global_tid.", KmpInt32PtrTy),
4472 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4473 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4474 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4475 std::make_pair(StringRef(), QualType()) // __context with shared vars
4476 };
4477 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4478 Params);
4479 break;
4480 }
4481 case OMPD_target_teams_loop:
4482 case OMPD_target_teams_distribute_parallel_for:
4483 case OMPD_target_teams_distribute_parallel_for_simd: {
4484 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4485 QualType KmpInt32PtrTy =
4488
4489 QualType Args[] = {VoidPtrTy};
4491 EPI.Variadic = true;
4492 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4493 Sema::CapturedParamNameType Params[] = {
4494 std::make_pair(".global_tid.", KmpInt32Ty),
4495 std::make_pair(".part_id.", KmpInt32PtrTy),
4496 std::make_pair(".privates.", VoidPtrTy),
4497 std::make_pair(
4498 ".copy_fn.",
4500 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4501 std::make_pair(StringRef(), QualType()) // __context with shared vars
4502 };
4503 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4504 Params, /*OpenMPCaptureLevel=*/0);
4505 // Mark this captured region as inlined, because we don't use outlined
4506 // function directly.
4508 AlwaysInlineAttr::CreateImplicit(
4509 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4511 if (getLangOpts().OpenMPIsTargetDevice)
4512 ParamsTarget.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4513 ParamsTarget.push_back(
4514 std::make_pair(StringRef(), QualType())); // __context with shared vars;
4515 // Start a captured region for 'target' with no implicit parameters.
4516 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4517 ParamsTarget, /*OpenMPCaptureLevel=*/1);
4518
4519 Sema::CapturedParamNameType ParamsTeams[] = {
4520 std::make_pair(".global_tid.", KmpInt32PtrTy),
4521 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4522 std::make_pair(StringRef(), QualType()) // __context with shared vars
4523 };
4524 // Start a captured region for 'target' with no implicit parameters.
4525 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4526 ParamsTeams, /*OpenMPCaptureLevel=*/2);
4527
4528 Sema::CapturedParamNameType ParamsParallel[] = {
4529 std::make_pair(".global_tid.", KmpInt32PtrTy),
4530 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4531 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4532 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4533 std::make_pair(StringRef(), QualType()) // __context with shared vars
4534 };
4535 // Start a captured region for 'teams' or 'parallel'. Both regions have
4536 // the same implicit parameters.
4537 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4538 ParamsParallel, /*OpenMPCaptureLevel=*/3);
4539 break;
4540 }
4541
4542 case OMPD_teams_loop:
4543 case OMPD_teams_distribute_parallel_for:
4544 case OMPD_teams_distribute_parallel_for_simd: {
4545 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4546 QualType KmpInt32PtrTy =
4548
4549 Sema::CapturedParamNameType ParamsTeams[] = {
4550 std::make_pair(".global_tid.", KmpInt32PtrTy),
4551 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4552 std::make_pair(StringRef(), QualType()) // __context with shared vars
4553 };
4554 // Start a captured region for 'target' with no implicit parameters.
4555 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4556 ParamsTeams, /*OpenMPCaptureLevel=*/0);
4557
4558 Sema::CapturedParamNameType ParamsParallel[] = {
4559 std::make_pair(".global_tid.", KmpInt32PtrTy),
4560 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4561 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4562 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4563 std::make_pair(StringRef(), QualType()) // __context with shared vars
4564 };
4565 // Start a captured region for 'teams' or 'parallel'. Both regions have
4566 // the same implicit parameters.
4567 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4568 ParamsParallel, /*OpenMPCaptureLevel=*/1);
4569 break;
4570 }
4571 case OMPD_target_update:
4572 case OMPD_target_enter_data:
4573 case OMPD_target_exit_data: {
4574 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4576 QualType KmpInt32PtrTy =
4578 QualType Args[] = {VoidPtrTy};
4580 EPI.Variadic = true;
4581 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4582 Sema::CapturedParamNameType Params[] = {
4583 std::make_pair(".global_tid.", KmpInt32Ty),
4584 std::make_pair(".part_id.", KmpInt32PtrTy),
4585 std::make_pair(".privates.", VoidPtrTy),
4586 std::make_pair(
4587 ".copy_fn.",
4589 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4590 std::make_pair(StringRef(), QualType()) // __context with shared vars
4591 };
4592 ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
4593 Params);
4594 // Mark this captured region as inlined, because we don't use outlined
4595 // function directly.
4597 AlwaysInlineAttr::CreateImplicit(
4598 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4599 break;
4600 }
4601 case OMPD_threadprivate:
4602 case OMPD_allocate:
4603 case OMPD_taskyield:
4604 case OMPD_error:
4605 case OMPD_barrier:
4606 case OMPD_taskwait:
4607 case OMPD_cancellation_point:
4608 case OMPD_cancel:
4609 case OMPD_flush:
4610 case OMPD_depobj:
4611 case OMPD_scan:
4612 case OMPD_declare_reduction:
4613 case OMPD_declare_mapper:
4614 case OMPD_declare_simd:
4615 case OMPD_declare_target:
4616 case OMPD_end_declare_target:
4617 case OMPD_requires:
4618 case OMPD_declare_variant:
4619 case OMPD_begin_declare_variant:
4620 case OMPD_end_declare_variant:
4621 case OMPD_metadirective:
4622 llvm_unreachable("OpenMP Directive is not allowed");
4623 case OMPD_unknown:
4624 default:
4625 llvm_unreachable("Unknown OpenMP directive");
4626 }
4627 DSAStack->setContext(CurContext);
4628 handleDeclareVariantConstructTrait(DSAStack, DKind, /* ScopeEntry */ true);
4629}
4630
4631int Sema::getNumberOfConstructScopes(unsigned Level) const {
4632 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4633}
4634
4637 getOpenMPCaptureRegions(CaptureRegions, DKind);
4638 return CaptureRegions.size();
4639}
4640
4642 Expr *CaptureExpr, bool WithInit,
4643 DeclContext *CurContext,
4644 bool AsExpression) {
4645 assert(CaptureExpr);
4646 ASTContext &C = S.getASTContext();
4647 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4648 QualType Ty = Init->getType();
4649 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4650 if (S.getLangOpts().CPlusPlus) {
4651 Ty = C.getLValueReferenceType(Ty);
4652 } else {
4653 Ty = C.getPointerType(Ty);
4654 ExprResult Res =
4655 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4656 if (!Res.isUsable())
4657 return nullptr;
4658 Init = Res.get();
4659 }
4660 WithInit = true;
4661 }
4662 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4663 CaptureExpr->getBeginLoc());
4664 if (!WithInit)
4665 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4666 CurContext->addHiddenDecl(CED);
4668 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4669 return CED;
4670}
4671
4672static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4673 bool WithInit) {
4675 if (VarDecl *VD = S.isOpenMPCapturedDecl(D))
4676 CD = cast<OMPCapturedExprDecl>(VD);
4677 else
4678 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4679 S.CurContext,
4680 /*AsExpression=*/false);
4681 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4682 CaptureExpr->getExprLoc());
4683}
4684
4685static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4686 StringRef Name) {
4687 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4688 if (!Ref) {
4690 S, &S.getASTContext().Idents.get(Name), CaptureExpr,
4691 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4692 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4693 CaptureExpr->getExprLoc());
4694 }
4695 ExprResult Res = Ref;
4696 if (!S.getLangOpts().CPlusPlus &&
4697 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4698 Ref->getType()->isPointerType()) {
4699 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4700 if (!Res.isUsable())
4701 return ExprError();
4702 }
4703 return S.DefaultLvalueConversion(Res.get());
4704}
4705
4706namespace {
4707// OpenMP directives parsed in this section are represented as a
4708// CapturedStatement with an associated statement. If a syntax error
4709// is detected during the parsing of the associated statement, the
4710// compiler must abort processing and close the CapturedStatement.
4711//
4712// Combined directives such as 'target parallel' have more than one
4713// nested CapturedStatements. This RAII ensures that we unwind out
4714// of all the nested CapturedStatements when an error is found.
4715class CaptureRegionUnwinderRAII {
4716private:
4717 Sema &S;
4718 bool &ErrorFound;
4719 OpenMPDirectiveKind DKind = OMPD_unknown;
4720
4721public:
4722 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4723 OpenMPDirectiveKind DKind)
4724 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4725 ~CaptureRegionUnwinderRAII() {
4726 if (ErrorFound) {
4727 int ThisCaptureLevel = S.getOpenMPCaptureLevels(DKind);
4728 while (--ThisCaptureLevel >= 0)
4730 }
4731 }
4732};
4733} // namespace
4734
4736 // Capture variables captured by reference in lambdas for target-based
4737 // directives.
4739 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4741 DSAStack->getCurrentDirective()))) {
4742 QualType Type = V->getType();
4743 if (const auto *RD = Type.getCanonicalType()
4744 .getNonReferenceType()
4745 ->getAsCXXRecordDecl()) {
4746 bool SavedForceCaptureByReferenceInTargetExecutable =
4747 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4748 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4749 /*V=*/true);
4750 if (RD->isLambda()) {
4751 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4752 FieldDecl *ThisCapture;
4753 RD->getCaptureFields(Captures, ThisCapture);
4754 for (const LambdaCapture &LC : RD->captures()) {
4755 if (LC.getCaptureKind() == LCK_ByRef) {
4756 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4757 DeclContext *VDC = VD->getDeclContext();
4758 if (!VDC->Encloses(CurContext))
4759 continue;
4760 MarkVariableReferenced(LC.getLocation(), VD);
4761 } else if (LC.getCaptureKind() == LCK_This) {
4762 QualType ThisTy = getCurrentThisType();
4763 if (!ThisTy.isNull() &&
4764 Context.typesAreCompatible(ThisTy, ThisCapture->getType()))
4765 CheckCXXThisCapture(LC.getLocation());
4766 }
4767 }
4768 }
4769 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4770 SavedForceCaptureByReferenceInTargetExecutable);
4771 }
4772 }
4773}
4774
4776 const ArrayRef<OMPClause *> Clauses) {
4777 const OMPOrderedClause *Ordered = nullptr;
4778 const OMPOrderClause *Order = nullptr;
4779
4780 for (const OMPClause *Clause : Clauses) {
4781 if (Clause->getClauseKind() == OMPC_ordered)
4782 Ordered = cast<OMPOrderedClause>(Clause);
4783 else if (Clause->getClauseKind() == OMPC_order) {
4784 Order = cast<OMPOrderClause>(Clause);
4785 if (Order->getKind() != OMPC_ORDER_concurrent)
4786 Order = nullptr;
4787 }
4788 if (Ordered && Order)
4789 break;
4790 }
4791
4792 if (Ordered && Order) {
4793 S.Diag(Order->getKindKwLoc(),
4794 diag::err_omp_simple_clause_incompatible_with_ordered)
4795 << getOpenMPClauseName(OMPC_order)
4796 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4797 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4798 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4799 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4800 return true;
4801 }
4802 return false;
4803}
4804
4806 ArrayRef<OMPClause *> Clauses) {
4808 /* ScopeEntry */ false);
4809 if (DSAStack->getCurrentDirective() == OMPD_atomic ||
4810 DSAStack->getCurrentDirective() == OMPD_critical ||
4811 DSAStack->getCurrentDirective() == OMPD_section ||
4812 DSAStack->getCurrentDirective() == OMPD_master ||
4813 DSAStack->getCurrentDirective() == OMPD_masked)
4814 return S;
4815
4816 bool ErrorFound = false;
4817 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4818 *this, ErrorFound, DSAStack->getCurrentDirective());
4819 if (!S.isUsable()) {
4820 ErrorFound = true;
4821 return StmtError();
4822 }
4823
4825 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4826 OMPOrderedClause *OC = nullptr;
4827 OMPScheduleClause *SC = nullptr;
4830 // This is required for proper codegen.
4831 for (OMPClause *Clause : Clauses) {
4832 if (!LangOpts.OpenMPSimd &&
4833 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4834 DSAStack->getCurrentDirective() == OMPD_target) &&
4835 Clause->getClauseKind() == OMPC_in_reduction) {
4836 // Capture taskgroup task_reduction descriptors inside the tasking regions
4837 // with the corresponding in_reduction items.
4838 auto *IRC = cast<OMPInReductionClause>(Clause);
4839 for (Expr *E : IRC->taskgroup_descriptors())
4840 if (E)
4842 }
4843 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4844 Clause->getClauseKind() == OMPC_copyprivate ||
4845 (getLangOpts().OpenMPUseTLS &&
4846 getASTContext().getTargetInfo().isTLSSupported() &&
4847 Clause->getClauseKind() == OMPC_copyin)) {
4848 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4849 // Mark all variables in private list clauses as used in inner region.
4850 for (Stmt *VarRef : Clause->children()) {
4851 if (auto *E = cast_or_null<Expr>(VarRef)) {
4853 }
4854 }
4855 DSAStack->setForceVarCapturing(/*V=*/false);
4857 DSAStack->getCurrentDirective())) {
4858 assert(CaptureRegions.empty() &&
4859 "No captured regions in loop transformation directives.");
4860 } else if (CaptureRegions.size() > 1 ||
4861 CaptureRegions.back() != OMPD_unknown) {
4862 if (auto *C = OMPClauseWithPreInit::get(Clause))
4863 PICs.push_back(C);
4864 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4865 if (Expr *E = C->getPostUpdateExpr())
4867 }
4868 }
4869 if (Clause->getClauseKind() == OMPC_schedule)
4870 SC = cast<OMPScheduleClause>(Clause);
4871 else if (Clause->getClauseKind() == OMPC_ordered)
4872 OC = cast<OMPOrderedClause>(Clause);
4873 else if (Clause->getClauseKind() == OMPC_linear)
4874 LCs.push_back(cast<OMPLinearClause>(Clause));
4875 }
4876 // Capture allocator expressions if used.
4877 for (Expr *E : DSAStack->getInnerAllocators())
4879 // OpenMP, 2.7.1 Loop Construct, Restrictions
4880 // The nonmonotonic modifier cannot be specified if an ordered clause is
4881 // specified.
4882 if (SC &&
4883 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4885 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4886 OC) {
4887 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4890 diag::err_omp_simple_clause_incompatible_with_ordered)
4891 << getOpenMPClauseName(OMPC_schedule)
4892 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4893 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4894 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4895 ErrorFound = true;
4896 }
4897 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4898 // If an order(concurrent) clause is present, an ordered clause may not appear
4899 // on the same directive.
4900 if (checkOrderedOrderSpecified(*this, Clauses))
4901 ErrorFound = true;
4902 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4903 for (const OMPLinearClause *C : LCs) {
4904 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4905 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4906 }
4907 ErrorFound = true;
4908 }
4909 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4910 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4911 OC->getNumForLoops()) {
4912 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4913 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
4914 ErrorFound = true;
4915 }
4916 if (ErrorFound) {
4917 return StmtError();
4918 }
4919 StmtResult SR = S;
4920 unsigned CompletedRegions = 0;
4921 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4922 // Mark all variables in private list clauses as used in inner region.
4923 // Required for proper codegen of combined directives.
4924 // TODO: add processing for other clauses.
4925 if (ThisCaptureRegion != OMPD_unknown) {
4926 for (const clang::OMPClauseWithPreInit *C : PICs) {
4927 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4928 // Find the particular capture region for the clause if the
4929 // directive is a combined one with multiple capture regions.
4930 // If the directive is not a combined one, the capture region
4931 // associated with the clause is OMPD_unknown and is generated
4932 // only once.
4933 if (CaptureRegion == ThisCaptureRegion ||
4934 CaptureRegion == OMPD_unknown) {
4935 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4936 for (Decl *D : DS->decls())
4937 MarkVariableReferenced(D->getLocation(), cast<VarDecl>(D));
4938 }
4939 }
4940 }
4941 }
4942 if (ThisCaptureRegion == OMPD_target) {
4943 // Capture allocator traits in the target region. They are used implicitly
4944 // and, thus, are not captured by default.
4945 for (OMPClause *C : Clauses) {
4946 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4947 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4948 ++I) {
4949 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4950 if (Expr *E = D.AllocatorTraits)
4952 }
4953 continue;
4954 }
4955 }
4956 }
4957 if (ThisCaptureRegion == OMPD_parallel) {
4958 // Capture temp arrays for inscan reductions and locals in aligned
4959 // clauses.
4960 for (OMPClause *C : Clauses) {
4961 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4962 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4963 continue;
4964 for (Expr *E : RC->copy_array_temps())
4965 if (E)
4967 }
4968 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4969 for (Expr *E : AC->varlists())
4971 }
4972 }
4973 }
4974 if (++CompletedRegions == CaptureRegions.size())
4975 DSAStack->setBodyComplete();
4976 SR = ActOnCapturedRegionEnd(SR.get());
4977 }
4978 return SR;
4979}
4980
4981static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4982 OpenMPDirectiveKind CancelRegion,
4983 SourceLocation StartLoc) {
4984 // CancelRegion is only needed for cancel and cancellation_point.
4985 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4986 return false;
4987
4988 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4989 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4990 return false;
4991
4992 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4993 << getOpenMPDirectiveName(CancelRegion);
4994 return true;
4995}
4996
4997static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4998 OpenMPDirectiveKind CurrentRegion,
4999 const DeclarationNameInfo &CurrentName,
5000 OpenMPDirectiveKind CancelRegion,
5001 OpenMPBindClauseKind BindKind,
5002 SourceLocation StartLoc) {
5003 if (Stack->getCurScope()) {
5004 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
5005 OpenMPDirectiveKind OffendingRegion = ParentRegion;
5006 bool NestingProhibited = false;
5007 bool CloseNesting = true;
5008 bool OrphanSeen = false;
5009 enum {
5010 NoRecommend,
5011 ShouldBeInParallelRegion,
5012 ShouldBeInOrderedRegion,
5013 ShouldBeInTargetRegion,
5014 ShouldBeInTeamsRegion,
5015 ShouldBeInLoopSimdRegion,
5016 } Recommend = NoRecommend;
5017 if (SemaRef.LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() &&
5018 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop &&
5019 CurrentRegion != OMPD_parallel &&
5020 !isOpenMPCombinedParallelADirective(CurrentRegion)) {
5021 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
5022 << getOpenMPDirectiveName(CurrentRegion);
5023 return true;
5024 }
5025 if (isOpenMPSimdDirective(ParentRegion) &&
5026 ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
5027 (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
5028 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
5029 CurrentRegion != OMPD_scan))) {
5030 // OpenMP [2.16, Nesting of Regions]
5031 // OpenMP constructs may not be nested inside a simd region.
5032 // OpenMP [2.8.1,simd Construct, Restrictions]
5033 // An ordered construct with the simd clause is the only OpenMP
5034 // construct that can appear in the simd region.
5035 // Allowing a SIMD construct nested in another SIMD construct is an
5036 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
5037 // message.
5038 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
5039 // The only OpenMP constructs that can be encountered during execution of
5040 // a simd region are the atomic construct, the loop construct, the simd
5041 // construct and the ordered construct with the simd clause.
5042 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
5043 ? diag::err_omp_prohibited_region_simd
5044 : diag::warn_omp_nesting_simd)
5045 << (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0);
5046 return CurrentRegion != OMPD_simd;
5047 }
5048 if (ParentRegion == OMPD_atomic) {
5049 // OpenMP [2.16, Nesting of Regions]
5050 // OpenMP constructs may not be nested inside an atomic region.
5051 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
5052 return true;
5053 }
5054 if (CurrentRegion == OMPD_section) {
5055 // OpenMP [2.7.2, sections Construct, Restrictions]
5056 // Orphaned section directives are prohibited. That is, the section
5057 // directives must appear within the sections construct and must not be
5058 // encountered elsewhere in the sections region.
5059 if (ParentRegion != OMPD_sections &&
5060 ParentRegion != OMPD_parallel_sections) {
5061 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
5062 << (ParentRegion != OMPD_unknown)
5063 << getOpenMPDirectiveName(ParentRegion);
5064 return true;
5065 }
5066 return false;
5067 }
5068 // Allow some constructs (except teams and cancellation constructs) to be
5069 // orphaned (they could be used in functions, called from OpenMP regions
5070 // with the required preconditions).
5071 if (ParentRegion == OMPD_unknown &&
5072 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
5073 CurrentRegion != OMPD_cancellation_point &&
5074 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5075 return false;
5076 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
5077 // for a detailed explanation
5078 if (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop &&
5079 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
5080 (isOpenMPWorksharingDirective(ParentRegion) ||
5081 ParentRegion == OMPD_loop)) {
5082 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
5083 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5084 << true << getOpenMPDirectiveName(ParentRegion) << ErrorMsgNumber
5085 << getOpenMPDirectiveName(CurrentRegion);
5086 return true;
5087 }
5088 if (CurrentRegion == OMPD_cancellation_point ||
5089 CurrentRegion == OMPD_cancel) {
5090 // OpenMP [2.16, Nesting of Regions]
5091 // A cancellation point construct for which construct-type-clause is
5092 // taskgroup must be nested inside a task construct. A cancellation
5093 // point construct for which construct-type-clause is not taskgroup must
5094 // be closely nested inside an OpenMP construct that matches the type
5095 // specified in construct-type-clause.
5096 // A cancel construct for which construct-type-clause is taskgroup must be
5097 // nested inside a task construct. A cancel construct for which
5098 // construct-type-clause is not taskgroup must be closely nested inside an
5099 // OpenMP construct that matches the type specified in
5100 // construct-type-clause.
5101 NestingProhibited =
5102 !((CancelRegion == OMPD_parallel &&
5103 (ParentRegion == OMPD_parallel ||
5104 ParentRegion == OMPD_target_parallel)) ||
5105 (CancelRegion == OMPD_for &&
5106 (ParentRegion == OMPD_for || ParentRegion == OMPD_parallel_for ||
5107 ParentRegion == OMPD_target_parallel_for ||
5108 ParentRegion == OMPD_distribute_parallel_for ||
5109 ParentRegion == OMPD_teams_distribute_parallel_for ||
5110 ParentRegion == OMPD_target_teams_distribute_parallel_for)) ||
5111 (CancelRegion == OMPD_taskgroup &&
5112 (ParentRegion == OMPD_task ||
5113 (SemaRef.getLangOpts().OpenMP >= 50 &&
5114 (ParentRegion == OMPD_taskloop ||
5115 ParentRegion == OMPD_master_taskloop ||
5116 ParentRegion == OMPD_masked_taskloop ||
5117 ParentRegion == OMPD_parallel_masked_taskloop ||
5118 ParentRegion == OMPD_parallel_master_taskloop)))) ||
5119 (CancelRegion == OMPD_sections &&
5120 (ParentRegion == OMPD_section || ParentRegion == OMPD_sections ||
5121 ParentRegion == OMPD_parallel_sections)));
5122 OrphanSeen = ParentRegion == OMPD_unknown;
5123 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5124 // OpenMP 5.1 [2.22, Nesting of Regions]
5125 // A masked region may not be closely nested inside a worksharing, loop,
5126 // atomic, task, or taskloop region.
5127 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5128 isOpenMPGenericLoopDirective(ParentRegion) ||
5129 isOpenMPTaskingDirective(ParentRegion);
5130 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5131 // OpenMP [2.16, Nesting of Regions]
5132 // A critical region may not be nested (closely or otherwise) inside a
5133 // critical region with the same name. Note that this restriction is not
5134 // sufficient to prevent deadlock.
5135 SourceLocation PreviousCriticalLoc;
5136 bool DeadLock = Stack->hasDirective(
5137 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5138 const DeclarationNameInfo &DNI,
5139 SourceLocation Loc) {
5140 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5141 PreviousCriticalLoc = Loc;
5142 return true;
5143 }
5144 return false;
5145 },
5146 false /* skip top directive */);
5147 if (DeadLock) {
5148 SemaRef.Diag(StartLoc,
5149 diag::err_omp_prohibited_region_critical_same_name)
5150 << CurrentName.getName();
5151 if (PreviousCriticalLoc.isValid())
5152 SemaRef.Diag(PreviousCriticalLoc,
5153 diag::note_omp_previous_critical_region);
5154 return true;
5155 }
5156 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5157 // OpenMP 5.1 [2.22, Nesting of Regions]
5158 // A scope region may not be closely nested inside a worksharing, loop,
5159 // task, taskloop, critical, ordered, atomic, or masked region.
5160 // OpenMP 5.1 [2.22, Nesting of Regions]
5161 // A barrier region may not be closely nested inside a worksharing, loop,
5162 // task, taskloop, critical, ordered, atomic, or masked region.
5163 NestingProhibited =
5164 isOpenMPWorksharingDirective(ParentRegion) ||
5165 isOpenMPGenericLoopDirective(ParentRegion) ||
5166 isOpenMPTaskingDirective(ParentRegion) ||
5167 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5168 ParentRegion == OMPD_parallel_master ||
5169 ParentRegion == OMPD_parallel_masked ||
5170 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5171 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
5172 !isOpenMPParallelDirective(CurrentRegion) &&
5173 !isOpenMPTeamsDirective(CurrentRegion)) {
5174 // OpenMP 5.1 [2.22, Nesting of Regions]
5175 // A loop region that binds to a parallel region or a worksharing region
5176 // may not be closely nested inside a worksharing, loop, task, taskloop,
5177 // critical, ordered, atomic, or masked region.
5178 NestingProhibited =
5179 isOpenMPWorksharingDirective(ParentRegion) ||
5180 isOpenMPGenericLoopDirective(ParentRegion) ||
5181 isOpenMPTaskingDirective(ParentRegion) ||
5182 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5183 ParentRegion == OMPD_parallel_master ||
5184 ParentRegion == OMPD_parallel_masked ||
5185 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5186 Recommend = ShouldBeInParallelRegion;
5187 } else if (CurrentRegion == OMPD_ordered) {
5188 // OpenMP [2.16, Nesting of Regions]
5189 // An ordered region may not be closely nested inside a critical,
5190 // atomic, or explicit task region.
5191 // An ordered region must be closely nested inside a loop region (or
5192 // parallel loop region) with an ordered clause.
5193 // OpenMP [2.8.1,simd Construct, Restrictions]
5194 // An ordered construct with the simd clause is the only OpenMP construct
5195 // that can appear in the simd region.
5196 NestingProhibited = ParentRegion == OMPD_critical ||
5197 isOpenMPTaskingDirective(ParentRegion) ||
5198 !(isOpenMPSimdDirective(ParentRegion) ||
5199 Stack->isParentOrderedRegion());
5200 Recommend = ShouldBeInOrderedRegion;
5201 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
5202 // OpenMP [2.16, Nesting of Regions]
5203 // If specified, a teams construct must be contained within a target
5204 // construct.
5205 NestingProhibited =
5206 (SemaRef.LangOpts.OpenMP <= 45 && ParentRegion != OMPD_target) ||
5207 (SemaRef.LangOpts.OpenMP >= 50 && ParentRegion != OMPD_unknown &&
5208 ParentRegion != OMPD_target);
5209 OrphanSeen = ParentRegion == OMPD_unknown;
5210 Recommend = ShouldBeInTargetRegion;
5211 } else if (CurrentRegion == OMPD_scan) {
5212 // OpenMP [2.16, Nesting of Regions]
5213 // If specified, a teams construct must be contained within a target
5214 // construct.
5215 NestingProhibited =
5216 SemaRef.LangOpts.OpenMP < 50 ||
5217 (ParentRegion != OMPD_simd && ParentRegion != OMPD_for &&
5218 ParentRegion != OMPD_for_simd && ParentRegion != OMPD_parallel_for &&
5219 ParentRegion != OMPD_parallel_for_simd);
5220 OrphanSeen = ParentRegion == OMPD_unknown;
5221 Recommend = ShouldBeInLoopSimdRegion;
5222 }
5223 if (!NestingProhibited &&
5224 !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5225 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5226 (ParentRegion == OMPD_teams || ParentRegion == OMPD_target_teams)) {
5227 // OpenMP [5.1, 2.22, Nesting of Regions]
5228 // distribute, distribute simd, distribute parallel worksharing-loop,
5229 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5230 // including any parallel regions arising from combined constructs,
5231 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5232 // only OpenMP regions that may be strictly nested inside the teams
5233 // region.
5234 //
5235 // As an extension, we permit atomic within teams as well.
5236 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5237 !isOpenMPDistributeDirective(CurrentRegion) &&
5238 CurrentRegion != OMPD_loop &&
5239 !(SemaRef.getLangOpts().OpenMPExtensions &&
5240 CurrentRegion == OMPD_atomic);
5241 Recommend = ShouldBeInParallelRegion;
5242 }
5243 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5244 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5245 // If the bind clause is present on the loop construct and binding is
5246 // teams then the corresponding loop region must be strictly nested inside
5247 // a teams region.
5248 NestingProhibited = BindKind == OMPC_BIND_teams &&
5249 ParentRegion != OMPD_teams &&
5250 ParentRegion != OMPD_target_teams;
5251 Recommend = ShouldBeInTeamsRegion;
5252 }
5253 if (!NestingProhibited &&
5254 isOpenMPNestingDistributeDirective(CurrentRegion)) {
5255 // OpenMP 4.5 [2.17 Nesting of Regions]
5256 // The region associated with the distribute construct must be strictly
5257 // nested inside a teams region
5258 NestingProhibited =
5259 (ParentRegion != OMPD_teams && ParentRegion != OMPD_target_teams);
5260 Recommend = ShouldBeInTeamsRegion;
5261 }
5262 if (!NestingProhibited &&
5263 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5264 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5265 // OpenMP 4.5 [2.17 Nesting of Regions]
5266 // If a target, target update, target data, target enter data, or
5267 // target exit data construct is encountered during execution of a
5268 // target region, the behavior is unspecified.
5269 NestingProhibited = Stack->hasDirective(
5270 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5273 OffendingRegion = K;
5274 return true;
5275 }
5276 return false;
5277 },
5278 false /* don't skip top directive */);
5279 CloseNesting = false;
5280 }
5281 if (NestingProhibited) {
5282 if (OrphanSeen) {
5283 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5284 << getOpenMPDirectiveName(CurrentRegion) << Recommend;
5285 } else {
5286 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5287 << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
5288 << Recommend << getOpenMPDirectiveName(CurrentRegion);
5289 }
5290 return true;
5291 }
5292 }
5293 return false;
5294}
5295
5298 unsigned operator()(argument_type DK) { return unsigned(DK); }
5299};
5301 ArrayRef<OMPClause *> Clauses,
5302 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5303 bool ErrorFound = false;
5304 unsigned NamedModifiersNumber = 0;
5305 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5306 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5307 SmallVector<SourceLocation, 4> NameModifierLoc;
5308 for (const OMPClause *C : Clauses) {
5309 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5310 // At most one if clause without a directive-name-modifier can appear on
5311 // the directive.
5312 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5313 if (FoundNameModifiers[CurNM]) {
5314 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5315 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
5316 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
5317 ErrorFound = true;
5318 } else if (CurNM != OMPD_unknown) {
5319 NameModifierLoc.push_back(IC->getNameModifierLoc());
5320 ++NamedModifiersNumber;
5321 }
5322 FoundNameModifiers[CurNM] = IC;
5323 if (CurNM == OMPD_unknown)
5324 continue;
5325 // Check if the specified name modifier is allowed for the current
5326 // directive.
5327 // At most one if clause with the particular directive-name-modifier can
5328 // appear on the directive.
5329 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5330 S.Diag(IC->getNameModifierLoc(),
5331 diag::err_omp_wrong_if_directive_name_modifier)
5332 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
5333 ErrorFound = true;
5334 }
5335 }
5336 }
5337 // If any if clause on the directive includes a directive-name-modifier then
5338 // all if clauses on the directive must include a directive-name-modifier.
5339 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5340 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5341 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5342 diag::err_omp_no_more_if_clause);
5343 } else {
5344 std::string Values;
5345 std::string Sep(", ");
5346 unsigned AllowedCnt = 0;
5347 unsigned TotalAllowedNum =
5348 AllowedNameModifiers.size() - NamedModifiersNumber;
5349 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5350 ++Cnt) {
5351 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5352 if (!FoundNameModifiers[NM]) {
5353 Values += "'";
5354 Values += getOpenMPDirectiveName(NM);
5355 Values += "'";
5356 if (AllowedCnt + 2 == TotalAllowedNum)
5357 Values += " or ";
5358 else if (AllowedCnt + 1 != TotalAllowedNum)
5359 Values += Sep;
5360 ++AllowedCnt;
5361 }
5362 }
5363 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5364 diag::err_omp_unnamed_if_clause)
5365 << (TotalAllowedNum > 1) << Values;
5366 }
5367 for (SourceLocation Loc : NameModifierLoc) {
5368 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5369 }
5370 ErrorFound = true;
5371 }
5372 return ErrorFound;
5373}
5374
5375static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5376 SourceLocation &ELoc,
5377 SourceRange &ERange,
5378 bool AllowArraySection,
5379 StringRef DiagType) {
5380 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5382 return std::make_pair(nullptr, true);
5383
5384 // OpenMP [3.1, C/C++]
5385 // A list item is a variable name.
5386 // OpenMP [2.9.3.3, Restrictions, p.1]
5387 // A variable that is part of another variable (as an array or
5388 // structure element) cannot appear in a private clause.
5389 RefExpr = RefExpr->IgnoreParens();
5390 enum {
5391 NoArrayExpr = -1,
5392 ArraySubscript = 0,
5393 OMPArraySection = 1
5394 } IsArrayExpr = NoArrayExpr;
5395 if (AllowArraySection) {
5396 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5397 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5398 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5399 Base = TempASE->getBase()->IgnoreParenImpCasts();
5400 RefExpr = Base;
5401 IsArrayExpr = ArraySubscript;
5402 } else if (auto *OASE = dyn_cast_or_null<OMPArraySectionExpr>(RefExpr)) {
5403 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5404 while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
5405 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5406 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5407 Base = TempASE->getBase()->IgnoreParenImpCasts();
5408 RefExpr = Base;
5409 IsArrayExpr = OMPArraySection;
5410 }
5411 }
5412 ELoc = RefExpr->getExprLoc();
5413 ERange = RefExpr->getSourceRange();
5414 RefExpr = RefExpr->IgnoreParenImpCasts();
5415 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5416 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5417 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5418 (S.getCurrentThisType().isNull() || !ME ||
5419 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5420 !isa<FieldDecl>(ME->getMemberDecl()))) {
5421 if (IsArrayExpr != NoArrayExpr) {
5422 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5423 << IsArrayExpr << ERange;
5424 } else if (!DiagType.empty()) {
5425 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5426 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5427 : 0;
5428 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5429 << DiagSelect << DiagType << ERange;
5430 } else {
5431 S.Diag(ELoc,
5432 AllowArraySection
5433 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5434 : diag::err_omp_expected_var_name_member_expr)
5435 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5436 }
5437 return std::make_pair(nullptr, false);
5438 }
5439 return std::make_pair(
5440 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5441}
5442
5443namespace {
5444/// Checks if the allocator is used in uses_allocators clause to be allowed in
5445/// target regions.
5446class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5447 DSAStackTy *S = nullptr;
5448
5449public:
5450 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5451 return S->isUsesAllocatorsDecl(E->getDecl())
5452 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5453 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5454 }
5455 bool VisitStmt(const Stmt *S) {
5456 for (const Stmt *Child : S->children()) {
5457 if (Child && Visit(Child))
5458 return true;
5459 }
5460 return false;
5461 }
5462 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5463};
5464} // namespace
5465
5466static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5467 ArrayRef<OMPClause *> Clauses) {
5468 assert(!S.CurContext->isDependentContext() &&
5469 "Expected non-dependent context.");
5470 auto AllocateRange =
5471 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5472 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5473 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5474 return isOpenMPPrivate(C->getClauseKind());
5475 });
5476 for (OMPClause *Cl : PrivateRange) {
5478 if (Cl->getClauseKind() == OMPC_private) {
5479 auto *PC = cast<OMPPrivateClause>(Cl);
5480 I = PC->private_copies().begin();
5481 It = PC->varlist_begin();
5482 Et = PC->varlist_end();
5483 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5484 auto *PC = cast<OMPFirstprivateClause>(Cl);
5485 I = PC->private_copies().begin();
5486 It = PC->varlist_begin();
5487 Et = PC->varlist_end();
5488 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5489 auto *PC = cast<OMPLastprivateClause>(Cl);
5490 I = PC->private_copies().begin();
5491 It = PC->varlist_begin();
5492 Et = PC->varlist_end();
5493 } else if (Cl->getClauseKind() == OMPC_linear) {
5494 auto *PC = cast<OMPLinearClause>(Cl);
5495 I = PC->privates().begin();
5496 It = PC->varlist_begin();
5497 Et = PC->varlist_end();
5498 } else if (Cl->getClauseKind() == OMPC_reduction) {
5499 auto *PC = cast<OMPReductionClause>(Cl);
5500 I = PC->privates().begin();
5501 It = PC->varlist_begin();
5502 Et = PC->varlist_end();
5503 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5504 auto *PC = cast<OMPTaskReductionClause>(Cl);
5505 I = PC->privates().begin();
5506 It = PC->varlist_begin();
5507 Et = PC->varlist_end();
5508 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5509 auto *PC = cast<OMPInReductionClause>(Cl);
5510 I = PC->privates().begin();
5511 It = PC->varlist_begin();
5512 Et = PC->varlist_end();
5513 } else {
5514 llvm_unreachable("Expected private clause.");
5515 }
5516 for (Expr *E : llvm::make_range(It, Et)) {
5517 if (!*I) {
5518 ++I;
5519 continue;
5520 }
5521 SourceLocation ELoc;
5522 SourceRange ERange;
5523 Expr *SimpleRefExpr = E;
5524 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5525 /*AllowArraySection=*/true);
5526 DeclToCopy.try_emplace(Res.first,
5527 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5528 ++I;
5529 }
5530 }
5531 for (OMPClause *C : AllocateRange) {
5532 auto *AC = cast<OMPAllocateClause>(C);
5533 if (S.getLangOpts().OpenMP >= 50 &&
5534 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5535 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5536 AC->getAllocator()) {
5537 Expr *Allocator = AC->getAllocator();
5538 // OpenMP, 2.12.5 target Construct
5539 // Memory allocators that do not appear in a uses_allocators clause cannot
5540 // appear as an allocator in an allocate clause or be used in the target
5541 // region unless a requires directive with the dynamic_allocators clause
5542 // is present in the same compilation unit.
5543 AllocatorChecker Checker(Stack);
5544 if (Checker.Visit(Allocator))
5545 S.Diag(Allocator->getExprLoc(),
5546 diag::err_omp_allocator_not_in_uses_allocators)
5547 << Allocator->getSourceRange();
5548 }
5549 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5550 getAllocatorKind(S, Stack, AC->getAllocator());
5551 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5552 // For task, taskloop or target directives, allocation requests to memory
5553 // allocators with the trait access set to thread result in unspecified
5554 // behavior.
5555 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5556 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5557 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5558 S.Diag(AC->getAllocator()->getExprLoc(),
5559 diag::warn_omp_allocate_thread_on_task_target_directive)
5560 << getOpenMPDirectiveName(Stack->getCurrentDirective());
5561 }
5562 for (Expr *E : AC->varlists()) {
5563 SourceLocation ELoc;
5564 SourceRange ERange;
5565 Expr *SimpleRefExpr = E;
5566 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5567 ValueDecl *VD = Res.first;
5568 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5569 if (!isOpenMPPrivate(Data.CKind)) {
5570 S.Diag(E->getExprLoc(),
5571 diag::err_omp_expected_private_copy_for_allocate);
5572 continue;
5573 }
5574 VarDecl *PrivateVD = DeclToCopy[VD];
5575 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5576 AllocatorKind, AC->getAllocator()))
5577 continue;
5578 // Placeholder until allocate clause supports align modifier.
5579 Expr *Alignment = nullptr;
5580 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5581 Alignment, E->getSourceRange());
5582 }
5583 }
5584}
5585
5586namespace {
5587/// Rewrite statements and expressions for Sema \p Actions CurContext.
5588///
5589/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5590/// context. DeclRefExpr used inside the new context are changed to refer to the
5591/// captured variable instead.
5592class CaptureVars : public TreeTransform<CaptureVars> {
5593 using BaseTransform = TreeTransform<CaptureVars>;
5594
5595public:
5596 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5597
5598 bool AlwaysRebuild() { return true; }
5599};
5600} // namespace
5601
5602static VarDecl *precomputeExpr(Sema &Actions,
5603 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5604 StringRef Name) {
5605 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5606 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5607 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5608 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5609 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5610 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5611 BodyStmts.push_back(NewDeclStmt);
5612 return NewVar;
5613}
5614
5615/// Create a closure that computes the number of iterations of a loop.
5616///
5617/// \param Actions The Sema object.
5618/// \param LogicalTy Type for the logical iteration number.
5619/// \param Rel Comparison operator of the loop condition.
5620/// \param StartExpr Value of the loop counter at the first iteration.
5621/// \param StopExpr Expression the loop counter is compared against in the loop
5622/// condition. \param StepExpr Amount of increment after each iteration.
5623///
5624/// \return Closure (CapturedStmt) of the distance calculation.
5625static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5627 Expr *StartExpr, Expr *StopExpr,
5628 Expr *StepExpr) {
5629 ASTContext &Ctx = Actions.getASTContext();
5630 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5631
5632 // Captured regions currently don't support return values, we use an
5633 // out-parameter instead. All inputs are implicit captures.
5634 // TODO: Instead of capturing each DeclRefExpr occurring in
5635 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5636 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5637 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5638 {StringRef(), QualType()}};
5639 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5640
5641 Stmt *Body;
5642 {
5643 Sema::CompoundScopeRAII CompoundScope(Actions);
5644 CapturedDecl *CS = cast<CapturedDecl>(Actions.CurContext);
5645
5646 // Get the LValue expression for the result.
5647 ImplicitParamDecl *DistParam = CS->getParam(0);
5648 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5649 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5650
5651 SmallVector<Stmt *, 4> BodyStmts;
5652
5653 // Capture all referenced variable references.
5654 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5655 // CapturedStmt, we could compute them before and capture the result, to be
5656 // used jointly with the LoopVar function.
5657 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5658 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5659 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5660 auto BuildVarRef = [&](VarDecl *VD) {
5661 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5662 };
5663
5665 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5667 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5668 Expr *Dist;
5669 if (Rel == BO_NE) {
5670 // When using a != comparison, the increment can be +1 or -1. This can be
5671 // dynamic at runtime, so we need to check for the direction.
5672 Expr *IsNegStep = AssertSuccess(
5673 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5674
5675 // Positive increment.
5676 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5677 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5678 ForwardRange = AssertSuccess(
5679 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5680 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5681 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5682
5683 // Negative increment.
5684 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5685 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5686 BackwardRange = AssertSuccess(
5687 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5688 Expr *NegIncAmount = AssertSuccess(
5689 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5690 Expr *BackwardDist = AssertSuccess(
5691 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5692
5693 // Use the appropriate case.
5694 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5695 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5696 } else {
5697 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5698 "Expected one of these relational operators");
5699
5700 // We can derive the direction from any other comparison operator. It is
5701 // non well-formed OpenMP if Step increments/decrements in the other
5702 // directions. Whether at least the first iteration passes the loop
5703 // condition.
5704 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5705 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5706
5707 // Compute the range between first and last counter value.
5708 Expr *Range;
5709 if (Rel == BO_GE || Rel == BO_GT)
5710 Range = AssertSuccess(Actions.BuildBinOp(
5711 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5712 else
5713 Range = AssertSuccess(Actions.BuildBinOp(
5714 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5715
5716 // Ensure unsigned range space.
5717 Range =
5718 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5719
5720 if (Rel == BO_LE || Rel == BO_GE) {
5721 // Add one to the range if the relational operator is inclusive.
5722 Range =
5723 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5724 }
5725
5726 // Divide by the absolute step amount. If the range is not a multiple of
5727 // the step size, rounding-up the effective upper bound ensures that the
5728 // last iteration is included.
5729 // Note that the rounding-up may cause an overflow in a temporry that
5730 // could be avoided, but would have occurred in a C-style for-loop as
5731 // well.
5732 Expr *Divisor = BuildVarRef(NewStep);
5733 if (Rel == BO_GE || Rel == BO_GT)
5734 Divisor =
5735 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5736 Expr *DivisorMinusOne =
5737 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5738 Expr *RangeRoundUp = AssertSuccess(
5739 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5740 Dist = AssertSuccess(
5741 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5742
5743 // If there is not at least one iteration, the range contains garbage. Fix
5744 // to zero in this case.
5745 Dist = AssertSuccess(
5746 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5747 }
5748
5749 // Assign the result to the out-parameter.
5750 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5751 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5752 BodyStmts.push_back(ResultAssign);
5753
5754 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5755 }
5756
5757 return cast<CapturedStmt>(
5758 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5759}
5760
5761/// Create a closure that computes the loop variable from the logical iteration
5762/// number.
5763///
5764/// \param Actions The Sema object.
5765/// \param LoopVarTy Type for the loop variable used for result value.
5766/// \param LogicalTy Type for the logical iteration number.
5767/// \param StartExpr Value of the loop counter at the first iteration.
5768/// \param Step Amount of increment after each iteration.
5769/// \param Deref Whether the loop variable is a dereference of the loop
5770/// counter variable.
5771///
5772/// \return Closure (CapturedStmt) of the loop value calculation.
5773static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5774 QualType LogicalTy,
5775 DeclRefExpr *StartExpr, Expr *Step,
5776 bool Deref) {
5777 ASTContext &Ctx = Actions.getASTContext();
5778
5779 // Pass the result as an out-parameter. Passing as return value would require
5780 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5781 // invoke a copy constructor.
5782 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5783 Sema::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5784 {"Logical", LogicalTy},
5785 {StringRef(), QualType()}};
5786 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5787
5788 // Capture the initial iterator which represents the LoopVar value at the
5789 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5790 // it in every iteration, capture it by value before it is modified.
5791 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5792 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5794 (void)Invalid;
5795 assert(!Invalid && "Expecting capture-by-value to work.");
5796
5797 Expr *Body;
5798 {
5799 Sema::CompoundScopeRAII CompoundScope(Actions);
5800 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5801
5802 ImplicitParamDecl *TargetParam = CS->getParam(0);
5803 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5804 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5805 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5806 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5807 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5808
5809 // Capture the Start expression.
5810 CaptureVars Recap(Actions);
5811 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5812 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5813
5814 Expr *Skip = AssertSuccess(
5815 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5816 // TODO: Explicitly cast to the iterator's difference_type instead of
5817 // relying on implicit conversion.
5818 Expr *Advanced =
5819 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5820
5821 if (Deref) {
5822 // For range-based for-loops convert the loop counter value to a concrete
5823 // loop variable value by dereferencing the iterator.
5824 Advanced =
5825 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5826 }
5827
5828 // Assign the result to the output parameter.
5829 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5830 BO_Assign, TargetRef, Advanced));
5831 }
5832 return cast<CapturedStmt>(
5833 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5834}
5835
5837 ASTContext &Ctx = getASTContext();
5838
5839 // Extract the common elements of ForStmt and CXXForRangeStmt:
5840 // Loop variable, repeat condition, increment
5841 Expr *Cond, *Inc;
5842 VarDecl *LIVDecl, *LUVDecl;
5843 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5844 Stmt *Init = For->getInit();
5845 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5846 // For statement declares loop variable.
5847 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5848 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5849 // For statement reuses variable.
5850 assert(LCAssign->getOpcode() == BO_Assign &&
5851 "init part must be a loop variable assignment");
5852 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5853 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5854 } else
5855 llvm_unreachable("Cannot determine loop variable");
5856 LUVDecl = LIVDecl;
5857
5858 Cond = For->getCond();
5859 Inc = For->getInc();
5860 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5861 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5862 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5863 LUVDecl = RangeFor->getLoopVariable();
5864
5865 Cond = RangeFor->getCond();
5866 Inc = RangeFor->getInc();
5867 } else
5868 llvm_unreachable("unhandled kind of loop");
5869
5870 QualType CounterTy = LIVDecl->getType();
5871 QualType LVTy = LUVDecl->getType();
5872
5873 // Analyze the loop condition.
5874 Expr *LHS, *RHS;
5875 BinaryOperator::Opcode CondRel;
5876 Cond = Cond->IgnoreImplicit();
5877 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5878 LHS = CondBinExpr->getLHS();
5879 RHS = CondBinExpr->getRHS();
5880 CondRel = CondBinExpr->getOpcode();
5881 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5882 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5883 LHS = CondCXXOp->getArg(0);
5884 RHS = CondCXXOp->getArg(1);
5885 switch (CondCXXOp->getOperator()) {
5886 case OO_ExclaimEqual:
5887 CondRel = BO_NE;
5888 break;
5889 case OO_Less:
5890 CondRel = BO_LT;
5891 break;
5892 case OO_LessEqual:
5893 CondRel = BO_LE;
5894 break;
5895 case OO_Greater:
5896 CondRel = BO_GT;
5897 break;
5898 case OO_GreaterEqual:
5899 CondRel = BO_GE;
5900 break;
5901 default:
5902 llvm_unreachable("unexpected iterator operator");
5903 }
5904 } else
5905 llvm_unreachable("unexpected loop condition");
5906
5907 // Normalize such that the loop counter is on the LHS.
5908 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5909 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5910 std::swap(LHS, RHS);
5911 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5912 }
5913 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5914
5915 // Decide the bit width for the logical iteration counter. By default use the
5916 // unsigned ptrdiff_t integer size (for iterators and pointers).
5917 // TODO: For iterators, use iterator::difference_type,
5918 // std::iterator_traits<>::difference_type or decltype(it - end).
5919 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5920 if (CounterTy->isIntegerType()) {
5921 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5922 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5923 }
5924
5925 // Analyze the loop increment.
5926 Expr *Step;
5927 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5928 int Direction;
5929 switch (IncUn->getOpcode()) {
5930 case UO_PreInc:
5931 case UO_PostInc:
5932 Direction = 1;
5933 break;
5934 case UO_PreDec:
5935 case UO_PostDec:
5936 Direction = -1;
5937 break;
5938 default:
5939 llvm_unreachable("unhandled unary increment operator");
5940 }
5942 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction), LogicalTy, {});
5943 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5944 if (IncBin->getOpcode() == BO_AddAssign) {
5945 Step = IncBin->getRHS();
5946 } else if (IncBin->getOpcode() == BO_SubAssign) {
5947 Step =
5948 AssertSuccess(BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5949 } else
5950 llvm_unreachable("unhandled binary increment operator");
5951 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5952 switch (CondCXXOp->getOperator()) {
5953 case OO_PlusPlus:
5955 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5956 break;
5957 case OO_MinusMinus:
5959 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5960 break;
5961 case OO_PlusEqual:
5962 Step = CondCXXOp->getArg(1);
5963 break;
5964 case OO_MinusEqual:
5965 Step = AssertSuccess(
5966 BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5967 break;
5968 default:
5969 llvm_unreachable("unhandled overloaded increment operator");
5970 }
5971 } else
5972 llvm_unreachable("unknown increment expression");
5973
5974 CapturedStmt *DistanceFunc =
5975 buildDistanceFunc(*this, LogicalTy, CondRel, LHS, RHS, Step);
5976 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5977 *this, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5978 DeclRefExpr *LVRef = BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue,
5979 {}, nullptr, nullptr, {}, nullptr);
5980 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
5981 LoopVarFunc, LVRef);
5982}
5983
5985 // Handle a literal loop.
5986 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5987 return ActOnOpenMPCanonicalLoop(AStmt);
5988
5989 // If not a literal loop, it must be the result of a loop transformation.
5990 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(AStmt);
5991 assert(
5993 "Loop transformation directive expected");
5994 return LoopTransform;
5995}
5996
5998 CXXScopeSpec &MapperIdScopeSpec,
5999 const DeclarationNameInfo &MapperId,
6000 QualType Type,
6001 Expr *UnresolvedMapper);
6002
6003/// Perform DFS through the structure/class data members trying to find
6004/// member(s) with user-defined 'default' mapper and generate implicit map
6005/// clauses for such members with the found 'default' mapper.
6006static void
6009 // Check for the deault mapper for data members.
6010 if (S.getLangOpts().OpenMP < 50)
6011 return;
6012 SmallVector<OMPClause *, 4> ImplicitMaps;
6013 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
6014 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
6015 if (!C)
6016 continue;
6017 SmallVector<Expr *, 4> SubExprs;
6018 auto *MI = C->mapperlist_begin();
6019 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
6020 ++I, ++MI) {
6021 // Expression is mapped using mapper - skip it.
6022 if (*MI)
6023 continue;
6024 Expr *E = *I;
6025 // Expression is dependent - skip it, build the mapper when it gets
6026 // instantiated.
6027 if (E->isTypeDependent() || E->isValueDependent() ||
6029 continue;
6030 // Array section - need to check for the mapping of the array section
6031 // element.
6032 QualType CanonType = E->getType().getCanonicalType();
6033 if (CanonType->isSpecificBuiltinType(BuiltinType::OMPArraySection)) {
6034 const auto *OASE = cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts());
6035 QualType BaseType =
6037 QualType ElemType;
6038 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6039 ElemType = ATy->getElementType();
6040 else
6041 ElemType = BaseType->getPointeeType();
6042 CanonType = ElemType;
6043 }
6044
6045 // DFS over data members in structures/classes.
6047 1, {CanonType, nullptr});
6048 llvm::DenseMap<const Type *, Expr *> Visited;
6050 1, {nullptr, 1});
6051 while (!Types.empty()) {
6052 QualType BaseType;
6053 FieldDecl *CurFD;
6054 std::tie(BaseType, CurFD) = Types.pop_back_val();
6055 while (ParentChain.back().second == 0)
6056 ParentChain.pop_back();
6057 --ParentChain.back().second;
6058 if (BaseType.isNull())
6059 continue;
6060 // Only structs/classes are allowed to have mappers.
6061 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6062 if (!RD)
6063 continue;
6064 auto It = Visited.find(BaseType.getTypePtr());
6065 if (It == Visited.end()) {
6066 // Try to find the associated user-defined mapper.
6067 CXXScopeSpec MapperIdScopeSpec;
6068 DeclarationNameInfo DefaultMapperId;
6070 &S.Context.Idents.get("default")));
6071 DefaultMapperId.setLoc(E->getExprLoc());
6073 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
6074 BaseType, /*UnresolvedMapper=*/nullptr);
6075 if (ER.isInvalid())
6076 continue;
6077 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
6078 }
6079 // Found default mapper.
6080 if (It->second) {
6081 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
6083 OE->setIsUnique(/*V=*/true);
6084 Expr *BaseExpr = OE;
6085 for (const auto &P : ParentChain) {
6086 if (P.first) {
6087 BaseExpr = S.BuildMemberExpr(
6088 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6090 DeclAccessPair::make(P.first, P.first->getAccess()),
6091 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6092 P.first->getType(), VK_LValue, OK_Ordinary);
6093 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
6094 }
6095 }
6096 if (CurFD)
6097 BaseExpr = S.BuildMemberExpr(
6098 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6100 DeclAccessPair::make(CurFD, CurFD->getAccess()),
6101 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6102 CurFD->getType(), VK_LValue, OK_Ordinary);
6103 SubExprs.push_back(BaseExpr);
6104 continue;
6105 }
6106 // Check for the "default" mapper for data members.
6107 bool FirstIter = true;
6108 for (FieldDecl *FD : RD->fields()) {
6109 if (!FD)
6110 continue;
6111 QualType FieldTy = FD->getType();
6112 if (FieldTy.isNull() ||
6113 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6114 continue;
6115 if (FirstIter) {
6116 FirstIter = false;
6117 ParentChain.emplace_back(CurFD, 1);
6118 } else {
6119 ++ParentChain.back().second;
6120 }
6121 Types.emplace_back(FieldTy, FD);
6122 }
6123 }
6124 }
6125 if (SubExprs.empty())
6126 continue;
6127 CXXScopeSpec MapperIdScopeSpec;
6128 DeclarationNameInfo MapperId;
6129 if (OMPClause *NewClause = S.ActOnOpenMPMapClause(
6130 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
6131 MapperIdScopeSpec, MapperId, C->getMapType(),
6132 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6133 SubExprs, OMPVarListLocTy()))
6134 Clauses.push_back(NewClause);
6135 }
6136}
6137
6138bool Sema::mapLoopConstruct(llvm::SmallVector<OMPClause *> &ClausesWithoutBind,
6139 ArrayRef<OMPClause *> Clauses,
6140 OpenMPBindClauseKind &BindKind,
6141 OpenMPDirectiveKind &Kind,
6142 OpenMPDirectiveKind &PrevMappedDirective,
6143 SourceLocation StartLoc, SourceLocation EndLoc,
6144 const DeclarationNameInfo &DirName,
6145 OpenMPDirectiveKind CancelRegion) {
6146
6147 bool UseClausesWithoutBind = false;
6148
6149 // Restricting to "#pragma omp loop bind"
6150 if (getLangOpts().OpenMP >= 50 && Kind == OMPD_loop) {
6151
6152 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
6153
6154 if (BindKind == OMPC_BIND_unknown) {
6155 // Setting the enclosing teams or parallel construct for the loop
6156 // directive without bind clause.
6157 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6158
6159 if (ParentDirective == OMPD_unknown) {
6160 Diag(DSAStack->getDefaultDSALocation(),
6161 diag::err_omp_bind_required_on_loop);
6162 } else if (ParentDirective == OMPD_parallel ||
6163 ParentDirective == OMPD_target_parallel) {
6164 BindKind = OMPC_BIND_parallel;
6165 } else if (ParentDirective == OMPD_teams ||
6166 ParentDirective == OMPD_target_teams) {
6167 BindKind = OMPC_BIND_teams;
6168 }
6169 } else {
6170 // bind clause is present in loop directive. When the loop directive is
6171 // changed to a new directive the bind clause is not used. So, we should
6172 // set flag indicating to only use the clauses that aren't the
6173 // bind clause.
6174 UseClausesWithoutBind = true;
6175 }
6176
6177 for (OMPClause *C : Clauses) {
6178 // Spec restriction : bind(teams) and reduction not permitted.
6179 if (BindKind == OMPC_BIND_teams &&
6180 C->getClauseKind() == llvm::omp::Clause::OMPC_reduction)
6181 Diag(DSAStack->getDefaultDSALocation(),
6182 diag::err_omp_loop_reduction_clause);
6183
6184 // A new Vector ClausesWithoutBind, which does not contain the bind
6185 // clause, for passing to new directive.
6186 if (C->getClauseKind() != llvm::omp::Clause::OMPC_bind)
6187 ClausesWithoutBind.push_back(C);
6188 }
6189
6190 switch (BindKind) {
6191 case OMPC_BIND_parallel:
6192 Kind = OMPD_for;
6193 DSAStack->setCurrentDirective(OMPD_for);
6194 DSAStack->setMappedDirective(OMPD_loop);
6195 PrevMappedDirective = OMPD_loop;
6196 break;
6197 case OMPC_BIND_teams:
6198 Kind = OMPD_distribute;
6199 DSAStack->setCurrentDirective(OMPD_distribute);
6200 DSAStack->setMappedDirective(OMPD_loop);
6201 PrevMappedDirective = OMPD_loop;
6202 break;
6203 case OMPC_BIND_thread:
6204 Kind = OMPD_simd;
6205 DSAStack->setCurrentDirective(OMPD_simd);
6206 DSAStack->setMappedDirective(OMPD_loop);
6207 PrevMappedDirective = OMPD_loop;
6208 break;
6209 case OMPC_BIND_unknown:
6210 break;
6211 }
6212 } else if (PrevMappedDirective == OMPD_loop) {
6213 /// An initial pass after recognizing all the statements is done in the
6214 /// Parser when the directive OMPD_loop is mapped to OMPD_for,
6215 /// OMPD_distribute or OMPD_simd. A second transform pass with call from
6216 /// clang::TreeTransform::TransformOMPExecutableDirective() is done
6217 /// with the Directive as one of the above mapped directive without
6218 /// the bind clause. Then "PrevMappedDirective" stored in the
6219 /// OMPExecutableDirective is accessed and hence this else statement.
6220
6221 DSAStack->setMappedDirective(OMPD_loop);
6222 }
6223
6224 return UseClausesWithoutBind;
6225}
6226
6228 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6229 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6230 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc,
6231 OpenMPDirectiveKind PrevMappedDirective) {
6232 StmtResult Res = StmtError();
6234 llvm::SmallVector<OMPClause *> ClausesWithoutBind;
6235 bool UseClausesWithoutBind = false;
6236
6237 if (const OMPBindClause *BC =
6238 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6239 BindKind = BC->getBindKind();
6240
6241 // Variable used to note down the DirectiveKind because mapLoopConstruct may
6242 // change "Kind" variable, due to mapping of "omp loop" to other directives.
6243 OpenMPDirectiveKind DK = Kind;
6244 if (Kind == OMPD_loop || PrevMappedDirective == OMPD_loop) {
6245 UseClausesWithoutBind = mapLoopConstruct(
6246 ClausesWithoutBind, Clauses, BindKind, Kind, PrevMappedDirective,
6247 StartLoc, EndLoc, DirName, CancelRegion);
6248 DK = OMPD_loop;
6249 }
6250
6251 // First check CancelRegion which is then used in checkNestingOfRegions.
6252 if (checkCancelRegion(*this, Kind, CancelRegion, StartLoc) ||
6253 checkNestingOfRegions(*this, DSAStack, DK, DirName, CancelRegion,
6254 BindKind, StartLoc)) {
6255 return StmtError();
6256 }
6257
6258 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6261 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6262
6263 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6264 VarsWithInheritedDSAType VarsWithInheritedDSA;
6265 bool ErrorFound = false;
6266 if (getLangOpts().OpenMP >= 50 && UseClausesWithoutBind) {
6267 ClausesWithImplicit.append(ClausesWithoutBind.begin(),
6268 ClausesWithoutBind.end());
6269 } else {
6270 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6271 }
6272 if (AStmt && !CurContext->isDependentContext() && Kind != OMPD_atomic &&
6273 Kind != OMPD_critical && Kind != OMPD_section && Kind != OMPD_master &&
6274 Kind != OMPD_masked && !isOpenMPLoopTransformationDirective(Kind)) {
6275 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6276
6277 // Check default data sharing attributes for referenced variables.
6278 DSAAttrChecker DSAChecker(DSAStack, *this, cast<CapturedStmt>(AStmt));
6279 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6280 Stmt *S = AStmt;
6281 while (--ThisCaptureLevel >= 0)
6282 S = cast<CapturedStmt>(S)->getCapturedStmt();
6283 DSAChecker.Visit(S);
6285 !isOpenMPTaskingDirective(Kind)) {
6286 // Visit subcaptures to generate implicit clauses for captured vars.
6287 auto *CS = cast<CapturedStmt>(AStmt);
6289 getOpenMPCaptureRegions(CaptureRegions, Kind);
6290 // Ignore outer tasking regions for target directives.
6291 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6292 CS = cast<CapturedStmt>(CS->getCapturedStmt());
6293 DSAChecker.visitSubCaptures(CS);
6294 }
6295 if (DSAChecker.isErrorFound())
6296 return StmtError();
6297 // Generate list of implicitly defined firstprivate variables.
6298 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6299
6300 SmallVector<Expr *, 4> ImplicitFirstprivates(
6301 DSAChecker.getImplicitFirstprivate().begin(),
6302 DSAChecker.getImplicitFirstprivate().end());
6303 SmallVector<Expr *, 4> ImplicitPrivates(
6304 DSAChecker.getImplicitPrivate().begin(),
6305 DSAChecker.getImplicitPrivate().end());
6306 const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
6307 SmallVector<Expr *, 4> ImplicitMaps[DefaultmapKindNum][OMPC_MAP_delete];
6309 ImplicitMapModifiers[DefaultmapKindNum];
6311 ImplicitMapModifiersLoc[DefaultmapKindNum];
6312 // Get the original location of present modifier from Defaultmap clause.
6313 SourceLocation PresentModifierLocs[DefaultmapKindNum];
6314 for (OMPClause *C : Clauses) {
6315 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6316 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6317 PresentModifierLocs[DMC->getDefaultmapKind()] =
6318 DMC->getDefaultmapModifierLoc();
6319 }
6320 for (unsigned VC = 0; VC < DefaultmapKindNum; ++VC) {
6321 auto Kind = static_cast<OpenMPDefaultmapClauseKind>(VC);
6322 for (unsigned I = 0; I < OMPC_MAP_delete; ++I) {
6323 ArrayRef<Expr *> ImplicitMap = DSAChecker.getImplicitMap(
6324 Kind, static_cast<OpenMPMapClauseKind>(I));
6325 ImplicitMaps[VC][I].append(ImplicitMap.begin(), ImplicitMap.end());
6326 }
6327 ArrayRef<OpenMPMapModifierKind> ImplicitModifier =
6328 DSAChecker.getImplicitMapModifier(Kind);
6329 ImplicitMapModifiers[VC].append(ImplicitModifier.begin(),
6330 ImplicitModifier.end());
6331 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[VC]),
6332 ImplicitModifier.size(), PresentModifierLocs[VC]);
6333 }
6334 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6335 for (OMPClause *C : Clauses) {
6336 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6337 for (Expr *E : IRC->taskgroup_descriptors())
6338 if (E)
6339 ImplicitFirstprivates.emplace_back(E);
6340 }
6341 // OpenMP 5.0, 2.10.1 task Construct
6342 // [detach clause]... The event-handle will be considered as if it was
6343 // specified on a firstprivate clause.
6344 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6345 ImplicitFirstprivates.push_back(DC->getEventHandler());
6346 }
6347 if (!ImplicitFirstprivates.empty()) {
6349 ImplicitFirstprivates, SourceLocation(), SourceLocation(),
6350 SourceLocation())) {
6351 ClausesWithImplicit.push_back(Implicit);
6352 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6353 ImplicitFirstprivates.size();
6354 } else {
6355 ErrorFound = true;
6356 }
6357 }
6358 if (!ImplicitPrivates.empty()) {
6359 if (OMPClause *Implicit =
6360 ActOnOpenMPPrivateClause(ImplicitPrivates, SourceLocation(),
6362 ClausesWithImplicit.push_back(Implicit);
6363 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6364 ImplicitPrivates.size();
6365 } else {
6366 ErrorFound = true;
6367 }
6368 }
6369 // OpenMP 5.0 [2.19.7]
6370 // If a list item appears in a reduction, lastprivate or linear
6371 // clause on a combined target construct then it is treated as
6372 // if it also appears in a map clause with a map-type of tofrom
6373 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6375 SmallVector<Expr *, 4> ImplicitExprs;
6376 for (OMPClause *C : Clauses) {
6377 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6378 for (Expr *E : RC->varlists())
6379 if (!isa<DeclRefExpr>(E->IgnoreParenImpCasts()))
6380 ImplicitExprs.emplace_back(E);
6381 }
6382 if (!ImplicitExprs.empty()) {
6383 ArrayRef<Expr *> Exprs = ImplicitExprs;
6384 CXXScopeSpec MapperIdScopeSpec;
6385 DeclarationNameInfo MapperId;
6386 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6388 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6389 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6390 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6391 ClausesWithImplicit.emplace_back(Implicit);
6392 }
6393 }
6394 for (unsigned I = 0, E = DefaultmapKindNum; I < E; ++I) {
6395 int ClauseKindCnt = -1;
6396 for (ArrayRef<Expr *> ImplicitMap : ImplicitMaps[I]) {
6397 ++ClauseKindCnt;
6398 if (ImplicitMap.empty())
6399 continue;
6400 CXXScopeSpec MapperIdScopeSpec;
6401 DeclarationNameInfo MapperId;
6402 auto Kind = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6403 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6404 nullptr, ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I],
6405 MapperIdScopeSpec, MapperId, Kind, /*IsMapTypeImplicit=*/true,
6406 SourceLocation(), SourceLocation(), ImplicitMap,
6407 OMPVarListLocTy())) {
6408 ClausesWithImplicit.emplace_back(Implicit);
6409 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6410 ImplicitMap.size();
6411 } else {
6412 ErrorFound = true;
6413 }
6414 }
6415 }
6416 // Build expressions for implicit maps of data members with 'default'
6417 // mappers.
6418 if (LangOpts.OpenMP >= 50)
6420 ClausesWithImplicit);
6421 }
6422
6423 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6424 switch (Kind) {
6425 case OMPD_parallel:
6426 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6427 EndLoc);
6428 AllowedNameModifiers.push_back(OMPD_parallel);
6429 break;
6430 case OMPD_simd:
6431 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6432 VarsWithInheritedDSA);
6433 if (LangOpts.OpenMP >= 50)
6434 AllowedNameModifiers.push_back(OMPD_simd);
6435 break;
6436 case OMPD_tile:
6437 Res =
6438 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6439 break;
6440 case OMPD_unroll:
6441 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6442 EndLoc);
6443 break;
6444 case OMPD_for:
6445 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6446 VarsWithInheritedDSA);
6447 break;
6448 case OMPD_for_simd:
6449 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6450 EndLoc, VarsWithInheritedDSA);
6451 if (LangOpts.OpenMP >= 50)
6452 AllowedNameModifiers.push_back(OMPD_simd);
6453 break;
6454 case OMPD_sections:
6455 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6456 EndLoc);
6457 break;
6458 case OMPD_section:
6459 assert(ClausesWithImplicit.empty() &&
6460 "No clauses are allowed for 'omp section' directive");
6461 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6462 break;
6463 case OMPD_single:
6464 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6465 EndLoc);
6466 break;
6467 case OMPD_master:
6468 assert(ClausesWithImplicit.empty() &&
6469 "No clauses are allowed for 'omp master' directive");
6470 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6471 break;
6472 case OMPD_masked:
6473 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6474 EndLoc);
6475 break;
6476 case OMPD_critical:
6477 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6478 StartLoc, EndLoc);
6479 break;
6480 case OMPD_parallel_for:
6481 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6482 EndLoc, VarsWithInheritedDSA);
6483 AllowedNameModifiers.push_back(OMPD_parallel);
6484 break;
6485 case OMPD_parallel_for_simd:
6487 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6488 AllowedNameModifiers.push_back(OMPD_parallel);
6489 if (LangOpts.OpenMP >= 50)
6490 AllowedNameModifiers.push_back(OMPD_simd);
6491 break;
6492 case OMPD_scope:
6493 Res =
6494 ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6495 break;
6496 case OMPD_parallel_master:
6497 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6498 StartLoc, EndLoc);
6499 AllowedNameModifiers.push_back(OMPD_parallel);
6500 break;
6501 case OMPD_parallel_masked:
6502 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6503 StartLoc, EndLoc);
6504 AllowedNameModifiers.push_back(OMPD_parallel);
6505 break;
6506 case OMPD_parallel_sections:
6507 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6508 StartLoc, EndLoc);
6509 AllowedNameModifiers.push_back(OMPD_parallel);
6510 break;
6511 case OMPD_task:
6512 Res =
6513 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6514 AllowedNameModifiers.push_back(OMPD_task);
6515 break;
6516 case OMPD_taskyield:
6517 assert(ClausesWithImplicit.empty() &&
6518 "No clauses are allowed for 'omp taskyield' directive");
6519 assert(AStmt == nullptr &&
6520 "No associated statement allowed for 'omp taskyield' directive");
6521 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6522 break;
6523 case OMPD_error:
6524 assert(AStmt == nullptr &&
6525 "No associated statement allowed for 'omp error' directive");
6526 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6527 break;
6528 case OMPD_barrier:
6529 assert(ClausesWithImplicit.empty() &&
6530 "No clauses are allowed for 'omp barrier' directive");
6531 assert(AStmt == nullptr &&
6532 "No associated statement allowed for 'omp barrier' directive");
6533 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6534 break;
6535 case OMPD_taskwait:
6536 assert(AStmt == nullptr &&
6537 "No associated statement allowed for 'omp taskwait' directive");
6538 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6539 break;
6540 case OMPD_taskgroup:
6541 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6542 EndLoc);
6543 break;
6544 case OMPD_flush:
6545 assert(AStmt == nullptr &&
6546 "No associated statement allowed for 'omp flush' directive");
6547 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6548 break;
6549 case OMPD_depobj:
6550 assert(AStmt == nullptr &&
6551 "No associated statement allowed for 'omp depobj' directive");
6552 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6553 break;
6554 case OMPD_scan:
6555 assert(AStmt == nullptr &&
6556 "No associated statement allowed for 'omp scan' directive");
6557 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6558 break;
6559 case OMPD_ordered:
6560 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6561 EndLoc);
6562 break;
6563 case OMPD_atomic:
6564 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6565 EndLoc);
6566 break;
6567 case OMPD_teams:
6568 Res =
6569 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6570 break;
6571 case OMPD_target:
6572 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6573 EndLoc);
6574 AllowedNameModifiers.push_back(OMPD_target);
6575 break;
6576 case OMPD_target_parallel:
6577 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6578 StartLoc, EndLoc);
6579 AllowedNameModifiers.push_back(OMPD_target);
6580 AllowedNameModifiers.push_back(OMPD_parallel);
6581 break;
6582 case OMPD_target_parallel_for:
6584 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6585 AllowedNameModifiers.push_back(OMPD_target);
6586 AllowedNameModifiers.push_back(OMPD_parallel);
6587 break;
6588 case OMPD_cancellation_point:
6589 assert(ClausesWithImplicit.empty() &&
6590 "No clauses are allowed for 'omp cancellation point' directive");
6591 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6592 "cancellation point' directive");
6593 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6594 break;
6595 case OMPD_cancel:
6596 assert(AStmt == nullptr &&
6597 "No associated statement allowed for 'omp cancel' directive");
6598 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6599 CancelRegion);
6600 AllowedNameModifiers.push_back(OMPD_cancel);
6601 break;
6602 case OMPD_target_data:
6603 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6604 EndLoc);
6605 AllowedNameModifiers.push_back(OMPD_target_data);
6606 break;
6607 case OMPD_target_enter_data:
6608 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6609 EndLoc, AStmt);
6610 AllowedNameModifiers.push_back(OMPD_target_enter_data);
6611 break;
6612 case OMPD_target_exit_data:
6613 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6614 EndLoc, AStmt);
6615 AllowedNameModifiers.push_back(OMPD_target_exit_data);
6616 break;
6617 case OMPD_taskloop:
6618 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6619 EndLoc, VarsWithInheritedDSA);
6620 AllowedNameModifiers.push_back(OMPD_taskloop);
6621 break;
6622 case OMPD_taskloop_simd:
6623 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6624 EndLoc, VarsWithInheritedDSA);
6625 AllowedNameModifiers.push_back(OMPD_taskloop);
6626 if (LangOpts.OpenMP >= 50)
6627 AllowedNameModifiers.push_back(OMPD_simd);
6628 break;
6629 case OMPD_master_taskloop:
6631 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6632 AllowedNameModifiers.push_back(OMPD_taskloop);
6633 break;
6634 case OMPD_masked_taskloop:
6636 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6637 AllowedNameModifiers.push_back(OMPD_taskloop);
6638 break;
6639 case OMPD_master_taskloop_simd:
6641 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6642 AllowedNameModifiers.push_back(OMPD_taskloop);
6643 if (LangOpts.OpenMP >= 50)
6644 AllowedNameModifiers.push_back(OMPD_simd);
6645 break;
6646 case OMPD_masked_taskloop_simd:
6648 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6649 if (LangOpts.OpenMP >= 51) {
6650 AllowedNameModifiers.push_back(OMPD_taskloop);
6651 AllowedNameModifiers.push_back(OMPD_simd);
6652 }
6653 break;
6654 case OMPD_parallel_master_taskloop:
6656 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6657 AllowedNameModifiers.push_back(OMPD_taskloop);
6658 AllowedNameModifiers.push_back(OMPD_parallel);
6659 break;
6660 case OMPD_parallel_masked_taskloop:
6662 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6663 if (LangOpts.OpenMP >= 51) {
6664 AllowedNameModifiers.push_back(OMPD_taskloop);
6665 AllowedNameModifiers.push_back(OMPD_parallel);
6666 }
6667 break;
6668 case OMPD_parallel_master_taskloop_simd:
6670 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6671 AllowedNameModifiers.push_back(OMPD_taskloop);
6672 AllowedNameModifiers.push_back(OMPD_parallel);
6673 if (LangOpts.OpenMP >= 50)
6674 AllowedNameModifiers.push_back(OMPD_simd);
6675 break;
6676 case OMPD_parallel_masked_taskloop_simd:
6678 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6679 if (LangOpts.OpenMP >= 51) {
6680 AllowedNameModifiers.push_back(OMPD_taskloop);
6681 AllowedNameModifiers.push_back(OMPD_parallel);
6682 AllowedNameModifiers.push_back(OMPD_simd);
6683 }
6684 break;
6685 case OMPD_distribute:
6686 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6687 EndLoc, VarsWithInheritedDSA);
6688 break;
6689 case OMPD_target_update:
6690 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6691 EndLoc, AStmt);
6692 AllowedNameModifiers.push_back(OMPD_target_update);
6693 break;
6694 case OMPD_distribute_parallel_for:
6696 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6697 AllowedNameModifiers.push_back(OMPD_parallel);
6698 break;
6699 case OMPD_distribute_parallel_for_simd:
6701 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6702 AllowedNameModifiers.push_back(OMPD_parallel);
6703 if (LangOpts.OpenMP >= 50)
6704 AllowedNameModifiers.push_back(OMPD_simd);
6705 break;
6706 case OMPD_distribute_simd:
6708 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6709 if (LangOpts.OpenMP >= 50)
6710 AllowedNameModifiers.push_back(OMPD_simd);
6711 break;
6712 case OMPD_target_parallel_for_simd:
6714 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6715 AllowedNameModifiers.push_back(OMPD_target);
6716 AllowedNameModifiers.push_back(OMPD_parallel);
6717 if (LangOpts.OpenMP >= 50)
6718 AllowedNameModifiers.push_back(OMPD_simd);
6719 break;
6720 case OMPD_target_simd:
6721 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6722 EndLoc, VarsWithInheritedDSA);
6723 AllowedNameModifiers.push_back(OMPD_target);
6724 if (LangOpts.OpenMP >= 50)
6725 AllowedNameModifiers.push_back(OMPD_simd);
6726 break;
6727 case OMPD_teams_distribute:
6729 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6730 break;
6731 case OMPD_teams_distribute_simd:
6733 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6734 if (LangOpts.OpenMP >= 50)
6735 AllowedNameModifiers.push_back(OMPD_simd);
6736 break;
6737 case OMPD_teams_distribute_parallel_for_simd:
6739 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6740 AllowedNameModifiers.push_back(OMPD_parallel);
6741 if (LangOpts.OpenMP >= 50)
6742 AllowedNameModifiers.push_back(OMPD_simd);
6743 break;
6744 case OMPD_teams_distribute_parallel_for:
6746 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6747 AllowedNameModifiers.push_back(OMPD_parallel);
6748 break;
6749 case OMPD_target_teams:
6750 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6751 EndLoc);
6752 AllowedNameModifiers.push_back(OMPD_target);
6753 break;
6754 case OMPD_target_teams_distribute:
6756 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6757 AllowedNameModifiers.push_back(OMPD_target);
6758 break;
6759 case OMPD_target_teams_distribute_parallel_for:
6761 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6762 AllowedNameModifiers.push_back(OMPD_target);
6763 AllowedNameModifiers.push_back(OMPD_parallel);
6764 break;
6765 case OMPD_target_teams_distribute_parallel_for_simd:
6767 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6768 AllowedNameModifiers.push_back(OMPD_target);
6769 AllowedNameModifiers.push_back(OMPD_parallel);
6770 if (LangOpts.OpenMP >= 50)
6771 AllowedNameModifiers.push_back(OMPD_simd);
6772 break;
6773 case OMPD_target_teams_distribute_simd:
6775 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6776 AllowedNameModifiers.push_back(OMPD_target);
6777 if (LangOpts.OpenMP >= 50)
6778 AllowedNameModifiers.push_back(OMPD_simd);
6779 break;
6780 case OMPD_interop:
6781 assert(AStmt == nullptr &&
6782 "No associated statement allowed for 'omp interop' directive");
6783 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6784 break;
6785 case OMPD_dispatch:
6786 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6787 EndLoc);
6788 break;
6789 case OMPD_loop:
6790 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6791 EndLoc, VarsWithInheritedDSA);
6792 break;
6793 case OMPD_teams_loop:
6795 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6796 break;
6797 case OMPD_target_teams_loop:
6799 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6800 AllowedNameModifiers.push_back(OMPD_target);
6801 break;
6802 case OMPD_parallel_loop:
6804 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6805 break;
6806 case OMPD_target_parallel_loop:
6808 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6809 break;
6810 case OMPD_declare_target:
6811 case OMPD_end_declare_target:
6812 case OMPD_threadprivate:
6813 case OMPD_allocate:
6814 case OMPD_declare_reduction:
6815 case OMPD_declare_mapper:
6816 case OMPD_declare_simd:
6817 case OMPD_requires:
6818 case OMPD_declare_variant:
6819 case OMPD_begin_declare_variant:
6820 case OMPD_end_declare_variant:
6821 llvm_unreachable("OpenMP Directive is not allowed");
6822 case OMPD_unknown:
6823 default:
6824 llvm_unreachable("Unknown OpenMP directive");
6825 }
6826
6827 ErrorFound = Res.isInvalid() || ErrorFound;
6828
6829 // Check variables in the clauses if default(none) or
6830 // default(firstprivate) was specified.
6831 if (DSAStack->getDefaultDSA() == DSA_none ||
6832 DSAStack->getDefaultDSA() == DSA_private ||
6833 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6834 DSAAttrChecker DSAChecker(DSAStack, *this, nullptr);
6835 for (OMPClause *C : Clauses) {
6836 switch (C->getClauseKind()) {
6837 case OMPC_num_threads:
6838 case OMPC_dist_schedule:
6839 // Do not analyse if no parent teams directive.
6840 if (isOpenMPTeamsDirective(Kind))
6841 break;
6842 continue;
6843 case OMPC_if:
6844 if (isOpenMPTeamsDirective(Kind) &&
6845 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6846 break;
6847 if (isOpenMPParallelDirective(Kind) &&
6849 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6850 break;
6851 continue;
6852 case OMPC_schedule:
6853 case OMPC_detach:
6854 break;
6855 case OMPC_grainsize:
6856 case OMPC_num_tasks:
6857 case OMPC_final:
6858 case OMPC_priority:
6859 case OMPC_novariants:
6860 case OMPC_nocontext:
6861 // Do not analyze if no parent parallel directive.
6862 if (isOpenMPParallelDirective(Kind))
6863 break;
6864 continue;
6865 case OMPC_ordered:
6866 case OMPC_device:
6867 case OMPC_num_teams:
6868 case OMPC_thread_limit:
6869 case OMPC_hint:
6870 case OMPC_collapse:
6871 case OMPC_safelen:
6872 case OMPC_simdlen:
6873 case OMPC_sizes:
6874 case OMPC_default:
6875 case OMPC_proc_bind:
6876 case OMPC_private:
6877 case OMPC_firstprivate:
6878 case OMPC_lastprivate:
6879 case OMPC_shared:
6880 case OMPC_reduction:
6881 case OMPC_task_reduction:
6882 case OMPC_in_reduction:
6883 case OMPC_linear:
6884 case OMPC_aligned:
6885 case OMPC_copyin:
6886 case OMPC_copyprivate:
6887 case OMPC_nowait:
6888 case OMPC_untied:
6889 case OMPC_mergeable:
6890 case OMPC_allocate:
6891 case OMPC_read:
6892 case OMPC_write:
6893 case OMPC_update:
6894 case OMPC_capture:
6895 case OMPC_compare:
6896 case OMPC_seq_cst:
6897 case OMPC_acq_rel:
6898 case OMPC_acquire:
6899 case OMPC_release:
6900 case OMPC_relaxed:
6901 case OMPC_depend:
6902 case OMPC_threads:
6903 case OMPC_simd:
6904 case OMPC_map:
6905 case OMPC_nogroup:
6906 case OMPC_defaultmap:
6907 case OMPC_to:
6908 case OMPC_from:
6909 case OMPC_use_device_ptr:
6910 case OMPC_use_device_addr:
6911 case OMPC_is_device_ptr:
6912 case OMPC_has_device_addr:
6913 case OMPC_nontemporal:
6914 case OMPC_order:
6915 case OMPC_destroy:
6916 case OMPC_inclusive:
6917 case OMPC_exclusive:
6918 case OMPC_uses_allocators:
6919 case OMPC_affinity:
6920 case OMPC_bind:
6921 case OMPC_filter:
6922 continue;
6923 case OMPC_allocator:
6924 case OMPC_flush:
6925 case OMPC_depobj:
6926 case OMPC_threadprivate:
6927 case OMPC_uniform:
6928 case OMPC_unknown:
6929 case OMPC_unified_address:
6930 case OMPC_unified_shared_memory:
6931 case OMPC_reverse_offload:
6932 case OMPC_dynamic_allocators:
6933 case OMPC_atomic_default_mem_order:
6934 case OMPC_device_type:
6935 case OMPC_match:
6936 case OMPC_when:
6937 case OMPC_at:
6938 case OMPC_severity:
6939 case OMPC_message:
6940 default:
6941 llvm_unreachable("Unexpected clause");
6942 }
6943 for (Stmt *CC : C->children()) {
6944 if (CC)
6945 DSAChecker.Visit(CC);
6946 }
6947 }
6948 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6949 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6950 }
6951 for (const auto &P : VarsWithInheritedDSA) {
6952 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6953 continue;
6954 ErrorFound = true;
6955 if (DSAStack->getDefaultDSA() == DSA_none ||
6956 DSAStack->getDefaultDSA() == DSA_private ||
6957 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6958 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6959 << P.first << P.second->getSourceRange();
6960 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6961 } else if (getLangOpts().OpenMP >= 50) {
6962 Diag(P.second->getExprLoc(),
6963 diag::err_omp_defaultmap_no_attr_for_variable)
6964 << P.first << P.second->getSourceRange();
6965 Diag(DSAStack->getDefaultDSALocation(),
6966 diag::note_omp_defaultmap_attr_none);
6967 }
6968 }
6969
6970 if (!AllowedNameModifiers.empty())
6971 ErrorFound = checkIfClauses(*this, Kind, Clauses, AllowedNameModifiers) ||
6972 ErrorFound;
6973
6974 if (ErrorFound)
6975 return StmtError();
6976
6979 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6980 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6981 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6982 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6983 // Register target to DSA Stack.
6984 DSAStack->addTargetDirLocation(StartLoc);
6985 }
6986
6987 return Res;
6988}
6989
6991 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6992 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6993 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6994 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6995 assert(Aligneds.size() == Alignments.size());
6996 assert(Linears.size() == LinModifiers.size());
6997 assert(Linears.size() == Steps.size());
6998 if (!DG || DG.get().isNull())
6999 return DeclGroupPtrTy();
7000
7001 const int SimdId = 0;
7002 if (!DG.get().isSingleDecl()) {
7003 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7004 << SimdId;
7005 return DG;
7006 }
7007 Decl *ADecl = DG.get().getSingleDecl();
7008 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7009 ADecl = FTD->getTemplatedDecl();
7010
7011 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7012 if (!FD) {
7013 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
7014 return DeclGroupPtrTy();
7015 }
7016
7017 // OpenMP [2.8.2, declare simd construct, Description]
7018 // The parameter of the simdlen clause must be a constant positive integer
7019 // expression.
7020 ExprResult SL;
7021 if (Simdlen)
7022 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
7023 // OpenMP [2.8.2, declare simd construct, Description]
7024 // The special this pointer can be used as if was one of the arguments to the
7025 // function in any of the linear, aligned, or uniform clauses.
7026 // The uniform clause declares one or more arguments to have an invariant
7027 // value for all concurrent invocations of the function in the execution of a
7028 // single SIMD loop.
7029 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
7030 const Expr *UniformedLinearThis = nullptr;
7031 for (const Expr *E : Uniforms) {
7032 E = E->IgnoreParenImpCasts();
7033 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7034 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
7035 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7036 FD->getParamDecl(PVD->getFunctionScopeIndex())
7037 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
7038 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
7039 continue;
7040 }
7041 if (isa<CXXThisExpr>(E)) {
7042 UniformedLinearThis = E;
7043 continue;
7044 }
7045 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7046 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7047 }
7048 // OpenMP [2.8.2, declare simd construct, Description]
7049 // The aligned clause declares that the object to which each list item points
7050 // is aligned to the number of bytes expressed in the optional parameter of
7051 // the aligned clause.
7052 // The special this pointer can be used as if was one of the arguments to the
7053 // function in any of the linear, aligned, or uniform clauses.
7054 // The type of list items appearing in the aligned clause must be array,
7055 // pointer, reference to array, or reference to pointer.
7056 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
7057 const Expr *AlignedThis = nullptr;
7058 for (const Expr *E : Aligneds) {
7059 E = E->IgnoreParenImpCasts();
7060 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7061 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7062 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7063 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7064 FD->getParamDecl(PVD->getFunctionScopeIndex())
7065 ->getCanonicalDecl() == CanonPVD) {
7066 // OpenMP [2.8.1, simd construct, Restrictions]
7067 // A list-item cannot appear in more than one aligned clause.
7068 if (AlignedArgs.count(CanonPVD) > 0) {
7069 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
7070 << 1 << getOpenMPClauseName(OMPC_aligned)
7071 << E->getSourceRange();
7072 Diag(AlignedArgs[CanonPVD]->getExprLoc(),
7073 diag::note_omp_explicit_dsa)
7074 << getOpenMPClauseName(OMPC_aligned);
7075 continue;
7076 }
7077 AlignedArgs[CanonPVD] = E;
7078 QualType QTy = PVD->getType()
7079 .getNonReferenceType()
7080 .getUnqualifiedType()
7081 .getCanonicalType();
7082 const Type *Ty = QTy.getTypePtrOrNull();
7083 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
7084 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
7085 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
7086 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
7087 }
7088 continue;
7089 }
7090 }
7091 if (isa<CXXThisExpr>(E)) {
7092 if (AlignedThis) {
7093 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
7094 << 2 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange();
7095 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
7096 << getOpenMPClauseName(OMPC_aligned);
7097 }
7098 AlignedThis = E;
7099 continue;
7100 }
7101 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7102 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7103 }
7104 // The optional parameter of the aligned clause, alignment, must be a constant
7105 // positive integer expression. If no optional parameter is specified,
7106 // implementation-defined default alignments for SIMD instructions on the
7107 // target platforms are assumed.
7109 for (Expr *E : Alignments) {
7110 ExprResult Align;
7111 if (E)
7112 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
7113 NewAligns.push_back(Align.get());
7114 }
7115 // OpenMP [2.8.2, declare simd construct, Description]
7116 // The linear clause declares one or more list items to be private to a SIMD
7117 // lane and to have a linear relationship with respect to the iteration space
7118 // of a loop.
7119 // The special this pointer can be used as if was one of the arguments to the
7120 // function in any of the linear, aligned, or uniform clauses.
7121 // When a linear-step expression is specified in a linear clause it must be
7122 // either a constant integer expression or an integer-typed parameter that is
7123 // specified in a uniform clause on the directive.
7124 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7125 const bool IsUniformedThis = UniformedLinearThis != nullptr;
7126 auto MI = LinModifiers.begin();
7127 for (const Expr *E : Linears) {
7128 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
7129 ++MI;
7130 E = E->IgnoreParenImpCasts();
7131 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7132 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7133 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7134 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7135 FD->getParamDecl(PVD->getFunctionScopeIndex())
7136 ->getCanonicalDecl() == CanonPVD) {
7137 // OpenMP [2.15.3.7, linear Clause, Restrictions]
7138 // A list-item cannot appear in more than one linear clause.
7139 if (LinearArgs.count(CanonPVD) > 0) {
7140 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7141 << getOpenMPClauseName(OMPC_linear)
7142 << getOpenMPClauseName(OMPC_linear) << E->getSourceRange();
7143 Diag(LinearArgs[CanonPVD]->getExprLoc(),
7144 diag::note_omp_explicit_dsa)
7145 << getOpenMPClauseName(OMPC_linear);
7146 continue;
7147 }
7148 // Each argument can appear in at most one uniform or linear clause.
7149 if (UniformedArgs.count(CanonPVD) > 0) {
7150 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7151 << getOpenMPClauseName(OMPC_linear)
7152 << getOpenMPClauseName(OMPC_uniform) << E->getSourceRange();
7153 Diag(UniformedArgs[CanonPVD]->getExprLoc(),
7154 diag::note_omp_explicit_dsa)
7155 << getOpenMPClauseName(OMPC_uniform);
7156 continue;
7157 }
7158 LinearArgs[CanonPVD] = E;
7159 if (E->isValueDependent() || E->isTypeDependent() ||
7162 continue;
7163 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
7164 PVD->getOriginalType(),
7165 /*IsDeclareSimd=*/true);
7166 continue;
7167 }
7168 }
7169 if (isa<CXXThisExpr>(E)) {
7170 if (UniformedLinearThis) {
7171 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7172 << getOpenMPClauseName(OMPC_linear)
7173 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear)
7174 << E->getSourceRange();
7175 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
7176 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform
7177 : OMPC_linear);
7178 continue;
7179 }
7180 UniformedLinearThis = E;
7181 if (E->isValueDependent() || E->isTypeDependent() ||
7183 continue;
7184 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
7185 E->getType(), /*IsDeclareSimd=*/true);
7186 continue;
7187 }
7188 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7189 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7190 }
7191 Expr *Step = nullptr;
7192 Expr *NewStep = nullptr;
7193 SmallVector<Expr *, 4> NewSteps;
7194 for (Expr *E : Steps) {
7195 // Skip the same step expression, it was checked already.
7196 if (Step == E || !E) {
7197 NewSteps.push_back(E ? NewStep : nullptr);
7198 continue;
7199 }
7200 Step = E;
7201 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
7202 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7203 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7204 if (UniformedArgs.count(CanonPVD) == 0) {
7205 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
7206 << Step->getSourceRange();
7207 } else if (E->isValueDependent() || E->isTypeDependent() ||
7210 CanonPVD->getType()->hasIntegerRepresentation()) {
7211 NewSteps.push_back(Step);
7212 } else {
7213 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
7214 << Step->getSourceRange();
7215 }
7216 continue;
7217 }
7218 NewStep = Step;
7219 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
7220 !Step->isInstantiationDependent() &&
7222 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
7223 .get();
7224 if (NewStep)
7225 NewStep =
7226 VerifyIntegerConstantExpression(NewStep, /*FIXME*/ AllowFold).get();
7227 }
7228 NewSteps.push_back(NewStep);
7229 }
7230 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7231 Context, BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
7232 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
7233 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
7234 const_cast<Expr **>(Linears.data()), Linears.size(),
7235 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
7236 NewSteps.data(), NewSteps.size(), SR);
7237 ADecl->addAttr(NewAttr);
7238 return DG;
7239}
7240
7241static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7242 QualType NewType) {
7243 assert(NewType->isFunctionProtoType() &&
7244 "Expected function type with prototype.");
7245 assert(FD->getType()->isFunctionNoProtoType() &&
7246 "Expected function with type with no prototype.");
7247 assert(FDWithProto->getType()->isFunctionProtoType() &&
7248 "Expected function with prototype.");
7249 // Synthesize parameters with the same types.
7250 FD->setType(NewType);
7252 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7253 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
7254 SourceLocation(), nullptr, P->getType(),
7255 /*TInfo=*/nullptr, SC_None, nullptr);
7256 Param->setScopeInfo(0, Params.size());
7257 Param->setImplicit();
7258 Params.push_back(Param);
7259 }
7260
7261 FD->setParams(Params);
7262}
7263
7265 if (D->isInvalidDecl())
7266 return;
7267 FunctionDecl *FD = nullptr;
7268 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7269 FD = UTemplDecl->getTemplatedDecl();
7270 else
7271 FD = cast<FunctionDecl>(D);
7272 assert(FD && "Expected a function declaration!");
7273
7274 // If we are instantiating templates we do *not* apply scoped assumptions but
7275 // only global ones. We apply scoped assumption to the template definition
7276 // though.
7277 if (!inTemplateInstantiation()) {
7278 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7279 FD->addAttr(AA);
7280 }
7281 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7282 FD->addAttr(AA);
7283}
7284
7285Sema::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7286 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7287
7289 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7291 if (!D.getIdentifier())
7292 return;
7293
7294 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7295
7296 // Template specialization is an extension, check if we do it.
7297 bool IsTemplated = !TemplateParamLists.empty();
7298 if (IsTemplated &
7299 !DVScope.TI->isExtensionActive(
7300 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7301 return;
7302
7303 IdentifierInfo *BaseII = D.getIdentifier();
7304 LookupResult Lookup(*this, DeclarationName(BaseII), D.getIdentifierLoc(),
7306 LookupParsedName(Lookup, S, &D.getCXXScopeSpec());
7307
7309 QualType FType = TInfo->getType();
7310
7311 bool IsConstexpr =
7313 bool IsConsteval =
7315
7316 for (auto *Candidate : Lookup) {
7317 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7318 FunctionDecl *UDecl = nullptr;
7319 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7320 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7321 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7322 UDecl = FTD->getTemplatedDecl();
7323 } else if (!IsTemplated)
7324 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7325 if (!UDecl)
7326 continue;
7327
7328 // Don't specialize constexpr/consteval functions with
7329 // non-constexpr/consteval functions.
7330 if (UDecl->isConstexpr() && !IsConstexpr)
7331 continue;
7332 if (UDecl->isConsteval() && !IsConsteval)
7333 continue;
7334
7335 QualType UDeclTy = UDecl->getType();
7336 if (!UDeclTy->isDependentType()) {
7338 FType, UDeclTy, /* OfBlockPointer */ false,
7339 /* Unqualified */ false, /* AllowCXX */ true);
7340 if (NewType.isNull())
7341 continue;
7342 }
7343
7344 // Found a base!
7345 Bases.push_back(UDecl);
7346 }
7347
7348 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7349 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7350 // If no base was found we create a declaration that we use as base.
7351 if (Bases.empty() && UseImplicitBase) {
7353 Decl *BaseD = HandleDeclarator(S, D, TemplateParamLists);
7354 BaseD->setImplicit(true);
7355 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7356 Bases.push_back(BaseTemplD->getTemplatedDecl());
7357 else
7358 Bases.push_back(cast<FunctionDecl>(BaseD));
7359 }
7360
7361 std::string MangledName;
7362 MangledName += D.getIdentifier()->getName();
7363 MangledName += getOpenMPVariantManglingSeparatorStr();
7364 MangledName += DVScope.NameSuffix;
7365 IdentifierInfo &VariantII = Context.Idents.get(MangledName);
7366
7367 VariantII.setMangledOpenMPVariantName(true);
7368 D.SetIdentifier(&VariantII, D.getBeginLoc());
7369}
7370
7373 // Do not mark function as is used to prevent its emission if this is the
7374 // only place where it is used.
7377
7378 FunctionDecl *FD = nullptr;
7379 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7380 FD = UTemplDecl->getTemplatedDecl();
7381 else
7382 FD = cast<FunctionDecl>(D);
7383 auto *VariantFuncRef = DeclRefExpr::Create(
7385 /* RefersToEnclosingVariableOrCapture */ false,
7386 /* NameLoc */ FD->getLocation(), FD->getType(),
7388
7389 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7390 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7391 Context, VariantFuncRef, DVScope.TI,
7392 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7393 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7394 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7395 for (FunctionDecl *BaseFD : Bases)
7396 BaseFD->addAttr(OMPDeclareVariantA);
7397}
7398
7400 SourceLocation LParenLoc,
7401 MultiExprArg ArgExprs,
7402 SourceLocation RParenLoc, Expr *ExecConfig) {
7403 // The common case is a regular call we do not want to specialize at all. Try
7404 // to make that case fast by bailing early.
7405 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7406 if (!CE)
7407 return Call;
7408
7409 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7410 if (!CalleeFnDecl)
7411 return Call;
7412
7413 if (LangOpts.OpenMP >= 51 && CalleeFnDecl->getIdentifier() &&
7414 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7415 // checking for any calls inside an Order region
7417 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7418 }
7419
7420 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7421 return Call;
7422
7424 std::function<void(StringRef)> DiagUnknownTrait = [this,
7425 CE](StringRef ISATrait) {
7426 // TODO Track the selector locations in a way that is accessible here to
7427 // improve the diagnostic location.
7428 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7429 << ISATrait;
7430 };
7431 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7432 getCurFunctionDecl(), DSAStack->getConstructTraits());
7433
7434 QualType CalleeFnType = CalleeFnDecl->getType();
7435
7438 while (CalleeFnDecl) {
7439 for (OMPDeclareVariantAttr *A :
7440 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7441 Expr *VariantRef = A->getVariantFuncRef();
7442
7443 VariantMatchInfo VMI;
7444 OMPTraitInfo &TI = A->getTraitInfo();
7446 if (!isVariantApplicableInContext(VMI, OMPCtx,
7447 /* DeviceSetOnly */ false))
7448 continue;
7449
7450 VMIs.push_back(VMI);
7451 Exprs.push_back(VariantRef);
7452 }
7453
7454 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7455 }
7456
7457 ExprResult NewCall;
7458 do {
7459 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7460 if (BestIdx < 0)
7461 return Call;
7462 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7463 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7464
7465 {
7466 // Try to build a (member) call expression for the current best applicable
7467 // variant expression. We allow this to fail in which case we continue
7468 // with the next best variant expression. The fail case is part of the
7469 // implementation defined behavior in the OpenMP standard when it talks
7470 // about what differences in the function prototypes: "Any differences
7471 // that the specific OpenMP context requires in the prototype of the
7472 // variant from the base function prototype are implementation defined."
7473 // This wording is there to allow the specialized variant to have a
7474 // different type than the base function. This is intended and OK but if
7475 // we cannot create a call the difference is not in the "implementation
7476 // defined range" we allow.
7477 Sema::TentativeAnalysisScope Trap(*this);
7478
7479 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7480 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7481 BestExpr = MemberExpr::CreateImplicit(
7482 Context, MemberCall->getImplicitObjectArgument(),
7483 /* IsArrow */ false, SpecializedMethod, Context.BoundMemberTy,
7484 MemberCall->getValueKind(), MemberCall->getObjectKind());
7485 }
7486 NewCall = BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs, RParenLoc,
7487 ExecConfig);
7488 if (NewCall.isUsable()) {
7489 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7490 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7492 CalleeFnType, NewCalleeFnDecl->getType(),
7493 /* OfBlockPointer */ false,
7494 /* Unqualified */ false, /* AllowCXX */ true);
7495 if (!NewType.isNull())
7496 break;
7497 // Don't use the call if the function type was not compatible.
7498 NewCall = nullptr;
7499 }
7500 }
7501 }
7502
7503 VMIs.erase(VMIs.begin() + BestIdx);
7504 Exprs.erase(Exprs.begin() + BestIdx);
7505 } while (!VMIs.empty());
7506
7507 if (!NewCall.isUsable())
7508 return Call;
7509 return PseudoObjectExpr::Create(Context, CE, {NewCall.get()}, 0);
7510}
7511
7512std::optional<std::pair<FunctionDecl *, Expr *>>
7514 Expr *VariantRef, OMPTraitInfo &TI,
7515 unsigned NumAppendArgs,
7516 SourceRange SR) {
7517 if (!DG || DG.get().isNull())
7518 return std::nullopt;
7519
7520 const int VariantId = 1;
7521 // Must be applied only to single decl.
7522 if (!DG.get().isSingleDecl()) {
7523 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7524 << VariantId << SR;
7525 return std::nullopt;
7526 }
7527 Decl *ADecl = DG.get().getSingleDecl();
7528 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7529 ADecl = FTD->getTemplatedDecl();
7530
7531 // Decl must be a function.
7532 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7533 if (!FD) {
7534 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7535 << VariantId << SR;
7536 return std::nullopt;
7537 }
7538
7539 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7540 // The 'target' attribute needs to be separately checked because it does
7541 // not always signify a multiversion function declaration.
7542 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7543 };
7544 // OpenMP is not compatible with multiversion function attributes.
7545 if (HasMultiVersionAttributes(FD)) {
7546 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7547 << SR;
7548 return std::nullopt;
7549 }
7550
7551 // Allow #pragma omp declare variant only if the function is not used.
7552 if (FD->isUsed(false))
7553 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7554 << FD->getLocation();
7555
7556 // Check if the function was emitted already.
7557 const FunctionDecl *Definition;
7558 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7559 (LangOpts.EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7560 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7561 << FD->getLocation();
7562
7563 // The VariantRef must point to function.
7564 if (!VariantRef) {
7565 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7566 return std::nullopt;
7567 }
7568
7569 auto ShouldDelayChecks = [](Expr *&E, bool) {
7570 return E && (E->isTypeDependent() || E->isValueDependent() ||
7573 };
7574 // Do not check templates, wait until instantiation.
7575 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7576 TI.anyScoreOrCondition(ShouldDelayChecks))
7577 return std::make_pair(FD, VariantRef);
7578
7579 // Deal with non-constant score and user condition expressions.
7580 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7581 bool IsScore) -> bool {
7582 if (!E || E->isIntegerConstantExpr(Context))
7583 return false;
7584
7585 if (IsScore) {
7586 // We warn on non-constant scores and pretend they were not present.
7587 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7588 << E;
7589 E = nullptr;
7590 } else {
7591 // We could replace a non-constant user condition with "false" but we
7592 // will soon need to handle these anyway for the dynamic version of
7593 // OpenMP context selectors.
7594 Diag(E->getExprLoc(),
7595 diag::err_omp_declare_variant_user_condition_not_constant)
7596 << E;
7597 }
7598 return true;
7599 };
7600 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7601 return std::nullopt;
7602
7603 QualType AdjustedFnType = FD->getType();
7604 if (NumAppendArgs) {
7605 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7606 if (!PTy) {
7607 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7608 << SR;
7609 return std::nullopt;
7610 }
7611 // Adjust the function type to account for an extra omp_interop_t for each
7612 // specified in the append_args clause.
7613 const TypeDecl *TD = nullptr;
7614 LookupResult Result(*this, &Context.Idents.get("omp_interop_t"),
7616 if (LookupName(Result, getCurScope())) {
7617 NamedDecl *ND = Result.getFoundDecl();
7618 TD = dyn_cast_or_null<TypeDecl>(ND);
7619 }
7620 if (!TD) {
7621 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7622 return std::nullopt;
7623 }
7624 QualType InteropType = Context.getTypeDeclType(TD);
7625 if (PTy->isVariadic()) {
7626 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7627 return std::nullopt;
7628 }
7630 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7631 Params.insert(Params.end(), NumAppendArgs, InteropType);
7632 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7633 PTy->getExtProtoInfo());
7634 }
7635
7636 // Convert VariantRef expression to the type of the original function to
7637 // resolve possible conflicts.
7638 ExprResult VariantRefCast = VariantRef;
7639 if (LangOpts.CPlusPlus) {
7640 QualType FnPtrType;
7641 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7642 if (Method && !Method->isStatic()) {
7643 const Type *ClassType =
7644 Context.getTypeDeclType(Method->getParent()).getTypePtr();
7645 FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType);
7646 ExprResult ER;
7647 {
7648 // Build adrr_of unary op to correctly handle type checks for member
7649 // functions.
7650 Sema::TentativeAnalysisScope Trap(*this);
7651 ER = CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7652 VariantRef);
7653 }
7654 if (!ER.isUsable()) {
7655 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7656 << VariantId << VariantRef->getSourceRange();
7657 return std::nullopt;
7658 }
7659 VariantRef = ER.get();
7660 } else {
7661 FnPtrType = Context.getPointerType(AdjustedFnType);
7662 }
7663 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7664 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7666 VariantRef, FnPtrType.getUnqualifiedType(),
7667 /*SuppressUserConversions=*/false, AllowedExplicit::None,
7668 /*InOverloadResolution=*/false,
7669 /*CStyle=*/false,
7670 /*AllowObjCWritebackConversion=*/false);
7671 if (ICS.isFailure()) {
7672 Diag(VariantRef->getExprLoc(),
7673 diag::err_omp_declare_variant_incompat_types)
7674 << VariantRef->getType()
7675 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7676 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7677 return std::nullopt;
7678 }
7679 VariantRefCast = PerformImplicitConversion(
7680 VariantRef, FnPtrType.getUnqualifiedType(), AA_Converting);
7681 if (!VariantRefCast.isUsable())
7682 return std::nullopt;
7683 }
7684 // Drop previously built artificial addr_of unary op for member functions.
7685 if (Method && !Method->isStatic()) {
7686 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7687 if (auto *UO = dyn_cast<UnaryOperator>(
7688 PossibleAddrOfVariantRef->IgnoreImplicit()))
7689 VariantRefCast = UO->getSubExpr();
7690 }
7691 }
7692
7693 ExprResult ER = CheckPlaceholderExpr(VariantRefCast.get());
7694 if (!ER.isUsable() ||
7696 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7697 << VariantId << VariantRef->getSourceRange();
7698 return std::nullopt;
7699 }
7700
7701 // The VariantRef must point to function.
7702 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7703 if (!DRE) {
7704 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7705 << VariantId << VariantRef->getSourceRange();
7706 return std::nullopt;
7707 }
7708 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7709 if (!NewFD) {
7710 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7711 << VariantId << VariantRef->getSourceRange();
7712 return std::nullopt;
7713 }
7714
7715 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7716 Diag(VariantRef->getExprLoc(),
7717 diag::err_omp_declare_variant_same_base_function)
7718 << VariantRef->getSourceRange();
7719 return std::nullopt;
7720 }
7721
7722 // Check if function types are compatible in C.
7723 if (!LangOpts.CPlusPlus) {
7724 QualType NewType =
7725 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7726 if (NewType.isNull()) {
7727 Diag(VariantRef->getExprLoc(),
7728 diag::err_omp_declare_variant_incompat_types)
7729 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7730 << VariantRef->getSourceRange();
7731 return std::nullopt;
7732 }
7733 if (NewType->isFunctionProtoType()) {
7734 if (FD->getType()->isFunctionNoProtoType())
7735 setPrototype(*this, FD, NewFD, NewType);
7736 else if (NewFD->getType()->isFunctionNoProtoType())
7737 setPrototype(*this, NewFD, FD, NewType);
7738 }
7739 }
7740
7741 // Check if variant function is not marked with declare variant directive.
7742 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7743 Diag(VariantRef->getExprLoc(),
7744 diag::warn_omp_declare_variant_marked_as_declare_variant)
7745 << VariantRef->getSourceRange();
7746 SourceRange SR =
7747 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7748 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7749 return std::nullopt;
7750 }
7751
7752 enum DoesntSupport {
7753 VirtFuncs = 1,
7754 Constructors = 3,
7755 Destructors = 4,
7756 DeletedFuncs = 5,
7757 DefaultedFuncs = 6,
7758 ConstexprFuncs = 7,
7759 ConstevalFuncs = 8,
7760 };
7761 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7762 if (CXXFD->isVirtual()) {
7763 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7764 << VirtFuncs;
7765 return std::nullopt;
7766 }
7767
7768 if (isa<CXXConstructorDecl>(FD)) {
7769 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7770 << Constructors;
7771 return std::nullopt;
7772 }
7773
7774 if (isa<CXXDestructorDecl>(FD)) {
7775 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7776 << Destructors;
7777 return std::nullopt;
7778 }
7779 }
7780
7781 if (FD->isDeleted()) {
7782 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7783 << DeletedFuncs;
7784 return std::nullopt;
7785 }
7786
7787 if (FD->isDefaulted()) {
7788 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7789 << DefaultedFuncs;
7790 return std::nullopt;
7791 }
7792
7793 if (FD->isConstexpr()) {
7794 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7795 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7796 return std::nullopt;
7797 }
7798
7799 // Check general compatibility.
7805 VariantRef->getExprLoc(),
7806 PDiag(diag::err_omp_declare_variant_doesnt_support)),
7807 PartialDiagnosticAt(VariantRef->getExprLoc(),
7808 PDiag(diag::err_omp_declare_variant_diff)
7809 << FD->getLocation()),
7810 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7811 /*CLinkageMayDiffer=*/true))
7812 return std::nullopt;
7813 return std::make_pair(FD, cast<Expr>(DRE));
7814}
7815
7817 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7818 ArrayRef<Expr *> AdjustArgsNothing,
7819 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7820 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7821 SourceLocation AppendArgsLoc, SourceRange SR) {
7822
7823 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7824 // An adjust_args clause or append_args clause can only be specified if the
7825 // dispatch selector of the construct selector set appears in the match
7826 // clause.
7827
7828 SmallVector<Expr *, 8> AllAdjustArgs;
7829 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7830 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7831
7832 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7833 VariantMatchInfo VMI;
7835 if (!llvm::is_contained(
7836 VMI.ConstructTraits,
7837 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7838 if (!AllAdjustArgs.empty())
7839 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7840 << getOpenMPClauseName(OMPC_adjust_args);
7841 if (!AppendArgs.empty())
7842 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7843 << getOpenMPClauseName(OMPC_append_args);
7844 return;
7845 }
7846 }
7847
7848 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7849 // Each argument can only appear in a single adjust_args clause for each
7850 // declare variant directive.
7852
7853 for (Expr *E : AllAdjustArgs) {
7854 E = E->IgnoreParenImpCasts();
7855 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7856 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7857 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7858 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7859 FD->getParamDecl(PVD->getFunctionScopeIndex())
7860 ->getCanonicalDecl() == CanonPVD) {
7861 // It's a parameter of the function, check duplicates.
7862 if (!AdjustVars.insert(CanonPVD).second) {
7863 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7864 << PVD;
7865 return;
7866 }
7867 continue;
7868 }
7869 }
7870 }
7871 // Anything that is not a function parameter is an error.
7872 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7873 return;
7874 }
7875
7876 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7877 Context, VariantRef, &TI, const_cast<Expr **>(AdjustArgsNothing.data()),
7878 AdjustArgsNothing.size(),
7879 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7880 AdjustArgsNeedDevicePtr.size(),
7881 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7882 FD->addAttr(NewAttr);
7883}
7884
7886 Stmt *AStmt,
7887 SourceLocation StartLoc,
7888 SourceLocation EndLoc) {
7889 if (!AStmt)
7890 return StmtError();
7891
7892 auto *CS = cast<CapturedStmt>(AStmt);
7893 // 1.2.2 OpenMP Language Terminology
7894 // Structured block - An executable statement with a single entry at the
7895 // top and a single exit at the bottom.
7896 // The point of exit cannot be a branch out of the structured block.
7897 // longjmp() and throw() must not violate the entry/exit criteria.
7898 CS->getCapturedDecl()->setNothrow();
7899
7901
7902 return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
7903 DSAStack->getTaskgroupReductionRef(),
7904 DSAStack->isCancelRegion());
7905}
7906
7907namespace {
7908/// Iteration space of a single for loop.
7909struct LoopIterationSpace final {
7910 /// True if the condition operator is the strict compare operator (<, > or
7911 /// !=).
7912 bool IsStrictCompare = false;
7913 /// Condition of the loop.
7914 Expr *PreCond = nullptr;
7915 /// This expression calculates the number of iterations in the loop.
7916 /// It is always possible to calculate it before starting the loop.
7917 Expr *NumIterations = nullptr;
7918 /// The loop counter variable.
7919 Expr *CounterVar = nullptr;
7920 /// Private loop counter variable.
7921 Expr *PrivateCounterVar = nullptr;
7922 /// This is initializer for the initial value of #CounterVar.
7923 Expr *CounterInit = nullptr;
7924 /// This is step for the #CounterVar used to generate its update:
7925 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7926 Expr *CounterStep = nullptr;
7927 /// Should step be subtracted?
7928 bool Subtract = false;
7929 /// Source range of the loop init.
7930 SourceRange InitSrcRange;
7931 /// Source range of the loop condition.
7932 SourceRange CondSrcRange;
7933 /// Source range of the loop increment.
7934 SourceRange IncSrcRange;
7935 /// Minimum value that can have the loop control variable. Used to support
7936 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7937 /// since only such variables can be used in non-loop invariant expressions.
7938 Expr *MinValue = nullptr;
7939 /// Maximum value that can have the loop control variable. Used to support
7940 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7941 /// since only such variables can be used in non-loop invariant expressions.
7942 Expr *MaxValue = nullptr;
7943 /// true, if the lower bound depends on the outer loop control var.
7944 bool IsNonRectangularLB = false;
7945 /// true, if the upper bound depends on the outer loop control var.
7946 bool IsNonRectangularUB = false;
7947 /// Index of the loop this loop depends on and forms non-rectangular loop
7948 /// nest.
7949 unsigned LoopDependentIdx = 0;
7950 /// Final condition for the non-rectangular loop nest support. It is used to
7951 /// check that the number of iterations for this particular counter must be
7952 /// finished.
7953 Expr *FinalCondition = nullptr;
7954};
7955
7956/// Helper class for checking canonical form of the OpenMP loops and
7957/// extracting iteration space of each loop in the loop nest, that will be used
7958/// for IR generation.
7959class OpenMPIterationSpaceChecker {
7960 /// Reference to Sema.
7961 Sema &SemaRef;
7962 /// Does the loop associated directive support non-rectangular loops?
7963 bool SupportsNonRectangular;
7964 /// Data-sharing stack.
7965 DSAStackTy &Stack;
7966 /// A location for diagnostics (when there is no some better location).
7967 SourceLocation DefaultLoc;
7968 /// A location for diagnostics (when increment is not compatible).
7969 SourceLocation ConditionLoc;
7970 /// A source location for referring to loop init later.
7971 SourceRange InitSrcRange;
7972 /// A source location for referring to condition later.
7973 SourceRange ConditionSrcRange;
7974 /// A source location for referring to increment later.
7975 SourceRange IncrementSrcRange;
7976 /// Loop variable.
7977 ValueDecl *LCDecl = nullptr;
7978 /// Reference to loop variable.
7979 Expr *LCRef = nullptr;
7980 /// Lower bound (initializer for the var).
7981 Expr *LB = nullptr;
7982 /// Upper bound.
7983 Expr *UB = nullptr;
7984 /// Loop step (increment).
7985 Expr *Step = nullptr;
7986 /// This flag is true when condition is one of:
7987 /// Var < UB
7988 /// Var <= UB
7989 /// UB > Var
7990 /// UB >= Var
7991 /// This will have no value when the condition is !=
7992 std::optional<bool> TestIsLessOp;
7993 /// This flag is true when condition is strict ( < or > ).
7994 bool TestIsStrictOp = false;
7995 /// This flag is true when step is subtracted on each iteration.
7996 bool SubtractStep = false;
7997 /// The outer loop counter this loop depends on (if any).
7998 const ValueDecl *DepDecl = nullptr;
7999 /// Contains number of loop (starts from 1) on which loop counter init
8000 /// expression of this loop depends on.
8001 std::optional<unsigned> InitDependOnLC;
8002 /// Contains number of loop (starts from 1) on which loop counter condition
8003 /// expression of this loop depends on.
8004 std::optional<unsigned> CondDependOnLC;
8005 /// Checks if the provide statement depends on the loop counter.
8006 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
8007 bool IsInitializer);
8008 /// Original condition required for checking of the exit condition for
8009 /// non-rectangular loop.
8010 Expr *Condition = nullptr;
8011
8012public:
8013 OpenMPIterationSpaceChecker(Sema &SemaRef, bool SupportsNonRectangular,
8014 DSAStackTy &Stack, SourceLocation DefaultLoc)
8015 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8016 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {}
8017 /// Check init-expr for canonical loop form and save loop counter
8018 /// variable - #Var and its initialization value - #LB.
8019 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
8020 /// Check test-expr for canonical form, save upper-bound (#UB), flags
8021 /// for less/greater and for strict/non-strict comparison.
8022 bool checkAndSetCond(Expr *S);
8023 /// Check incr-expr for canonical loop form and return true if it
8024 /// does not conform, otherwise save loop step (#Step).
8025 bool checkAndSetInc(Expr *S);
8026 /// Return the loop counter variable.
8027 ValueDecl *getLoopDecl() const { return LCDecl; }
8028 /// Return the reference expression to loop counter variable.
8029 Expr *getLoopDeclRefExpr() const { return LCRef; }
8030 /// Source range of the loop init.
8031 SourceRange getInitSrcRange() const { return InitSrcRange; }
8032 /// Source range of the loop condition.
8033 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
8034 /// Source range of the loop increment.
8035 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
8036 /// True if the step should be subtracted.
8037 bool shouldSubtractStep() const { return SubtractStep; }
8038 /// True, if the compare operator is strict (<, > or !=).
8039 bool isStrictTestOp() const { return TestIsStrictOp; }
8040 /// Build the expression to calculate the number of iterations.
8041 Expr *buildNumIterations(
8042 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8043 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8044 /// Build the precondition expression for the loops.
8045 Expr *
8046 buildPreCond(Scope *S, Expr *Cond,
8047 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8048 /// Build reference expression to the counter be used for codegen.
8049 DeclRefExpr *
8050 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8051 DSAStackTy &DSA) const;
8052 /// Build reference expression to the private counter be used for
8053 /// codegen.
8054 Expr *buildPrivateCounterVar() const;
8055 /// Build initialization of the counter be used for codegen.
8056 Expr *buildCounterInit() const;
8057 /// Build step of the counter be used for codegen.
8058 Expr *buildCounterStep() const;
8059 /// Build loop data with counter value for depend clauses in ordered
8060 /// directives.
8061 Expr *
8062 buildOrderedLoopData(Scope *S, Expr *Counter,
8063 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8064 SourceLocation Loc, Expr *Inc = nullptr,
8065 OverloadedOperatorKind OOK = OO_Amp);
8066 /// Builds the minimum value for the loop counter.
8067 std::pair<Expr *, Expr *> buildMinMaxValues(
8068 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8069 /// Builds final condition for the non-rectangular loops.
8070 Expr *buildFinalCondition(Scope *S) const;
8071 /// Return true if any expression is dependent.
8072 bool dependent() const;
8073 /// Returns true if the initializer forms non-rectangular loop.
8074 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
8075 /// Returns true if the condition forms non-rectangular loop.
8076 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
8077 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
8078 unsigned getLoopDependentIdx() const {
8079 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
8080 }
8081
8082private:
8083 /// Check the right-hand side of an assignment in the increment
8084 /// expression.
8085 bool checkAndSetIncRHS(Expr *RHS);
8086 /// Helper to set loop counter variable and its initializer.
8087 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8088 bool EmitDiags);
8089 /// Helper to set upper bound.
8090 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
8092 /// Helper to set loop increment.
8093 bool setStep(Expr *NewStep, bool Subtract);
8094};
8095
8096bool OpenMPIterationSpaceChecker::dependent() const {
8097 if (!LCDecl) {
8098 assert(!LB && !UB && !Step);
8099 return false;
8100 }
8101 return LCDecl->getType()->isDependentType() ||
8102 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
8103 (Step && Step->isValueDependent());
8104}
8105
8106bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
8107 Expr *NewLCRefExpr,
8108 Expr *NewLB, bool EmitDiags) {
8109 // State consistency checking to ensure correct usage.
8110 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
8111 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8112 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
8113 return true;
8114 LCDecl = getCanonicalDecl(NewLCDecl);
8115 LCRef = NewLCRefExpr;
8116 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
8117 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8118 if ((Ctor->isCopyOrMoveConstructor() ||
8119 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8120 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8121 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
8122 LB = NewLB;
8123 if (EmitDiags)
8124 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
8125 return false;
8126}
8127
8128bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
8129 bool StrictOp, SourceRange SR,
8130 SourceLocation SL) {
8131 // State consistency checking to ensure correct usage.
8132 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
8133 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8134 if (!NewUB || NewUB->containsErrors())
8135 return true;
8136 UB = NewUB;
8137 if (LessOp)
8138 TestIsLessOp = LessOp;
8139 TestIsStrictOp = StrictOp;
8140 ConditionSrcRange = SR;
8141 ConditionLoc = SL;
8142 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
8143 return false;
8144}
8145
8146bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
8147 // State consistency checking to ensure correct usage.
8148 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
8149 if (!NewStep || NewStep->containsErrors())
8150 return true;
8151 if (!NewStep->isValueDependent()) {
8152 // Check that the step is integer expression.
8153 SourceLocation StepLoc = NewStep->getBeginLoc();
8155 StepLoc, getExprAsWritten(NewStep));
8156 if (Val.isInvalid())
8157 return true;
8158 NewStep = Val.get();
8159
8160 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8161 // If test-expr is of form var relational-op b and relational-op is < or
8162 // <= then incr-expr must cause var to increase on each iteration of the
8163 // loop. If test-expr is of form var relational-op b and relational-op is
8164 // > or >= then incr-expr must cause var to decrease on each iteration of
8165 // the loop.
8166 // If test-expr is of form b relational-op var and relational-op is < or
8167 // <= then incr-expr must cause var to decrease on each iteration of the
8168 // loop. If test-expr is of form b relational-op var and relational-op is
8169 // > or >= then incr-expr must cause var to increase on each iteration of
8170 // the loop.
8171 std::optional<llvm::APSInt> Result =
8172 NewStep->getIntegerConstantExpr(SemaRef.Context);
8173 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
8174 bool IsConstNeg =
8175 Result && Result->isSigned() && (Subtract != Result->isNegative());
8176 bool IsConstPos =
8177 Result && Result->isSigned() && (Subtract == Result->isNegative());
8178 bool IsConstZero = Result && !Result->getBoolValue();
8179
8180 // != with increment is treated as <; != with decrement is treated as >
8181 if (!TestIsLessOp)
8182 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8183 if (UB && (IsConstZero ||
8184 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8185 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8186 SemaRef.Diag(NewStep->getExprLoc(),
8187 diag::err_omp_loop_incr_not_compatible)
8188 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
8189 SemaRef.Diag(ConditionLoc,
8190 diag::note_omp_loop_cond_requres_compatible_incr)
8191 << *TestIsLessOp << ConditionSrcRange;
8192 return true;
8193 }
8194 if (*TestIsLessOp == Subtract) {
8195 NewStep =
8196 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
8197 .get();
8198 Subtract = !Subtract;
8199 }
8200 }
8201
8202 Step = NewStep;
8203 SubtractStep = Subtract;
8204 return false;
8205}
8206
8207namespace {
8208/// Checker for the non-rectangular loops. Checks if the initializer or
8209/// condition expression references loop counter variable.
8210class LoopCounterRefChecker final
8211 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8212 Sema &SemaRef;
8213 DSAStackTy &Stack;
8214 const ValueDecl *CurLCDecl = nullptr;
8215 const ValueDecl *DepDecl = nullptr;
8216 const ValueDecl *PrevDepDecl = nullptr;
8217 bool IsInitializer = true;
8218 bool SupportsNonRectangular;
8219 unsigned BaseLoopId = 0;
8220 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8221 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
8222 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8223 << (IsInitializer ? 0 : 1);
8224 return false;
8225 }
8226 const auto &&Data = Stack.isLoopControlVariable(VD);
8227 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8228 // The type of the loop iterator on which we depend may not have a random
8229 // access iterator type.
8230 if (Data.first && VD->getType()->isRecordType()) {
8231 SmallString<128> Name;
8232 llvm::raw_svector_ostream OS(Name);
8233 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8234 /*Qualified=*/true);
8235 SemaRef.Diag(E->getExprLoc(),
8236 diag::err_omp_wrong_dependency_iterator_type)
8237 << OS.str();
8238 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8239 return false;
8240 }
8241 if (Data.first && !SupportsNonRectangular) {
8242 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8243 return false;
8244 }
8245 if (Data.first &&
8246 (DepDecl || (PrevDepDecl &&
8247 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8248 if (!DepDecl && PrevDepDecl)
8249 DepDecl = PrevDepDecl;
8250 SmallString<128> Name;
8251 llvm::raw_svector_ostream OS(Name);
8252 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8253 /*Qualified=*/true);
8254 SemaRef.Diag(E->getExprLoc(),
8255 diag::err_omp_invariant_or_linear_dependency)
8256 << OS.str();
8257 return false;
8258 }
8259 if (Data.first) {
8260 DepDecl = VD;
8261 BaseLoopId = Data.first;
8262 }
8263 return Data.first;
8264 }
8265
8266public:
8267 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8268 const ValueDecl *VD = E->getDecl();
8269 if (isa<VarDecl>(VD))
8270 return checkDecl(E, VD);
8271 return false;
8272 }
8273 bool VisitMemberExpr(const MemberExpr *E) {
8274 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8275 const ValueDecl *VD = E->getMemberDecl();
8276 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8277 return checkDecl(E, VD);
8278 }
8279 return false;
8280 }
8281 bool VisitStmt(const Stmt *S) {
8282 bool Res = false;
8283 for (const Stmt *Child : S->children())
8284 Res = (Child && Visit(Child)) || Res;
8285 return Res;
8286 }
8287 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8288 const ValueDecl *CurLCDecl, bool IsInitializer,
8289 const ValueDecl *PrevDepDecl = nullptr,
8290 bool SupportsNonRectangular = true)
8291 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8292 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8293 SupportsNonRectangular(SupportsNonRectangular) {}
8294 unsigned getBaseLoopId() const {
8295 assert(CurLCDecl && "Expected loop dependency.");
8296 return BaseLoopId;
8297 }
8298 const ValueDecl *getDepDecl() const {
8299 assert(CurLCDecl && "Expected loop dependency.");
8300 return DepDecl;
8301 }
8302};
8303} // namespace
8304
8305std::optional<unsigned>
8306OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8307 bool IsInitializer) {
8308 // Check for the non-rectangular loops.
8309 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8310 DepDecl, SupportsNonRectangular);
8311 if (LoopStmtChecker.Visit(S)) {
8312 DepDecl = LoopStmtChecker.getDepDecl();
8313 return LoopStmtChecker.getBaseLoopId();
8314 }
8315 return std::nullopt;
8316}
8317
8318bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8319 // Check init-expr for canonical loop form and save loop counter
8320 // variable - #Var and its initialization value - #LB.
8321 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8322 // var = lb
8323 // integer-type var = lb
8324 // random-access-iterator-type var = lb
8325 // pointer-type var = lb
8326 //
8327 if (!S) {
8328 if (EmitDiags) {
8329 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8330 }
8331 return true;
8332 }
8333 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8334 if (!ExprTemp->cleanupsHaveSideEffects())
8335 S = ExprTemp->getSubExpr();
8336
8337 InitSrcRange = S->getSourceRange();
8338 if (Expr *E = dyn_cast<Expr>(S))
8339 S = E->IgnoreParens();
8340 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8341 if (BO->getOpcode() == BO_Assign) {
8342 Expr *LHS = BO->getLHS()->IgnoreParens();
8343 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8344 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8345 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8346 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8347 EmitDiags);
8348 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8349 }
8350 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8351 if (ME->isArrow() &&
8352 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8353 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8354 EmitDiags);
8355 }
8356 }
8357 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8358 if (DS->isSingleDecl()) {
8359 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8360 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8361 // Accept non-canonical init form here but emit ext. warning.
8362 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8363 SemaRef.Diag(S->getBeginLoc(),
8364 diag::ext_omp_loop_not_canonical_init)
8365 << S->getSourceRange();
8366 return setLCDeclAndLB(
8367 Var,
8368 buildDeclRefExpr(SemaRef, Var,
8369 Var->getType().getNonReferenceType(),
8370 DS->getBeginLoc()),
8371 Var->getInit(), EmitDiags);
8372 }
8373 }
8374 }
8375 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8376 if (CE->getOperator() == OO_Equal) {
8377 Expr *LHS = CE->getArg(0);
8378 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8379 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8380 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8381 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8382 EmitDiags);
8383 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8384 }
8385 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8386 if (ME->isArrow() &&
8387 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8388 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8389 EmitDiags);
8390 }
8391 }
8392 }
8393
8394 if (dependent() || SemaRef.CurContext->isDependentContext())
8395 return false;
8396 if (EmitDiags) {
8397 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8398 << S->getSourceRange();
8399 }
8400 return true;
8401}
8402
8403/// Ignore parenthesizes, implicit casts, copy constructor and return the
8404/// variable (which may be the loop variable) if possible.
8405static const ValueDecl *getInitLCDecl(const Expr *E) {
8406 if (!E)
8407 return nullptr;
8408 E = getExprAsWritten(E);
8409 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8410 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8411 if ((Ctor->isCopyOrMoveConstructor() ||
8412 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8413 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8414 E = CE->getArg(0)->IgnoreParenImpCasts();
8415 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8416 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8417 return getCanonicalDecl(VD);
8418 }
8419 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8420 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8421 return getCanonicalDecl(ME->getMemberDecl());
8422 return nullptr;
8423}
8424
8425bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8426 // Check test-expr for canonical form, save upper-bound UB, flags for
8427 // less/greater and for strict/non-strict comparison.
8428 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8429 // var relational-op b
8430 // b relational-op var
8431 //
8432 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8433 if (!S) {
8434 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8435 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8436 return true;
8437 }
8438 Condition = S;
8439 S = getExprAsWritten(S);
8440 SourceLocation CondLoc = S->getBeginLoc();
8441 auto &&CheckAndSetCond =
8442 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8443 const Expr *RHS, SourceRange SR,
8444 SourceLocation OpLoc) -> std::optional<bool> {
8445 if (BinaryOperator::isRelationalOp(Opcode)) {
8446 if (getInitLCDecl(LHS) == LCDecl)
8447 return setUB(const_cast<Expr *>(RHS),
8448 (Opcode == BO_LT || Opcode == BO_LE),
8449 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8450 if (getInitLCDecl(RHS) == LCDecl)
8451 return setUB(const_cast<Expr *>(LHS),
8452 (Opcode == BO_GT || Opcode == BO_GE),
8453 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8454 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8455 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8456 /*LessOp=*/std::nullopt,
8457 /*StrictOp=*/true, SR, OpLoc);
8458 }
8459 return std::nullopt;
8460 };
8461 std::optional<bool> Res;
8462 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8463 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8464 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8465 RBO->getOperatorLoc());
8466 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8467 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8468 BO->getSourceRange(), BO->getOperatorLoc());
8469 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8470 if (CE->getNumArgs() == 2) {
8471 Res = CheckAndSetCond(
8472 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8473 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8474 }
8475 }
8476 if (Res)
8477 return *Res;
8478 if (dependent() || SemaRef.CurContext->isDependentContext())
8479 return false;
8480 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8481 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8482 return true;
8483}
8484
8485bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8486 // RHS of canonical loop form increment can be:
8487 // var + incr
8488 // incr + var
8489 // var - incr
8490 //
8491 RHS = RHS->IgnoreParenImpCasts();
8492 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8493 if (BO->isAdditiveOp()) {
8494 bool IsAdd = BO->getOpcode() == BO_Add;
8495 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8496 return setStep(BO->getRHS(), !IsAdd);
8497 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8498 return setStep(BO->getLHS(), /*Subtract=*/false);
8499 }
8500 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8501 bool IsAdd = CE->getOperator() == OO_Plus;
8502 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8503 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8504 return setStep(CE->getArg(1), !IsAdd);
8505 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8506 return setStep(CE->getArg(0), /*Subtract=*/false);
8507 }
8508 }
8509 if (dependent() || SemaRef.CurContext->isDependentContext())
8510 return false;
8511 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8512 << RHS->getSourceRange() << LCDecl;
8513 return true;
8514}
8515
8516bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8517 // Check incr-expr for canonical loop form and return true if it
8518 // does not conform.
8519 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8520 // ++var
8521 // var++
8522 // --var
8523 // var--
8524 // var += incr
8525 // var -= incr
8526 // var = var + incr
8527 // var = incr + var
8528 // var = var - incr
8529 //
8530 if (!S) {
8531 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8532 return true;
8533 }
8534 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8535 if (!ExprTemp->cleanupsHaveSideEffects())
8536 S = ExprTemp->getSubExpr();
8537
8538 IncrementSrcRange = S->getSourceRange();
8539 S = S->IgnoreParens();
8540 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8541 if (UO->isIncrementDecrementOp() &&
8542 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8543 return setStep(SemaRef
8544 .ActOnIntegerConstant(UO->getBeginLoc(),
8545 (UO->isDecrementOp() ? -1 : 1))
8546 .get(),
8547 /*Subtract=*/false);
8548 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8549 switch (BO->getOpcode()) {
8550 case BO_AddAssign:
8551 case BO_SubAssign:
8552 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8553 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8554 break;
8555 case BO_Assign:
8556 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8557 return checkAndSetIncRHS(BO->getRHS());
8558 break;
8559 default:
8560 break;
8561 }
8562 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8563 switch (CE->getOperator()) {
8564 case OO_PlusPlus:
8565 case OO_MinusMinus:
8566 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8567 return setStep(SemaRef
8568 .ActOnIntegerConstant(
8569 CE->getBeginLoc(),
8570 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8571 .get(),
8572 /*Subtract=*/false);
8573 break;
8574 case OO_PlusEqual:
8575 case OO_MinusEqual:
8576 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8577 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8578 break;
8579 case OO_Equal:
8580 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8581 return checkAndSetIncRHS(CE->getArg(1));
8582 break;
8583 default:
8584 break;
8585 }
8586 }
8587 if (dependent() || SemaRef.CurContext->isDependentContext())
8588 return false;
8589 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8590 << S->getSourceRange() << LCDecl;
8591 return true;
8592}
8593
8594static ExprResult
8595tryBuildCapture(Sema &SemaRef, Expr *Capture,
8596 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8597 StringRef Name = ".capture_expr.") {
8598 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8599 return Capture;
8600 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8601 return SemaRef.PerformImplicitConversion(
8602 Capture->IgnoreImpCasts(), Capture->getType(), Sema::AA_Converting,
8603 /*AllowExplicit=*/true);
8604 auto I = Captures.find(Capture);
8605 if (I != Captures.end())
8606 return buildCapture(SemaRef, Capture, I->second, Name);
8607 DeclRefExpr *Ref = nullptr;
8608 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8609 Captures[Capture] = Ref;
8610 return Res;
8611}
8612
8613/// Calculate number of iterations, transforming to unsigned, if number of
8614/// iterations may be larger than the original type.
8615static Expr *
8616calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8617 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8618 bool TestIsStrictOp, bool RoundToStep,
8619 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8620 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8621 if (!NewStep.isUsable())
8622 return nullptr;
8623 llvm::APSInt LRes, SRes;
8624 bool IsLowerConst = false, IsStepConst = false;
8625 if (std::optional<llvm::APSInt> Res =
8626 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8627 LRes = *Res;
8628 IsLowerConst = true;
8629 }
8630 if (std::optional<llvm::APSInt> Res =
8631 Step->getIntegerConstantExpr(SemaRef.Context)) {
8632 SRes = *Res;
8633 IsStepConst = true;
8634 }
8635 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8636 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8637 (TestIsStrictOp && LRes.isStrictlyPositive()));
8638 bool NeedToReorganize = false;
8639 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8640 if (!NoNeedToConvert && IsLowerConst &&
8641 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8642 NoNeedToConvert = true;
8643 if (RoundToStep) {
8644 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8645 ? LRes.getBitWidth()
8646 : SRes.getBitWidth();
8647 LRes = LRes.extend(BW + 1);
8648 LRes.setIsSigned(true);
8649 SRes = SRes.extend(BW + 1);
8650 SRes.setIsSigned(true);
8651 LRes -= SRes;
8652 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8653 LRes = LRes.trunc(BW);
8654 }
8655 if (TestIsStrictOp) {
8656 unsigned BW = LRes.getBitWidth();
8657 LRes = LRes.extend(BW + 1);
8658 LRes.setIsSigned(true);
8659 ++LRes;
8660 NoNeedToConvert =
8661 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8662 // truncate to the original bitwidth.
8663 LRes = LRes.trunc(BW);
8664 }
8665 NeedToReorganize = NoNeedToConvert;
8666 }
8667 llvm::APSInt URes;
8668 bool IsUpperConst = false;
8669 if (std::optional<llvm::APSInt> Res =
8670 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8671 URes = *Res;
8672 IsUpperConst = true;
8673 }
8674 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8675 (!RoundToStep || IsStepConst)) {
8676 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8677 : URes.getBitWidth();
8678 LRes = LRes.extend(BW + 1);
8679 LRes.setIsSigned(true);
8680 URes = URes.extend(BW + 1);
8681 URes.setIsSigned(true);
8682 URes -= LRes;
8683 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8684 NeedToReorganize = NoNeedToConvert;
8685 }
8686 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8687 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8688 // unsigned.
8689 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8690 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8691 QualType LowerTy = Lower->getType();
8692 QualType UpperTy = Upper->getType();
8693 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8694 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8695 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8696 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8698 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8699 Upper =
8700 SemaRef
8702 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8704 .get();
8705 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8706 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8707 }
8708 }
8709 if (!Lower || !Upper || NewStep.isInvalid())
8710 return nullptr;
8711
8712 ExprResult Diff;
8713 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8714 // 1]).
8715 if (NeedToReorganize) {
8716 Diff = Lower;
8717
8718 if (RoundToStep) {
8719 // Lower - Step
8720 Diff =
8721 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8722 if (!Diff.isUsable())
8723 return nullptr;
8724 }
8725
8726 // Lower - Step [+ 1]
8727 if (TestIsStrictOp)
8728 Diff = SemaRef.BuildBinOp(
8729 S, DefaultLoc, BO_Add, Diff.get(),
8730 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8731 if (!Diff.isUsable())
8732 return nullptr;
8733
8734 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8735 if (!Diff.isUsable())
8736 return nullptr;
8737
8738 // Upper - (Lower - Step [+ 1]).
8739 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8740 if (!Diff.isUsable())
8741 return nullptr;
8742 } else {
8743 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8744
8745 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8746 // BuildBinOp already emitted error, this one is to point user to upper
8747 // and lower bound, and to tell what is passed to 'operator-'.
8748 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8749 << Upper->getSourceRange() << Lower->getSourceRange();
8750 return nullptr;
8751 }
8752
8753 if (!Diff.isUsable())
8754 return nullptr;
8755
8756 // Upper - Lower [- 1]
8757 if (TestIsStrictOp)
8758 Diff = SemaRef.BuildBinOp(
8759 S, DefaultLoc, BO_Sub, Diff.get(),
8760 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8761 if (!Diff.isUsable())
8762 return nullptr;
8763
8764 if (RoundToStep) {
8765 // Upper - Lower [- 1] + Step
8766 Diff =
8767 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8768 if (!Diff.isUsable())
8769 return nullptr;
8770 }
8771 }
8772
8773 // Parentheses (for dumping/debugging purposes only).
8774 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8775 if (!Diff.isUsable())
8776 return nullptr;
8777
8778 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8779 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8780 if (!Diff.isUsable())
8781 return nullptr;
8782
8783 return Diff.get();
8784}
8785
8786/// Build the expression to calculate the number of iterations.
8787Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8788 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8789 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8790 QualType VarType = LCDecl->getType().getNonReferenceType();
8791 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8792 !SemaRef.getLangOpts().CPlusPlus)
8793 return nullptr;
8794 Expr *LBVal = LB;
8795 Expr *UBVal = UB;
8796 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8797 // max(LB(MinVal), LB(MaxVal)))
8798 if (InitDependOnLC) {
8799 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8800 if (!IS.MinValue || !IS.MaxValue)
8801 return nullptr;
8802 // OuterVar = Min
8803 ExprResult MinValue =
8804 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8805 if (!MinValue.isUsable())
8806 return nullptr;
8807
8808 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8809 IS.CounterVar, MinValue.get());
8810 if (!LBMinVal.isUsable())
8811 return nullptr;
8812 // OuterVar = Min, LBVal
8813 LBMinVal =
8814 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8815 if (!LBMinVal.isUsable())
8816 return nullptr;
8817 // (OuterVar = Min, LBVal)
8818 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8819 if (!LBMinVal.isUsable())
8820 return nullptr;
8821
8822 // OuterVar = Max
8823 ExprResult MaxValue =
8824 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8825 if (!MaxValue.isUsable())
8826 return nullptr;
8827
8828 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8829 IS.CounterVar, MaxValue.get());
8830 if (!LBMaxVal.isUsable())
8831 return nullptr;
8832 // OuterVar = Max, LBVal
8833 LBMaxVal =
8834 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8835 if (!LBMaxVal.isUsable())
8836 return nullptr;
8837 // (OuterVar = Max, LBVal)
8838 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8839 if (!LBMaxVal.isUsable())
8840 return nullptr;
8841
8842 Expr *LBMin =
8843 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
8844 Expr *LBMax =
8845 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
8846 if (!LBMin || !LBMax)
8847 return nullptr;
8848 // LB(MinVal) < LB(MaxVal)
8849 ExprResult MinLessMaxRes =
8850 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8851 if (!MinLessMaxRes.isUsable())
8852 return nullptr;
8853 Expr *MinLessMax =
8854 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
8855 .get();
8856 if (!MinLessMax)
8857 return nullptr;
8858 if (*TestIsLessOp) {
8859 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8860 // LB(MaxVal))
8861 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8862 MinLessMax, LBMin, LBMax);
8863 if (!MinLB.isUsable())
8864 return nullptr;
8865 LBVal = MinLB.get();
8866 } else {
8867 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8868 // LB(MaxVal))
8869 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8870 MinLessMax, LBMax, LBMin);
8871 if (!MaxLB.isUsable())
8872 return nullptr;
8873 LBVal = MaxLB.get();
8874 }
8875 // OuterVar = LB
8876 LBMinVal =
8877 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8878 if (!LBMinVal.isUsable())
8879 return nullptr;
8880 LBVal = LBMinVal.get();
8881 }
8882 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8883 // min(UB(MinVal), UB(MaxVal))
8884 if (CondDependOnLC) {
8885 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8886 if (!IS.MinValue || !IS.MaxValue)
8887 return nullptr;
8888 // OuterVar = Min
8889 ExprResult MinValue =
8890 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8891 if (!MinValue.isUsable())
8892 return nullptr;
8893
8894 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8895 IS.CounterVar, MinValue.get());
8896 if (!UBMinVal.isUsable())
8897 return nullptr;
8898 // OuterVar = Min, UBVal
8899 UBMinVal =
8900 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
8901 if (!UBMinVal.isUsable())
8902 return nullptr;
8903 // (OuterVar = Min, UBVal)
8904 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
8905 if (!UBMinVal.isUsable())
8906 return nullptr;
8907
8908 // OuterVar = Max
8909 ExprResult MaxValue =
8910 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8911 if (!MaxValue.isUsable())
8912 return nullptr;
8913
8914 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8915 IS.CounterVar, MaxValue.get());
8916 if (!UBMaxVal.isUsable())
8917 return nullptr;
8918 // OuterVar = Max, UBVal
8919 UBMaxVal =
8920 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
8921 if (!UBMaxVal.isUsable())
8922 return nullptr;
8923 // (OuterVar = Max, UBVal)
8924 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
8925 if (!UBMaxVal.isUsable())
8926 return nullptr;
8927
8928 Expr *UBMin =
8929 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
8930 Expr *UBMax =
8931 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
8932 if (!UBMin || !UBMax)
8933 return nullptr;
8934 // UB(MinVal) > UB(MaxVal)
8935 ExprResult MinGreaterMaxRes =
8936 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8937 if (!MinGreaterMaxRes.isUsable())
8938 return nullptr;
8939 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
8940 Captures, ".min_greater_max")
8941 .get();
8942 if (!MinGreaterMax)
8943 return nullptr;
8944 if (*TestIsLessOp) {
8945 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8946 // UB(MaxVal))
8947 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
8948 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8949 if (!MaxUB.isUsable())
8950 return nullptr;
8951 UBVal = MaxUB.get();
8952 } else {
8953 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
8954 // UB(MaxVal))
8955 ExprResult MinUB = SemaRef.ActOnConditionalOp(
8956 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
8957 if (!MinUB.isUsable())
8958 return nullptr;
8959 UBVal = MinUB.get();
8960 }
8961 }
8962 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
8963 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
8964 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
8965 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
8966 if (!Upper || !Lower)
8967 return nullptr;
8968
8969 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8970 Step, VarType, TestIsStrictOp,
8971 /*RoundToStep=*/true, Captures);
8972 if (!Diff.isUsable())
8973 return nullptr;
8974
8975 // OpenMP runtime requires 32-bit or 64-bit loop variables.
8976 QualType Type = Diff.get()->getType();
8977 ASTContext &C = SemaRef.Context;
8978 bool UseVarType = VarType->hasIntegerRepresentation() &&
8979 C.getTypeSize(Type) > C.getTypeSize(VarType);
8980 if (!Type->isIntegerType() || UseVarType) {
8981 unsigned NewSize =
8982 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
8983 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
8985 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
8986 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
8987 Diff = SemaRef.PerformImplicitConversion(
8988 Diff.get(), Type, Sema::AA_Converting, /*AllowExplicit=*/true);
8989 if (!Diff.isUsable())
8990 return nullptr;
8991 }
8992 }
8993 if (LimitedType) {
8994 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
8995 if (NewSize != C.getTypeSize(Type)) {
8996 if (NewSize < C.getTypeSize(Type)) {
8997 assert(NewSize == 64 && "incorrect loop var size");
8998 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8999 << InitSrcRange << ConditionSrcRange;
9000 }
9001 QualType NewType = C.getIntTypeForBitwidth(
9003 C.getTypeSize(Type) < NewSize);
9004 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
9005 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
9006 Sema::AA_Converting, true);
9007 if (!Diff.isUsable())
9008 return nullptr;
9009 }
9010 }
9011 }
9012
9013 return Diff.get();
9014}
9015
9016std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9017 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9018 // Do not build for iterators, they cannot be used in non-rectangular loop
9019 // nests.
9020 if (LCDecl->getType()->isRecordType())
9021 return std::make_pair(nullptr, nullptr);
9022 // If we subtract, the min is in the condition, otherwise the min is in the
9023 // init value.
9024 Expr *MinExpr = nullptr;
9025 Expr *MaxExpr = nullptr;
9026 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9027 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9028 bool LBNonRect =
9029 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9030 bool UBNonRect =
9031 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9032 Expr *Lower =
9033 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
9034 Expr *Upper =
9035 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
9036 if (!Upper || !Lower)
9037 return std::make_pair(nullptr, nullptr);
9038
9039 if (*TestIsLessOp)
9040 MinExpr = Lower;
9041 else
9042 MaxExpr = Upper;
9043
9044 // Build minimum/maximum value based on number of iterations.
9045 QualType VarType = LCDecl->getType().getNonReferenceType();
9046
9047 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9048 Step, VarType, TestIsStrictOp,
9049 /*RoundToStep=*/false, Captures);
9050 if (!Diff.isUsable())
9051 return std::make_pair(nullptr, nullptr);
9052
9053 // ((Upper - Lower [- 1]) / Step) * Step
9054 // Parentheses (for dumping/debugging purposes only).
9055 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9056 if (!Diff.isUsable())
9057 return std::make_pair(nullptr, nullptr);
9058
9059 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
9060 if (!NewStep.isUsable())
9061 return std::make_pair(nullptr, nullptr);
9062 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
9063 if (!Diff.isUsable())
9064 return std::make_pair(nullptr, nullptr);
9065
9066 // Parentheses (for dumping/debugging purposes only).
9067 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9068 if (!Diff.isUsable())
9069 return std::make_pair(nullptr, nullptr);
9070
9071 // Convert to the ptrdiff_t, if original type is pointer.
9072 if (VarType->isAnyPointerType() &&
9073 !SemaRef.Context.hasSameType(
9074 Diff.get()->getType(),
9076 Diff = SemaRef.PerformImplicitConversion(
9077 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
9078 Sema::AA_Converting, /*AllowExplicit=*/true);
9079 }
9080 if (!Diff.isUsable())
9081 return std::make_pair(nullptr, nullptr);
9082
9083 if (*TestIsLessOp) {
9084 // MinExpr = Lower;
9085 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
9086 Diff = SemaRef.BuildBinOp(
9087 S, DefaultLoc, BO_Add,
9088 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
9089 Diff.get());
9090 if (!Diff.isUsable())
9091 return std::make_pair(nullptr, nullptr);
9092 } else {
9093 // MaxExpr = Upper;
9094 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
9095 Diff = SemaRef.BuildBinOp(
9096 S, DefaultLoc, BO_Sub,
9097 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
9098 Diff.get());
9099 if (!Diff.isUsable())
9100 return std::make_pair(nullptr, nullptr);
9101 }
9102
9103 // Convert to the original type.
9104 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
9105 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
9107 /*AllowExplicit=*/true);
9108 if (!Diff.isUsable())
9109 return std::make_pair(nullptr, nullptr);
9110
9111 Sema::TentativeAnalysisScope Trap(SemaRef);
9112 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
9113 if (!Diff.isUsable())
9114 return std::make_pair(nullptr, nullptr);
9115
9116 if (*TestIsLessOp)
9117 MaxExpr = Diff.get();
9118 else
9119 MinExpr = Diff.get();
9120
9121 return std::make_pair(MinExpr, MaxExpr);
9122}
9123
9124Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
9125 if (InitDependOnLC || CondDependOnLC)
9126 return Condition;
9127 return nullptr;
9128}
9129
9130Expr *OpenMPIterationSpaceChecker::buildPreCond(
9131 Scope *S, Expr *Cond,
9132 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9133 // Do not build a precondition when the condition/initialization is dependent
9134 // to prevent pessimistic early loop exit.
9135 // TODO: this can be improved by calculating min/max values but not sure that
9136 // it will be very effective.
9137 if (CondDependOnLC || InitDependOnLC)
9138 return SemaRef
9140 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
9141 SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
9142 /*AllowExplicit=*/true)
9143 .get();
9144
9145 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
9146 Sema::TentativeAnalysisScope Trap(SemaRef);
9147
9148 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9149 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9150 if (!NewLB.isUsable() || !NewUB.isUsable())
9151 return nullptr;
9152
9153 ExprResult CondExpr =
9154 SemaRef.BuildBinOp(S, DefaultLoc,
9155 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9156 : (TestIsStrictOp ? BO_GT : BO_GE),
9157 NewLB.get(), NewUB.get());
9158 if (CondExpr.isUsable()) {
9159 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
9160 SemaRef.Context.BoolTy))
9161 CondExpr = SemaRef.PerformImplicitConversion(
9162 CondExpr.get(), SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
9163 /*AllowExplicit=*/true);
9164 }
9165
9166 // Otherwise use original loop condition and evaluate it in runtime.
9167 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9168}
9169
9170/// Build reference expression to the counter be used for codegen.
9171DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9172 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9173 DSAStackTy &DSA) const {
9174 auto *VD = dyn_cast<VarDecl>(LCDecl);
9175 if (!VD) {
9176 VD = SemaRef.isOpenMPCapturedDecl(LCDecl);
9178 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
9179 const DSAStackTy::DSAVarData Data =
9180 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
9181 // If the loop control decl is explicitly marked as private, do not mark it
9182 // as captured again.
9183 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
9184 Captures.insert(std::make_pair(LCRef, Ref));
9185 return Ref;
9186 }
9187 return cast<DeclRefExpr>(LCRef);
9188}
9189
9190Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9191 if (LCDecl && !LCDecl->isInvalidDecl()) {
9193 VarDecl *PrivateVar = buildVarDecl(
9194 SemaRef, DefaultLoc, Type, LCDecl->getName(),
9195 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9196 isa<VarDecl>(LCDecl)
9197 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
9198 : nullptr);
9199 if (PrivateVar->isInvalidDecl())
9200 return nullptr;
9201 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
9202 }
9203 return nullptr;
9204}
9205
9206/// Build initialization of the counter to be used for codegen.
9207Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9208
9209/// Build step of the counter be used for codegen.
9210Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9211
9212Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9213 Scope *S, Expr *Counter,
9214 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9215 Expr *Inc, OverloadedOperatorKind OOK) {
9216 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
9217 if (!Cnt)
9218 return nullptr;
9219 if (Inc) {
9220 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9221 "Expected only + or - operations for depend clauses.");
9222 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9223 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
9224 if (!Cnt)
9225 return nullptr;
9226 }
9227 QualType VarType = LCDecl->getType().getNonReferenceType();
9228 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9229 !SemaRef.getLangOpts().CPlusPlus)
9230 return nullptr;
9231 // Upper - Lower
9232 Expr *Upper =
9233 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9234 Expr *Lower =
9235 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9236 if (!Upper || !Lower)
9237 return nullptr;
9238
9239 ExprResult Diff = calculateNumIters(
9240 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9241 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9242 if (!Diff.isUsable())
9243 return nullptr;
9244
9245 return Diff.get();
9246}
9247} // namespace
9248
9250 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9251 assert(Init && "Expected loop in canonical form.");
9252 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9253 if (AssociatedLoops > 0 &&
9254 isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
9255 DSAStack->loopStart();
9256 OpenMPIterationSpaceChecker ISC(*this, /*SupportsNonRectangular=*/true,
9257 *DSAStack, ForLoc);
9258 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9259 if (ValueDecl *D = ISC.getLoopDecl()) {
9260 auto *VD = dyn_cast<VarDecl>(D);
9261 DeclRefExpr *PrivateRef = nullptr;
9262 if (!VD) {
9264 VD = Private;
9265 } else {
9266 PrivateRef = buildCapture(*this, D, ISC.getLoopDeclRefExpr(),
9267 /*WithInit=*/false);
9268 VD = cast<VarDecl>(PrivateRef->getDecl());
9269 }
9270 }
9271 DSAStack->addLoopControlVariable(D, VD);
9272 const Decl *LD = DSAStack->getPossiblyLoopCunter();
9273 if (LD != D->getCanonicalDecl()) {
9274 DSAStack->resetPossibleLoopCounter();
9275 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9277 buildDeclRefExpr(*this, const_cast<VarDecl *>(Var),
9279 ForLoc, /*RefersToCapture=*/true));
9280 }
9281 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9282 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9283 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9284 // associated for-loop of a simd construct with just one associated
9285 // for-loop may be listed in a linear clause with a constant-linear-step
9286 // that is the increment of the associated for-loop. The loop iteration
9287 // variable(s) in the associated for-loop(s) of a for or parallel for
9288 // construct may be listed in a private or lastprivate clause.
9289 DSAStackTy::DSAVarData DVar =
9290 DSAStack->getTopDSA(D, /*FromParent=*/false);
9291 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9292 // is declared in the loop and it is predetermined as a private.
9293 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9294 OpenMPClauseKind PredeterminedCKind =
9296 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9297 : OMPC_private;
9298 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9299 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9300 (LangOpts.OpenMP <= 45 || (DVar.CKind != OMPC_lastprivate &&
9301 DVar.CKind != OMPC_private))) ||
9302 ((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop ||
9303 DKind == OMPD_master_taskloop || DKind == OMPD_masked_taskloop ||
9304 DKind == OMPD_parallel_master_taskloop ||
9305 DKind == OMPD_parallel_masked_taskloop ||
9307 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9308 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9309 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9310 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9311 << getOpenMPClauseName(DVar.CKind)
9312 << getOpenMPDirectiveName(DKind)
9313 << getOpenMPClauseName(PredeterminedCKind);
9314 if (DVar.RefExpr == nullptr)
9315 DVar.CKind = PredeterminedCKind;
9316 reportOriginalDsa(*this, DSAStack, D, DVar,
9317 /*IsLoopIterVar=*/true);
9318 } else if (LoopDeclRefExpr) {
9319 // Make the loop iteration variable private (for worksharing
9320 // constructs), linear (for simd directives with the only one
9321 // associated loop) or lastprivate (for simd directives with several
9322 // collapsed or ordered loops).
9323 if (DVar.CKind == OMPC_unknown)
9324 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind,
9325 PrivateRef);
9326 }
9327 }
9328 }
9329 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9330 }
9331}
9332
9333namespace {
9334// Utility for openmp doacross clause kind
9335class OMPDoacrossKind {
9336public:
9337 bool isSource(const OMPDoacrossClause *C) {
9338 return C->getDependenceType() == OMPC_DOACROSS_source ||
9339 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9340 }
9341 bool isSink(const OMPDoacrossClause *C) {
9342 return C->getDependenceType() == OMPC_DOACROSS_sink;
9343 }
9344 bool isSinkIter(const OMPDoacrossClause *C) {
9345 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9346 }
9347};
9348} // namespace
9349/// Called on a for stmt to check and extract its iteration space
9350/// for further processing (such as collapsing).
9352 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9353 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9354 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9355 Expr *OrderedLoopCountExpr,
9356 Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9358 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9359 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9360 // OpenMP [2.9.1, Canonical Loop Form]
9361 // for (init-expr; test-expr; incr-expr) structured-block
9362 // for (range-decl: range-expr) structured-block
9363 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9364 S = CanonLoop->getLoopStmt();
9365 auto *For = dyn_cast_or_null<ForStmt>(S);
9366 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9367 // Ranged for is supported only in OpenMP 5.0.
9368 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9369 OpenMPDirectiveKind DK = (SemaRef.getLangOpts().OpenMP < 50 ||
9370 DSA.getMappedDirective() == OMPD_unknown)
9371 ? DKind
9372 : DSA.getMappedDirective();
9373 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9374 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9375 << getOpenMPDirectiveName(DK) << TotalNestedLoopCount
9376 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9377 if (TotalNestedLoopCount > 1) {
9378 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9379 SemaRef.Diag(DSA.getConstructLoc(),
9380 diag::note_omp_collapse_ordered_expr)
9381 << 2 << CollapseLoopCountExpr->getSourceRange()
9382 << OrderedLoopCountExpr->getSourceRange();
9383 else if (CollapseLoopCountExpr)
9384 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9385 diag::note_omp_collapse_ordered_expr)
9386 << 0 << CollapseLoopCountExpr->getSourceRange();
9387 else
9388 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9389 diag::note_omp_collapse_ordered_expr)
9390 << 1 << OrderedLoopCountExpr->getSourceRange();
9391 }
9392 return true;
9393 }
9394 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9395 "No loop body.");
9396 // Postpone analysis in dependent contexts for ranged for loops.
9397 if (CXXFor && SemaRef.CurContext->isDependentContext())
9398 return false;
9399
9400 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9401 For ? For->getForLoc() : CXXFor->getForLoc());
9402
9403 // Check init.
9404 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9405 if (ISC.checkAndSetInit(Init))
9406 return true;
9407
9408 bool HasErrors = false;
9409
9410 // Check loop variable's type.
9411 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9412 // OpenMP [2.6, Canonical Loop Form]
9413 // Var is one of the following:
9414 // A variable of signed or unsigned integer type.
9415 // For C++, a variable of a random access iterator type.
9416 // For C, a variable of a pointer type.
9417 QualType VarType = LCDecl->getType().getNonReferenceType();
9418 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9419 !VarType->isPointerType() &&
9420 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9421 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9422 << SemaRef.getLangOpts().CPlusPlus;
9423 HasErrors = true;
9424 }
9425
9426 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9427 // a Construct
9428 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9429 // parallel for construct is (are) private.
9430 // The loop iteration variable in the associated for-loop of a simd
9431 // construct with just one associated for-loop is linear with a
9432 // constant-linear-step that is the increment of the associated for-loop.
9433 // Exclude loop var from the list of variables with implicitly defined data
9434 // sharing attributes.
9435 VarsWithImplicitDSA.erase(LCDecl);
9436
9437 assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
9438
9439 // Check test-expr.
9440 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9441
9442 // Check incr-expr.
9443 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9444 }
9445
9446 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9447 return HasErrors;
9448
9449 // Build the loop's iteration space representation.
9450 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9451 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9452 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9453 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9459 Captures);
9460 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9461 ISC.buildCounterVar(Captures, DSA);
9462 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9463 ISC.buildPrivateCounterVar();
9464 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9465 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9466 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9467 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9468 ISC.getConditionSrcRange();
9469 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9470 ISC.getIncrementSrcRange();
9471 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9472 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9473 ISC.isStrictTestOp();
9474 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9475 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9476 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9477 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9478 ISC.buildFinalCondition(DSA.getCurScope());
9479 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9480 ISC.doesInitDependOnLC();
9481 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9482 ISC.doesCondDependOnLC();
9483 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9484 ISC.getLoopDependentIdx();
9485
9486 HasErrors |=
9487 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9488 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9489 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9490 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9491 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9492 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9493 if (!HasErrors && DSA.isOrderedRegion()) {
9494 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9495 if (CurrentNestedLoopCount <
9496 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9497 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9498 CurrentNestedLoopCount,
9499 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9500 DSA.getOrderedRegionParam().second->setLoopCounter(
9501 CurrentNestedLoopCount,
9502 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9503 }
9504 }
9505 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9506 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9507 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9508 unsigned NumLoops =
9509 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9510 if (CurrentNestedLoopCount >= NumLoops) {
9511 // Erroneous case - clause has some problems.
9512 continue;
9513 }
9514 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9515 Pair.second.size() <= CurrentNestedLoopCount) {
9516 // Erroneous case - clause has some problems.
9517 DependC->setLoopData(CurrentNestedLoopCount, nullptr);
9518 continue;
9519 }
9520 OMPDoacrossKind ODK;
9521 if (DoacrossC && ODK.isSink(DoacrossC) &&
9522 Pair.second.size() <= CurrentNestedLoopCount) {
9523 // Erroneous case - clause has some problems.
9524 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
9525 continue;
9526 }
9527 Expr *CntValue;
9528 SourceLocation DepLoc =
9529 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9530 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9531 (DoacrossC && ODK.isSource(DoacrossC)))
9532 CntValue = ISC.buildOrderedLoopData(
9533 DSA.getCurScope(),
9534 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9535 DepLoc);
9536 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9537 Expr *Cnt = SemaRef
9539 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9540 .get();
9541 if (!Cnt)
9542 continue;
9543 // build CounterVar - 1
9544 Expr *Inc =
9545 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
9546 .get();
9547 CntValue = ISC.buildOrderedLoopData(
9548 DSA.getCurScope(),
9549 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9550 DepLoc, Inc, clang::OO_Minus);
9551 } else
9552 CntValue = ISC.buildOrderedLoopData(
9553 DSA.getCurScope(),
9554 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9555 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9556 Pair.second[CurrentNestedLoopCount].second);
9557 if (DependC)
9558 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9559 else
9560 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9561 }
9562 }
9563
9564 return HasErrors;
9565}
9566
9567/// Build 'VarRef = Start.
9568static ExprResult
9570 ExprResult Start, bool IsNonRectangularLB,
9571 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9572 // Build 'VarRef = Start.
9573 ExprResult NewStart = IsNonRectangularLB
9574 ? Start.get()
9575 : tryBuildCapture(SemaRef, Start.get(), Captures);
9576 if (!NewStart.isUsable())
9577 return ExprError();
9578 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9579 VarRef.get()->getType())) {
9580 NewStart = SemaRef.PerformImplicitConversion(
9581 NewStart.get(), VarRef.get()->getType(), Sema::AA_Converting,
9582 /*AllowExplicit=*/true);
9583 if (!NewStart.isUsable())
9584 return ExprError();
9585 }
9586
9588 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9589 return Init;
9590}
9591
9592/// Build 'VarRef = Start + Iter * Step'.
9594 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9595 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9596 bool IsNonRectangularLB,
9597 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9598 // Add parentheses (for debugging purposes only).
9599 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9600 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9601 !Step.isUsable())
9602 return ExprError();
9603
9604 ExprResult NewStep = Step;
9605 if (Captures)
9606 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9607 if (NewStep.isInvalid())
9608 return ExprError();
9610 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9611 if (!Update.isUsable())
9612 return ExprError();
9613
9614 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9615 // 'VarRef = Start (+|-) Iter * Step'.
9616 if (!Start.isUsable())
9617 return ExprError();
9618 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9619 if (!NewStart.isUsable())
9620 return ExprError();
9621 if (Captures && !IsNonRectangularLB)
9622 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9623 if (NewStart.isInvalid())
9624 return ExprError();
9625
9626 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9627 ExprResult SavedUpdate = Update;
9628 ExprResult UpdateVal;
9629 if (VarRef.get()->getType()->isOverloadableType() ||
9630 NewStart.get()->getType()->isOverloadableType() ||
9631 Update.get()->getType()->isOverloadableType()) {
9632 Sema::TentativeAnalysisScope Trap(SemaRef);
9633
9634 Update =
9635 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9636 if (Update.isUsable()) {
9637 UpdateVal =
9638 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9639 VarRef.get(), SavedUpdate.get());
9640 if (UpdateVal.isUsable()) {
9641 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9642 UpdateVal.get());
9643 }
9644 }
9645 }
9646
9647 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9648 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9649 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9650 NewStart.get(), SavedUpdate.get());
9651 if (!Update.isUsable())
9652 return ExprError();
9653
9654 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9655 VarRef.get()->getType())) {
9657 Update.get(), VarRef.get()->getType(), Sema::AA_Converting, true);
9658 if (!Update.isUsable())
9659 return ExprError();
9660 }
9661
9662 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9663 }
9664 return Update;
9665}
9666
9667/// Convert integer expression \a E to make it have at least \a Bits
9668/// bits.
9669static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9670 if (E == nullptr)
9671 return ExprError();
9672 ASTContext &C = SemaRef.Context;
9673 QualType OldType = E->getType();
9674 unsigned HasBits = C.getTypeSize(OldType);
9675 if (HasBits >= Bits)
9676 return ExprResult(E);
9677 // OK to convert to signed, because new type has more bits than old.
9678 QualType NewType = C.getIntTypeForBitwidth(Bits, /* Signed */ true);
9679 return SemaRef.PerformImplicitConversion(E, NewType, Sema::AA_Converting,
9680 true);
9681}
9682
9683/// Check if the given expression \a E is a constant integer that fits
9684/// into \a Bits bits.
9685static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9686 if (E == nullptr)
9687 return false;
9688 if (std::optional<llvm::APSInt> Result =
9689 E->getIntegerConstantExpr(SemaRef.Context))
9690 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9691 return false;
9692}
9693
9694/// Build preinits statement for the given declarations.
9696 MutableArrayRef<Decl *> PreInits) {
9697 if (!PreInits.empty()) {
9698 return new (Context) DeclStmt(
9699 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9701 }
9702 return nullptr;
9703}
9704
9705/// Build preinits statement for the given declarations.
9706static Stmt *
9708 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9709 if (!Captures.empty()) {
9710 SmallVector<Decl *, 16> PreInits;
9711 for (const auto &Pair : Captures)
9712 PreInits.push_back(Pair.second->getDecl());
9713 return buildPreInits(Context, PreInits);
9714 }
9715 return nullptr;
9716}
9717
9718/// Build postupdate expression for the given list of postupdates expressions.
9719static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9720 Expr *PostUpdate = nullptr;
9721 if (!PostUpdates.empty()) {
9722 for (Expr *E : PostUpdates) {
9723 Expr *ConvE = S.BuildCStyleCastExpr(
9724 E->getExprLoc(),
9726 E->getExprLoc(), E)
9727 .get();
9728 PostUpdate = PostUpdate
9729 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9730 PostUpdate, ConvE)
9731 .get()
9732 : ConvE;
9733 }
9734 }
9735 return PostUpdate;
9736}
9737
9738/// Called on a for stmt to check itself and nested loops (if any).
9739/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9740/// number of collapsed loops otherwise.
9741static unsigned
9742checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9743 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9744 DSAStackTy &DSA,
9745 Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9747 unsigned NestedLoopCount = 1;
9748 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9750
9751 if (CollapseLoopCountExpr) {
9752 // Found 'collapse' clause - calculate collapse number.
9754 if (!CollapseLoopCountExpr->isValueDependent() &&
9755 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9756 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9757 } else {
9758 Built.clear(/*Size=*/1);
9759 return 1;
9760 }
9761 }
9762 unsigned OrderedLoopCount = 1;
9763 if (OrderedLoopCountExpr) {
9764 // Found 'ordered' clause - calculate collapse number.
9765 Expr::EvalResult EVResult;
9766 if (!OrderedLoopCountExpr->isValueDependent() &&
9767 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9768 SemaRef.getASTContext())) {
9769 llvm::APSInt Result = EVResult.Val.getInt();
9770 if (Result.getLimitedValue() < NestedLoopCount) {
9771 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9772 diag::err_omp_wrong_ordered_loop_count)
9773 << OrderedLoopCountExpr->getSourceRange();
9774 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9775 diag::note_collapse_loop_count)
9776 << CollapseLoopCountExpr->getSourceRange();
9777 }
9778 OrderedLoopCount = Result.getLimitedValue();
9779 } else {
9780 Built.clear(/*Size=*/1);
9781 return 1;
9782 }
9783 }
9784 // This is helper routine for loop directives (e.g., 'for', 'simd',
9785 // 'for simd', etc.).
9786 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9787 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9788 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9791 SupportsNonPerfectlyNested, NumLoops,
9792 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9793 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9794 &IterSpaces, &Captures](unsigned Cnt, Stmt *CurStmt) {
9796 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9797 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9798 VarsWithImplicitDSA, IterSpaces, Captures))
9799 return true;
9800 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9801 IterSpaces[Cnt].CounterVar) {
9802 // Handle initialization of captured loop iterator variables.
9803 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9804 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9805 Captures[DRE] = DRE;
9806 }
9807 }
9808 return false;
9809 },
9810 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9811 Stmt *DependentPreInits = Transform->getPreInits();
9812 if (!DependentPreInits)
9813 return;
9814 for (Decl *C : cast<DeclStmt>(DependentPreInits)->getDeclGroup()) {
9815 auto *D = cast<VarDecl>(C);
9816 DeclRefExpr *Ref = buildDeclRefExpr(SemaRef, D, D->getType(),
9817 Transform->getBeginLoc());
9818 Captures[Ref] = Ref;
9819 }
9820 }))
9821 return 0;
9822
9823 Built.clear(/* size */ NestedLoopCount);
9824
9825 if (SemaRef.CurContext->isDependentContext())
9826 return NestedLoopCount;
9827
9828 // An example of what is generated for the following code:
9829 //
9830 // #pragma omp simd collapse(2) ordered(2)
9831 // for (i = 0; i < NI; ++i)
9832 // for (k = 0; k < NK; ++k)
9833 // for (j = J0; j < NJ; j+=2) {
9834 // <loop body>
9835 // }
9836 //
9837 // We generate the code below.
9838 // Note: the loop body may be outlined in CodeGen.
9839 // Note: some counters may be C++ classes, operator- is used to find number of
9840 // iterations and operator+= to calculate counter value.
9841 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9842 // or i64 is currently supported).
9843 //
9844 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9845 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9846 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9847 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9848 // // similar updates for vars in clauses (e.g. 'linear')
9849 // <loop body (using local i and j)>
9850 // }
9851 // i = NI; // assign final values of counters
9852 // j = NJ;
9853 //
9854
9855 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9856 // the iteration counts of the collapsed for loops.
9857 // Precondition tests if there is at least one iteration (all conditions are
9858 // true).
9859 auto PreCond = ExprResult(IterSpaces[0].PreCond);
9860 Expr *N0 = IterSpaces[0].NumIterations;
9861 ExprResult LastIteration32 =
9862 widenIterationCount(/*Bits=*/32,
9863 SemaRef
9864 .PerformImplicitConversion(
9865 N0->IgnoreImpCasts(), N0->getType(),
9866 Sema::AA_Converting, /*AllowExplicit=*/true)
9867 .get(),
9868 SemaRef);
9869 ExprResult LastIteration64 = widenIterationCount(
9870 /*Bits=*/64,
9871 SemaRef
9872 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
9874 /*AllowExplicit=*/true)
9875 .get(),
9876 SemaRef);
9877
9878 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
9879 return NestedLoopCount;
9880
9881 ASTContext &C = SemaRef.Context;
9882 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
9883
9884 Scope *CurScope = DSA.getCurScope();
9885 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9886 if (PreCond.isUsable()) {
9887 PreCond =
9888 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
9889 PreCond.get(), IterSpaces[Cnt].PreCond);
9890 }
9891 Expr *N = IterSpaces[Cnt].NumIterations;
9892 SourceLocation Loc = N->getExprLoc();
9893 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
9894 if (LastIteration32.isUsable())
9895 LastIteration32 = SemaRef.BuildBinOp(
9896 CurScope, Loc, BO_Mul, LastIteration32.get(),
9897 SemaRef
9900 /*AllowExplicit=*/true)
9901 .get());
9902 if (LastIteration64.isUsable())
9903 LastIteration64 = SemaRef.BuildBinOp(
9904 CurScope, Loc, BO_Mul, LastIteration64.get(),
9905 SemaRef
9908 /*AllowExplicit=*/true)
9909 .get());
9910 }
9911
9912 // Choose either the 32-bit or 64-bit version.
9913 ExprResult LastIteration = LastIteration64;
9914 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
9915 (LastIteration32.isUsable() &&
9916 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
9917 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9918 fitsInto(
9919 /*Bits=*/32,
9920 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
9921 LastIteration64.get(), SemaRef))))
9922 LastIteration = LastIteration32;
9923 QualType VType = LastIteration.get()->getType();
9924 QualType RealVType = VType;
9925 QualType StrideVType = VType;
9926 if (isOpenMPTaskLoopDirective(DKind)) {
9927 VType =
9928 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9929 StrideVType =
9930 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9931 }
9932
9933 if (!LastIteration.isUsable())
9934 return 0;
9935
9936 // Save the number of iterations.
9937 ExprResult NumIterations = LastIteration;
9938 {
9939 LastIteration = SemaRef.BuildBinOp(
9940 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
9941 LastIteration.get(),
9942 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9943 if (!LastIteration.isUsable())
9944 return 0;
9945 }
9946
9947 // Calculate the last iteration number beforehand instead of doing this on
9948 // each iteration. Do not do this if the number of iterations may be kfold-ed.
9949 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
9950 ExprResult CalcLastIteration;
9951 if (!IsConstant) {
9952 ExprResult SaveRef =
9953 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
9954 LastIteration = SaveRef;
9955
9956 // Prepare SaveRef + 1.
9957 NumIterations = SemaRef.BuildBinOp(
9958 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
9959 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9960 if (!NumIterations.isUsable())
9961 return 0;
9962 }
9963
9964 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
9965
9966 // Build variables passed into runtime, necessary for worksharing directives.
9967 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9972 // Lower bound variable, initialized with zero.
9973 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
9974 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
9975 SemaRef.AddInitializerToDecl(LBDecl,
9976 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9977 /*DirectInit*/ false);
9978
9979 // Upper bound variable, initialized with last iteration number.
9980 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
9981 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
9982 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
9983 /*DirectInit*/ false);
9984
9985 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
9986 // This will be used to implement clause 'lastprivate'.
9987 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
9988 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
9989 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
9990 SemaRef.AddInitializerToDecl(ILDecl,
9991 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9992 /*DirectInit*/ false);
9993
9994 // Stride variable returned by runtime (we initialize it to 1 by default).
9995 VarDecl *STDecl =
9996 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
9997 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
9998 SemaRef.AddInitializerToDecl(STDecl,
9999 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
10000 /*DirectInit*/ false);
10001
10002 // Build expression: UB = min(UB, LastIteration)
10003 // It is necessary for CodeGen of directives with static scheduling.
10004 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
10005 UB.get(), LastIteration.get());
10006 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10007 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
10008 LastIteration.get(), UB.get());
10009 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
10010 CondOp.get());
10011 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false);
10012
10013 // If we have a combined directive that combines 'distribute', 'for' or
10014 // 'simd' we need to be able to access the bounds of the schedule of the
10015 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
10016 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
10018 // Lower bound variable, initialized with zero.
10019 VarDecl *CombLBDecl =
10020 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
10021 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
10022 SemaRef.AddInitializerToDecl(
10023 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10024 /*DirectInit*/ false);
10025
10026 // Upper bound variable, initialized with last iteration number.
10027 VarDecl *CombUBDecl =
10028 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
10029 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
10030 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
10031 /*DirectInit*/ false);
10032
10033 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
10034 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
10035 ExprResult CombCondOp =
10036 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
10037 LastIteration.get(), CombUB.get());
10038 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
10039 CombCondOp.get());
10040 CombEUB =
10041 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false);
10042
10043 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
10044 // We expect to have at least 2 more parameters than the 'parallel'
10045 // directive does - the lower and upper bounds of the previous schedule.
10046 assert(CD->getNumParams() >= 4 &&
10047 "Unexpected number of parameters in loop combined directive");
10048
10049 // Set the proper type for the bounds given what we learned from the
10050 // enclosed loops.
10051 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
10052 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
10053
10054 // Previous lower and upper bounds are obtained from the region
10055 // parameters.
10056 PrevLB =
10057 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
10058 PrevUB =
10059 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
10060 }
10061 }
10062
10063 // Build the iteration variable and its initialization before loop.
10064 ExprResult IV;
10065 ExprResult Init, CombInit;
10066 {
10067 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
10068 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
10069 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
10074 ? LB.get()
10075 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10076 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
10077 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false);
10078
10080 Expr *CombRHS =
10085 ? CombLB.get()
10086 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10087 CombInit =
10088 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
10089 CombInit =
10090 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false);
10091 }
10092 }
10093
10094 bool UseStrictCompare =
10095 RealVType->hasUnsignedIntegerRepresentation() &&
10096 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
10097 return LIS.IsStrictCompare;
10098 });
10099 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10100 // unsigned IV)) for worksharing loops.
10101 SourceLocation CondLoc = AStmt->getBeginLoc();
10102 Expr *BoundUB = UB.get();
10103 if (UseStrictCompare) {
10104 BoundUB =
10105 SemaRef
10106 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10107 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10108 .get();
10109 BoundUB =
10110 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue*/ false).get();
10111 }
10112 ExprResult Cond =
10117 ? SemaRef.BuildBinOp(CurScope, CondLoc,
10118 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
10119 BoundUB)
10120 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10121 NumIterations.get());
10122 ExprResult CombDistCond;
10124 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10125 NumIterations.get());
10126 }
10127
10128 ExprResult CombCond;
10130 Expr *BoundCombUB = CombUB.get();
10131 if (UseStrictCompare) {
10132 BoundCombUB =
10133 SemaRef
10134 .BuildBinOp(
10135 CurScope, CondLoc, BO_Add, BoundCombUB,
10136 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10137 .get();
10138 BoundCombUB =
10139 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue*/ false)
10140 .get();
10141 }
10142 CombCond =
10143 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10144 IV.get(), BoundCombUB);
10145 }
10146 // Loop increment (IV = IV + 1)
10147 SourceLocation IncLoc = AStmt->getBeginLoc();
10148 ExprResult Inc =
10149 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
10150 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
10151 if (!Inc.isUsable())
10152 return 0;
10153 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
10154 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false);
10155 if (!Inc.isUsable())
10156 return 0;
10157
10158 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10159 // Used for directives with static scheduling.
10160 // In combined construct, add combined version that use CombLB and CombUB
10161 // base variables for the update
10162 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10167 // LB + ST
10168 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
10169 if (!NextLB.isUsable())
10170 return 0;
10171 // LB = LB + ST
10172 NextLB =
10173 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
10174 NextLB =
10175 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false);
10176 if (!NextLB.isUsable())
10177 return 0;
10178 // UB + ST
10179 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
10180 if (!NextUB.isUsable())
10181 return 0;
10182 // UB = UB + ST
10183 NextUB =
10184 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
10185 NextUB =
10186 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false);
10187 if (!NextUB.isUsable())
10188 return 0;
10190 CombNextLB =
10191 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
10192 if (!NextLB.isUsable())
10193 return 0;
10194 // LB = LB + ST
10195 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
10196 CombNextLB.get());
10197 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
10198 /*DiscardedValue*/ false);
10199 if (!CombNextLB.isUsable())
10200 return 0;
10201 // UB + ST
10202 CombNextUB =
10203 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
10204 if (!CombNextUB.isUsable())
10205 return 0;
10206 // UB = UB + ST
10207 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
10208 CombNextUB.get());
10209 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
10210 /*DiscardedValue*/ false);
10211 if (!CombNextUB.isUsable())
10212 return 0;
10213 }
10214 }
10215
10216 // Create increment expression for distribute loop when combined in a same
10217 // directive with for as IV = IV + ST; ensure upper bound expression based
10218 // on PrevUB instead of NumIterations - used to implement 'for' when found
10219 // in combination with 'distribute', like in 'distribute parallel for'
10220 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10221 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10223 DistCond = SemaRef.BuildBinOp(
10224 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10225 assert(DistCond.isUsable() && "distribute cond expr was not built");
10226
10227 DistInc =
10228 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10229 assert(DistInc.isUsable() && "distribute inc expr was not built");
10230 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10231 DistInc.get());
10232 DistInc =
10233 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false);
10234 assert(DistInc.isUsable() && "distribute inc expr was not built");
10235
10236 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10237 // construct
10238 ExprResult NewPrevUB = PrevUB;
10239 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10240 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10241 PrevUB.get()->getType())) {
10242 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10243 DistEUBLoc,
10245 DistEUBLoc, NewPrevUB.get());
10246 if (!NewPrevUB.isUsable())
10247 return 0;
10248 }
10249 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10250 UB.get(), NewPrevUB.get());
10251 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10252 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10253 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10254 CondOp.get());
10255 PrevEUB =
10256 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false);
10257
10258 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10259 // parallel for is in combination with a distribute directive with
10260 // schedule(static, 1)
10261 Expr *BoundPrevUB = PrevUB.get();
10262 if (UseStrictCompare) {
10263 BoundPrevUB =
10264 SemaRef
10265 .BuildBinOp(
10266 CurScope, CondLoc, BO_Add, BoundPrevUB,
10267 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10268 .get();
10269 BoundPrevUB =
10270 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue*/ false)
10271 .get();
10272 }
10273 ParForInDistCond =
10274 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10275 IV.get(), BoundPrevUB);
10276 }
10277
10278 // Build updates and final values of the loop counters.
10279 bool HasErrors = false;
10280 Built.Counters.resize(NestedLoopCount);
10281 Built.Inits.resize(NestedLoopCount);
10282 Built.Updates.resize(NestedLoopCount);
10283 Built.Finals.resize(NestedLoopCount);
10284 Built.DependentCounters.resize(NestedLoopCount);
10285 Built.DependentInits.resize(NestedLoopCount);
10286 Built.FinalsConditions.resize(NestedLoopCount);
10287 {
10288 // We implement the following algorithm for obtaining the
10289 // original loop iteration variable values based on the
10290 // value of the collapsed loop iteration variable IV.
10291 //
10292 // Let n+1 be the number of collapsed loops in the nest.
10293 // Iteration variables (I0, I1, .... In)
10294 // Iteration counts (N0, N1, ... Nn)
10295 //
10296 // Acc = IV;
10297 //
10298 // To compute Ik for loop k, 0 <= k <= n, generate:
10299 // Prod = N(k+1) * N(k+2) * ... * Nn;
10300 // Ik = Acc / Prod;
10301 // Acc -= Ik * Prod;
10302 //
10303 ExprResult Acc = IV;
10304 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10305 LoopIterationSpace &IS = IterSpaces[Cnt];
10306 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10308
10309 // Compute prod
10310 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10311 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10312 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10313 IterSpaces[K].NumIterations);
10314
10315 // Iter = Acc / Prod
10316 // If there is at least one more inner loop to avoid
10317 // multiplication by 1.
10318 if (Cnt + 1 < NestedLoopCount)
10319 Iter =
10320 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10321 else
10322 Iter = Acc;
10323 if (!Iter.isUsable()) {
10324 HasErrors = true;
10325 break;
10326 }
10327
10328 // Update Acc:
10329 // Acc -= Iter * Prod
10330 // Check if there is at least one more inner loop to avoid
10331 // multiplication by 1.
10332 if (Cnt + 1 < NestedLoopCount)
10333 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10334 Prod.get());
10335 else
10336 Prod = Iter;
10337 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10338
10339 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10340 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10341 DeclRefExpr *CounterVar = buildDeclRefExpr(
10342 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10343 /*RefersToCapture=*/true);
10345 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10346 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10347 if (!Init.isUsable()) {
10348 HasErrors = true;
10349 break;
10350 }
10352 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10353 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10354 if (!Update.isUsable()) {
10355 HasErrors = true;
10356 break;
10357 }
10358
10359 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10360 ExprResult Final =
10361 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10362 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10363 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10364 if (!Final.isUsable()) {
10365 HasErrors = true;
10366 break;
10367 }
10368
10369 if (!Update.isUsable() || !Final.isUsable()) {
10370 HasErrors = true;
10371 break;
10372 }
10373 // Save results
10374 Built.Counters[Cnt] = IS.CounterVar;
10375 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10376 Built.Inits[Cnt] = Init.get();
10377 Built.Updates[Cnt] = Update.get();
10378 Built.Finals[Cnt] = Final.get();
10379 Built.DependentCounters[Cnt] = nullptr;
10380 Built.DependentInits[Cnt] = nullptr;
10381 Built.FinalsConditions[Cnt] = nullptr;
10382 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10383 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10384 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10385 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10386 }
10387 }
10388 }
10389
10390 if (HasErrors)
10391 return 0;
10392
10393 // Save results
10394 Built.IterationVarRef = IV.get();
10395 Built.LastIteration = LastIteration.get();
10396 Built.NumIterations = NumIterations.get();
10397 Built.CalcLastIteration = SemaRef
10398 .ActOnFinishFullExpr(CalcLastIteration.get(),
10399 /*DiscardedValue=*/false)
10400 .get();
10401 Built.PreCond = PreCond.get();
10402 Built.PreInits = buildPreInits(C, Captures);
10403 Built.Cond = Cond.get();
10404 Built.Init = Init.get();
10405 Built.Inc = Inc.get();
10406 Built.LB = LB.get();
10407 Built.UB = UB.get();
10408 Built.IL = IL.get();
10409 Built.ST = ST.get();
10410 Built.EUB = EUB.get();
10411 Built.NLB = NextLB.get();
10412 Built.NUB = NextUB.get();
10413 Built.PrevLB = PrevLB.get();
10414 Built.PrevUB = PrevUB.get();
10415 Built.DistInc = DistInc.get();
10416 Built.PrevEUB = PrevEUB.get();
10417 Built.DistCombinedFields.LB = CombLB.get();
10418 Built.DistCombinedFields.UB = CombUB.get();
10419 Built.DistCombinedFields.EUB = CombEUB.get();
10420 Built.DistCombinedFields.Init = CombInit.get();
10421 Built.DistCombinedFields.Cond = CombCond.get();
10422 Built.DistCombinedFields.NLB = CombNextLB.get();
10423 Built.DistCombinedFields.NUB = CombNextUB.get();
10424 Built.DistCombinedFields.DistCond = CombDistCond.get();
10425 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10426
10427 return NestedLoopCount;
10428}
10429
10431 auto CollapseClauses =
10432 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10433 if (CollapseClauses.begin() != CollapseClauses.end())
10434 return (*CollapseClauses.begin())->getNumForLoops();
10435 return nullptr;
10436}
10437
10439 auto OrderedClauses =
10440 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10441 if (OrderedClauses.begin() != OrderedClauses.end())
10442 return (*OrderedClauses.begin())->getNumForLoops();
10443 return nullptr;
10444}
10445
10447 const ArrayRef<OMPClause *> Clauses) {
10448 const OMPSafelenClause *Safelen = nullptr;
10449 const OMPSimdlenClause *Simdlen = nullptr;
10450
10451 for (const OMPClause *Clause : Clauses) {
10452 if (Clause->getClauseKind() == OMPC_safelen)
10453 Safelen = cast<OMPSafelenClause>(Clause);
10454 else if (Clause->getClauseKind() == OMPC_simdlen)
10455 Simdlen = cast<OMPSimdlenClause>(Clause);
10456 if (Safelen && Simdlen)
10457 break;
10458 }
10459
10460 if (Simdlen && Safelen) {
10461 const Expr *SimdlenLength = Simdlen->getSimdlen();
10462 const Expr *SafelenLength = Safelen->getSafelen();
10463 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10464 SimdlenLength->isInstantiationDependent() ||
10465 SimdlenLength->containsUnexpandedParameterPack())
10466 return false;
10467 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10468 SafelenLength->isInstantiationDependent() ||
10469 SafelenLength->containsUnexpandedParameterPack())
10470 return false;
10471 Expr::EvalResult SimdlenResult, SafelenResult;
10472 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10473 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10474 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10475 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10476 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10477 // If both simdlen and safelen clauses are specified, the value of the
10478 // simdlen parameter must be less than or equal to the value of the safelen
10479 // parameter.
10480 if (SimdlenRes > SafelenRes) {
10481 S.Diag(SimdlenLength->getExprLoc(),
10482 diag::err_omp_wrong_simdlen_safelen_values)
10483 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10484 return true;
10485 }
10486 }
10487 return false;
10488}
10489
10492 DSAStackTy *Stack);
10493
10494bool Sema::checkLastPrivateForMappedDirectives(ArrayRef<OMPClause *> Clauses) {
10495
10496 // Check for syntax of lastprivate
10497 // Param of the lastprivate have different meanings in the mapped directives
10498 // e.g. "omp loop" Only loop iteration vars are allowed in lastprivate clause
10499 // "omp for" lastprivate vars must be shared
10500 if (getLangOpts().OpenMP >= 50 &&
10501 DSAStack->getMappedDirective() == OMPD_loop &&
10502 checkGenericLoopLastprivate(*this, Clauses, OMPD_loop, DSAStack)) {
10503 return false;
10504 }
10505 return true;
10506}
10507
10510 SourceLocation StartLoc, SourceLocation EndLoc,
10511 VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10512 if (!AStmt)
10513 return StmtError();
10514
10515 if (!checkLastPrivateForMappedDirectives(Clauses))
10516 return StmtError();
10517
10518 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10520 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10521 // define the nested loops number.
10522 unsigned NestedLoopCount = checkOpenMPLoop(
10523 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10524 AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
10525 if (NestedLoopCount == 0)
10526 return StmtError();
10527
10528 assert((CurContext->isDependentContext() || B.builtAll()) &&
10529 "omp simd loop exprs were not built");
10530
10532 // Finalize the clauses that need pre-built expressions for CodeGen.
10533 for (OMPClause *C : Clauses) {
10534 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10535 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10536 B.NumIterations, *this, CurScope,
10537 DSAStack))
10538 return StmtError();
10539 }
10540 }
10541
10542 if (checkSimdlenSafelenSpecified(*this, Clauses))
10543 return StmtError();
10544
10546 auto *SimdDirective = OMPSimdDirective::Create(
10547 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10548 DSAStack->getMappedDirective());
10549 return SimdDirective;
10550}
10551
10554 SourceLocation StartLoc, SourceLocation EndLoc,
10555 VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10556 if (!AStmt)
10557 return StmtError();
10558
10559 if (!checkLastPrivateForMappedDirectives(Clauses))
10560 return StmtError();
10561
10562 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10564 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10565 // define the nested loops number.
10566 unsigned NestedLoopCount = checkOpenMPLoop(
10567 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10568 AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
10569 if (NestedLoopCount == 0)
10570 return StmtError();
10571
10572 assert((CurContext->isDependentContext() || B.builtAll()) &&
10573 "omp for loop exprs were not built");
10574
10576 // Finalize the clauses that need pre-built expressions for CodeGen.
10577 for (OMPClause *C : Clauses) {
10578 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10579 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10580 B.NumIterations, *this, CurScope,
10581 DSAStack))
10582 return StmtError();
10583 }
10584 }
10585
10586 auto *ForDirective = OMPForDirective::Create(
10587 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10588 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion(),
10589 DSAStack->getMappedDirective());
10590 return ForDirective;
10591}
10592
10594 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10595 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10596 if (!AStmt)
10597 return StmtError();
10598
10599 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10601 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10602 // define the nested loops number.
10603 unsigned NestedLoopCount =
10604 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10605 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
10606 VarsWithImplicitDSA, B);
10607 if (NestedLoopCount == 0)
10608 return StmtError();
10609
10610 assert((CurContext->isDependentContext() || B.builtAll()) &&
10611 "omp for simd loop exprs were not built");
10612
10614 // Finalize the clauses that need pre-built expressions for CodeGen.
10615 for (OMPClause *C : Clauses) {
10616 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10617 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10618 B.NumIterations, *this, CurScope,
10619 DSAStack))
10620 return StmtError();
10621 }
10622 }
10623
10624 if (checkSimdlenSafelenSpecified(*this, Clauses))
10625 return StmtError();
10626
10628 return OMPForSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
10629 Clauses, AStmt, B);
10630}
10631
10633 Stmt *AStmt,
10634 SourceLocation StartLoc,
10635 SourceLocation EndLoc) {
10636 if (!AStmt)
10637 return StmtError();
10638
10639 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10640 auto BaseStmt = AStmt;
10641 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10642 BaseStmt = CS->getCapturedStmt();
10643 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10644 auto S = C->children();
10645 if (S.begin() == S.end())
10646 return StmtError();
10647 // All associated statements must be '#pragma omp section' except for
10648 // the first one.
10649 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10650 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10651 if (SectionStmt)
10652 Diag(SectionStmt->getBeginLoc(),
10653 diag::err_omp_sections_substmt_not_section);
10654 return StmtError();
10655 }
10656 cast<OMPSectionDirective>(SectionStmt)
10657 ->setHasCancel(DSAStack->isCancelRegion());
10658 }
10659 } else {
10660 Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt);
10661 return StmtError();
10662 }
10663
10665
10666 return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
10667 DSAStack->getTaskgroupReductionRef(),
10668 DSAStack->isCancelRegion());
10669}
10670
10672 SourceLocation StartLoc,
10673 SourceLocation EndLoc) {
10674 if (!AStmt)
10675 return StmtError();
10676
10678 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10679
10680 return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt,
10681 DSAStack->isCancelRegion());
10682}
10683
10685 E = E->IgnoreParenCasts()->IgnoreImplicit();
10686 if (auto *CE = dyn_cast<CallExpr>(E))
10687 if (CE->getDirectCallee())
10688 return E;
10689 return nullptr;
10690}
10691
10693 Stmt *AStmt,
10694 SourceLocation StartLoc,
10695 SourceLocation EndLoc) {
10696 if (!AStmt)
10697 return StmtError();
10698
10699 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10700
10701 // 5.1 OpenMP
10702 // expression-stmt : an expression statement with one of the following forms:
10703 // expression = target-call ( [expression-list] );
10704 // target-call ( [expression-list] );
10705
10706 SourceLocation TargetCallLoc;
10707
10709 Expr *TargetCall = nullptr;
10710
10711 auto *E = dyn_cast<Expr>(S);
10712 if (!E) {
10713 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10714 return StmtError();
10715 }
10716
10717 E = E->IgnoreParenCasts()->IgnoreImplicit();
10718
10719 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10720 if (BO->getOpcode() == BO_Assign)
10721 TargetCall = getDirectCallExpr(BO->getRHS());
10722 } else {
10723 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10724 if (COCE->getOperator() == OO_Equal)
10725 TargetCall = getDirectCallExpr(COCE->getArg(1));
10726 if (!TargetCall)
10727 TargetCall = getDirectCallExpr(E);
10728 }
10729 if (!TargetCall) {
10730 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10731 return StmtError();
10732 }
10733 TargetCallLoc = TargetCall->getExprLoc();
10734 }
10735
10737
10738 return OMPDispatchDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
10739 TargetCallLoc);
10740}
10741
10744 DSAStackTy *Stack) {
10745 bool ErrorFound = false;
10746 for (OMPClause *C : Clauses) {
10747 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10748 for (Expr *RefExpr : LPC->varlists()) {
10749 SourceLocation ELoc;
10750 SourceRange ERange;
10751 Expr *SimpleRefExpr = RefExpr;
10752 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10753 if (ValueDecl *D = Res.first) {
10754 auto &&Info = Stack->isLoopControlVariable(D);
10755 if (!Info.first) {
10756 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10757 << getOpenMPDirectiveName(K);
10758 ErrorFound = true;
10759 }
10760 }
10761 }
10762 }
10763 }
10764 return ErrorFound;
10765}
10766
10768 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10769 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10770 if (!AStmt)
10771 return StmtError();
10772
10773 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10774 // A list item may not appear in a lastprivate clause unless it is the
10775 // loop iteration variable of a loop that is associated with the construct.
10776 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_loop, DSAStack))
10777 return StmtError();
10778
10779 auto *CS = cast<CapturedStmt>(AStmt);
10780 // 1.2.2 OpenMP Language Terminology
10781 // Structured block - An executable statement with a single entry at the
10782 // top and a single exit at the bottom.
10783 // The point of exit cannot be a branch out of the structured block.
10784 // longjmp() and throw() must not violate the entry/exit criteria.
10785 CS->getCapturedDecl()->setNothrow();
10786
10788 // In presence of clause 'collapse', it will define the nested loops number.
10789 unsigned NestedLoopCount = checkOpenMPLoop(
10790 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10791 AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
10792 if (NestedLoopCount == 0)
10793 return StmtError();
10794
10795 assert((CurContext->isDependentContext() || B.builtAll()) &&
10796 "omp loop exprs were not built");
10797
10799 return OMPGenericLoopDirective::Create(Context, StartLoc, EndLoc,
10800 NestedLoopCount, Clauses, AStmt, B);
10801}
10802
10804 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10805 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10806 if (!AStmt)
10807 return StmtError();
10808
10809 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10810 // A list item may not appear in a lastprivate clause unless it is the
10811 // loop iteration variable of a loop that is associated with the construct.
10812 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_teams_loop, DSAStack))
10813 return StmtError();
10814
10815 auto *CS = cast<CapturedStmt>(AStmt);
10816 // 1.2.2 OpenMP Language Terminology
10817 // Structured block - An executable statement with a single entry at the
10818 // top and a single exit at the bottom.
10819 // The point of exit cannot be a branch out of the structured block.
10820 // longjmp() and throw() must not violate the entry/exit criteria.
10821 CS->getCapturedDecl()->setNothrow();
10822 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_loop);
10823 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10824 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10825 // 1.2.2 OpenMP Language Terminology
10826 // Structured block - An executable statement with a single entry at the
10827 // top and a single exit at the bottom.
10828 // The point of exit cannot be a branch out of the structured block.
10829 // longjmp() and throw() must not violate the entry/exit criteria.
10830 CS->getCapturedDecl()->setNothrow();
10831 }
10832
10834 // In presence of clause 'collapse', it will define the nested loops number.
10835 unsigned NestedLoopCount =
10836 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10837 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10838 VarsWithImplicitDSA, B);
10839 if (NestedLoopCount == 0)
10840 return StmtError();
10841
10842 assert((CurContext->isDependentContext() || B.builtAll()) &&
10843 "omp loop exprs were not built");
10844
10846 DSAStack->setParentTeamsRegionLoc(StartLoc);
10847
10849 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10850}
10851
10853 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10854 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10855 if (!AStmt)
10856 return StmtError();
10857
10858 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10859 // A list item may not appear in a lastprivate clause unless it is the
10860 // loop iteration variable of a loop that is associated with the construct.
10861 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_target_teams_loop,
10862 DSAStack))
10863 return StmtError();
10864
10865 auto *CS = cast<CapturedStmt>(AStmt);
10866 // 1.2.2 OpenMP Language Terminology
10867 // Structured block - An executable statement with a single entry at the
10868 // top and a single exit at the bottom.
10869 // The point of exit cannot be a branch out of the structured block.
10870 // longjmp() and throw() must not violate the entry/exit criteria.
10871 CS->getCapturedDecl()->setNothrow();
10872 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams_loop);
10873 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10874 CS = cast<CapturedStmt>(CS->getCapturedStmt());
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
10884 // In presence of clause 'collapse', it will define the nested loops number.
10885 unsigned NestedLoopCount =
10886 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10887 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10888 VarsWithImplicitDSA, B);
10889 if (NestedLoopCount == 0)
10890 return StmtError();
10891
10892 assert((CurContext->isDependentContext() || B.builtAll()) &&
10893 "omp loop exprs were not built");
10894
10896
10898 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10899}
10900
10902 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10903 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10904 if (!AStmt)
10905 return StmtError();
10906
10907 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10908 // A list item may not appear in a lastprivate clause unless it is the
10909 // loop iteration variable of a loop that is associated with the construct.
10910 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_parallel_loop, DSAStack))
10911 return StmtError();
10912
10913 auto *CS = cast<CapturedStmt>(AStmt);
10914 // 1.2.2 OpenMP Language Terminology
10915 // Structured block - An executable statement with a single entry at the
10916 // top and a single exit at the bottom.
10917 // The point of exit cannot be a branch out of the structured block.
10918 // longjmp() and throw() must not violate the entry/exit criteria.
10919 CS->getCapturedDecl()->setNothrow();
10920 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_parallel_loop);
10921 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10922 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10923 // 1.2.2 OpenMP Language Terminology
10924 // Structured block - An executable statement with a single entry at the
10925 // top and a single exit at the bottom.
10926 // The point of exit cannot be a branch out of the structured block.
10927 // longjmp() and throw() must not violate the entry/exit criteria.
10928 CS->getCapturedDecl()->setNothrow();
10929 }
10930
10932 // In presence of clause 'collapse', it will define the nested loops number.
10933 unsigned NestedLoopCount =
10934 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
10935 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10936 VarsWithImplicitDSA, B);
10937 if (NestedLoopCount == 0)
10938 return StmtError();
10939
10940 assert((CurContext->isDependentContext() || B.builtAll()) &&
10941 "omp loop exprs were not built");
10942
10944
10946 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10947}
10948
10950 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10951 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10952 if (!AStmt)
10953 return StmtError();
10954
10955 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10956 // A list item may not appear in a lastprivate clause unless it is the
10957 // loop iteration variable of a loop that is associated with the construct.
10958 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_target_parallel_loop,
10959 DSAStack))
10960 return StmtError();
10961
10962 auto *CS = cast<CapturedStmt>(AStmt);
10963 // 1.2.2 OpenMP Language Terminology
10964 // Structured block - An executable statement with a single entry at the
10965 // top and a single exit at the bottom.
10966 // The point of exit cannot be a branch out of the structured block.
10967 // longjmp() and throw() must not violate the entry/exit criteria.
10968 CS->getCapturedDecl()->setNothrow();
10969 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_loop);
10970 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10971 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10972 // 1.2.2 OpenMP Language Terminology
10973 // Structured block - An executable statement with a single entry at the
10974 // top and a single exit at the bottom.
10975 // The point of exit cannot be a branch out of the structured block.
10976 // longjmp() and throw() must not violate the entry/exit criteria.
10977 CS->getCapturedDecl()->setNothrow();
10978 }
10979
10981 // In presence of clause 'collapse', it will define the nested loops number.
10982 unsigned NestedLoopCount =
10983 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
10984 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
10985 VarsWithImplicitDSA, B);
10986 if (NestedLoopCount == 0)
10987 return StmtError();
10988
10989 assert((CurContext->isDependentContext() || B.builtAll()) &&
10990 "omp loop exprs were not built");
10991
10993
10995 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10996}
10997
10999 Stmt *AStmt,
11000 SourceLocation StartLoc,
11001 SourceLocation EndLoc) {
11002 if (!AStmt)
11003 return StmtError();
11004
11005 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11006
11008
11009 // OpenMP [2.7.3, single Construct, Restrictions]
11010 // The copyprivate clause must not be used with the nowait clause.
11011 const OMPClause *Nowait = nullptr;
11012 const OMPClause *Copyprivate = nullptr;
11013 for (const OMPClause *Clause : Clauses) {
11014 if (Clause->getClauseKind() == OMPC_nowait)
11015 Nowait = Clause;
11016 else if (Clause->getClauseKind() == OMPC_copyprivate)
11017 Copyprivate = Clause;
11018 if (Copyprivate && Nowait) {
11019 Diag(Copyprivate->getBeginLoc(),
11020 diag::err_omp_single_copyprivate_with_nowait);
11021 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
11022 return StmtError();
11023 }
11024 }
11025
11026 return OMPSingleDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
11027}
11028
11030 SourceLocation StartLoc,
11031 SourceLocation EndLoc) {
11032 if (!AStmt)
11033 return StmtError();
11034
11036
11037 return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt);
11038}
11039
11041 Stmt *AStmt,
11042 SourceLocation StartLoc,
11043 SourceLocation EndLoc) {
11044 if (!AStmt)
11045 return StmtError();
11046
11048
11049 return OMPMaskedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
11050}
11051
11053 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
11054 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
11055 if (!AStmt)
11056 return StmtError();
11057
11058 bool ErrorFound = false;
11059 llvm::APSInt Hint;
11060 SourceLocation HintLoc;
11061 bool DependentHint = false;
11062 for (const OMPClause *C : Clauses) {
11063 if (C->getClauseKind() == OMPC_hint) {
11064 if (!DirName.getName()) {
11065 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
11066 ErrorFound = true;
11067 }
11068 Expr *E = cast<OMPHintClause>(C)->getHint();
11069 if (E->isTypeDependent() || E->isValueDependent() ||
11071 DependentHint = true;
11072 } else {
11073 Hint = E->EvaluateKnownConstInt(Context);
11074 HintLoc = C->getBeginLoc();
11075 }
11076 }
11077 }
11078 if (ErrorFound)
11079 return StmtError();
11080 const auto Pair = DSAStack->getCriticalWithHint(DirName);
11081 if (Pair.first && DirName.getName() && !DependentHint) {
11082 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
11083 Diag(StartLoc, diag::err_omp_critical_with_hint);
11084 if (HintLoc.isValid())
11085 Diag(HintLoc, diag::note_omp_critical_hint_here)
11086 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
11087 else
11088 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
11089 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
11090 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
11091 << 1
11092 << toString(C->getHint()->EvaluateKnownConstInt(Context),
11093 /*Radix=*/10, /*Signed=*/false);
11094 } else {
11095 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
11096 }
11097 }
11098 }
11099
11101
11102 auto *Dir = OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc,
11103 Clauses, AStmt);
11104 if (!Pair.first && DirName.getName() && !DependentHint)
11105 DSAStack->addCriticalWithHint(Dir, Hint);
11106 return Dir;
11107}
11108
11110 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11111 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11112 if (!AStmt)
11113 return StmtError();
11114
11115 auto *CS = cast<CapturedStmt>(AStmt);
11116 // 1.2.2 OpenMP Language Terminology
11117 // Structured block - An executable statement with a single entry at the
11118 // top and a single exit at the bottom.
11119 // The point of exit cannot be a branch out of the structured block.
11120 // longjmp() and throw() must not violate the entry/exit criteria.
11121 CS->getCapturedDecl()->setNothrow();
11122
11124 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11125 // define the nested loops number.
11126 unsigned NestedLoopCount =
11127 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
11128 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
11129 VarsWithImplicitDSA, B);
11130 if (NestedLoopCount == 0)
11131 return StmtError();
11132
11133 assert((CurContext->isDependentContext() || B.builtAll()) &&
11134 "omp parallel for loop exprs were not built");
11135
11137 // Finalize the clauses that need pre-built expressions for CodeGen.
11138 for (OMPClause *C : Clauses) {
11139 if (auto *LC = dyn_cast<OMPLinearClause>(C))
11140 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
11141 B.NumIterations, *this, CurScope,
11142 DSAStack))
11143 return StmtError();
11144 }
11145 }
11146
11149 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11150 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11151}
11152
11154 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11155 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11156 if (!AStmt)
11157 return StmtError();
11158
11159 auto *CS = cast<CapturedStmt>(AStmt);
11160 // 1.2.2 OpenMP Language Terminology
11161 // Structured block - An executable statement with a single entry at the
11162 // top and a single exit at the bottom.
11163 // The point of exit cannot be a branch out of the structured block.
11164 // longjmp() and throw() must not violate the entry/exit criteria.
11165 CS->getCapturedDecl()->setNothrow();
11166
11168 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11169 // define the nested loops number.
11170 unsigned NestedLoopCount =
11171 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
11172 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
11173 VarsWithImplicitDSA, B);
11174 if (NestedLoopCount == 0)
11175 return StmtError();
11176
11178 // Finalize the clauses that need pre-built expressions for CodeGen.
11179 for (OMPClause *C : Clauses) {
11180 if (auto *LC = dyn_cast<OMPLinearClause>(C))
11181 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
11182 B.NumIterations, *this, CurScope,
11183 DSAStack))
11184 return StmtError();
11185 }
11186 }
11187
11188 if (checkSimdlenSafelenSpecified(*this, Clauses))
11189 return StmtError();
11190
11193 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11194}
11195
11198 Stmt *AStmt, SourceLocation StartLoc,
11199 SourceLocation EndLoc) {
11200 if (!AStmt)
11201 return StmtError();
11202
11203 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11204 auto *CS = cast<CapturedStmt>(AStmt);
11205 // 1.2.2 OpenMP Language Terminology
11206 // Structured block - An executable statement with a single entry at the
11207 // top and a single exit at the bottom.
11208 // The point of exit cannot be a branch out of the structured block.
11209 // longjmp() and throw() must not violate the entry/exit criteria.
11210 CS->getCapturedDecl()->setNothrow();
11211
11213
11215 Context, StartLoc, EndLoc, Clauses, AStmt,
11216 DSAStack->getTaskgroupReductionRef());
11217}
11218
11221 Stmt *AStmt, SourceLocation StartLoc,
11222 SourceLocation EndLoc) {
11223 if (!AStmt)
11224 return StmtError();
11225
11226 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11227 auto *CS = cast<CapturedStmt>(AStmt);
11228 // 1.2.2 OpenMP Language Terminology
11229 // Structured block - An executable statement with a single entry at the
11230 // top and a single exit at the bottom.
11231 // The point of exit cannot be a branch out of the structured block.
11232 // longjmp() and throw() must not violate the entry/exit criteria.
11233 CS->getCapturedDecl()->setNothrow();
11234
11236
11238 Context, StartLoc, EndLoc, Clauses, AStmt,
11239 DSAStack->getTaskgroupReductionRef());
11240}
11241
11244 Stmt *AStmt, SourceLocation StartLoc,
11245 SourceLocation EndLoc) {
11246 if (!AStmt)
11247 return StmtError();
11248
11249 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11250 auto BaseStmt = AStmt;
11251 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
11252 BaseStmt = CS->getCapturedStmt();
11253 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
11254 auto S = C->children();
11255 if (S.begin() == S.end())
11256 return StmtError();
11257 // All associated statements must be '#pragma omp section' except for
11258 // the first one.
11259 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
11260 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
11261 if (SectionStmt)
11262 Diag(SectionStmt->getBeginLoc(),
11263 diag::err_omp_parallel_sections_substmt_not_section);
11264 return StmtError();
11265 }
11266 cast<OMPSectionDirective>(SectionStmt)
11267 ->setHasCancel(DSAStack->isCancelRegion());
11268 }
11269 } else {
11270 Diag(AStmt->getBeginLoc(),
11271 diag::err_omp_parallel_sections_not_compound_stmt);
11272 return StmtError();
11273 }
11274
11276
11278 Context, StartLoc, EndLoc, Clauses, AStmt,
11279 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11280}
11281
11282/// Find and diagnose mutually exclusive clause kinds.
11284 Sema &S, ArrayRef<OMPClause *> Clauses,
11285 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11286 const OMPClause *PrevClause = nullptr;
11287 bool ErrorFound = false;
11288 for (const OMPClause *C : Clauses) {
11289 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
11290 if (!PrevClause) {
11291 PrevClause = C;
11292 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11293 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11294 << getOpenMPClauseName(C->getClauseKind())
11295 << getOpenMPClauseName(PrevClause->getClauseKind());
11296 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
11297 << getOpenMPClauseName(PrevClause->getClauseKind());
11298 ErrorFound = true;
11299 }
11300 }
11301 }
11302 return ErrorFound;
11303}
11304
11306 Stmt *AStmt, SourceLocation StartLoc,
11307 SourceLocation EndLoc) {
11308 if (!AStmt)
11309 return StmtError();
11310
11311 // OpenMP 5.0, 2.10.1 task Construct
11312 // If a detach clause appears on the directive, then a mergeable clause cannot
11313 // appear on the same directive.
11314 if (checkMutuallyExclusiveClauses(*this, Clauses,
11315 {OMPC_detach, OMPC_mergeable}))
11316 return StmtError();
11317
11318 auto *CS = cast<CapturedStmt>(AStmt);
11319 // 1.2.2 OpenMP Language Terminology
11320 // Structured block - An executable statement with a single entry at the
11321 // top and a single exit at the bottom.
11322 // The point of exit cannot be a branch out of the structured block.
11323 // longjmp() and throw() must not violate the entry/exit criteria.
11324 CS->getCapturedDecl()->setNothrow();
11325
11327
11328 return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
11329 DSAStack->isCancelRegion());
11330}
11331
11333 SourceLocation EndLoc) {
11334 return OMPTaskyieldDirective::Create(Context, StartLoc, EndLoc);
11335}
11336
11338 SourceLocation EndLoc) {
11339 return OMPBarrierDirective::Create(Context, StartLoc, EndLoc);
11340}
11341
11343 SourceLocation StartLoc,
11344 SourceLocation EndLoc,
11345 bool InExContext) {
11346 const OMPAtClause *AtC =
11347 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11348
11349 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11350 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11351 return StmtError();
11352 }
11353
11354 const OMPSeverityClause *SeverityC =
11355 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11356 const OMPMessageClause *MessageC =
11357 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11358 Expr *ME = MessageC ? MessageC->getMessageString() : nullptr;
11359
11360 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11361 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11362 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11363 << (ME ? cast<StringLiteral>(ME)->getString() : "WARNING");
11364 else
11365 Diag(StartLoc, diag::err_diagnose_if_succeeded)
11366 << (ME ? cast<StringLiteral>(ME)->getString() : "ERROR");
11367 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11368 return StmtError();
11369 }
11370 return OMPErrorDirective::Create(Context, StartLoc, EndLoc, Clauses);
11371}
11372
11374 SourceLocation StartLoc,
11375 SourceLocation EndLoc) {
11376 const OMPNowaitClause *NowaitC =
11377 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11378 bool HasDependC =
11379 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11380 .empty();
11381 if (NowaitC && !HasDependC) {
11382 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11383 return StmtError();
11384 }
11385
11386 return OMPTaskwaitDirective::Create(Context, StartLoc, EndLoc, Clauses);
11387}
11388
11390 Stmt *AStmt,
11391 SourceLocation StartLoc,
11392 SourceLocation EndLoc) {
11393 if (!AStmt)
11394 return StmtError();
11395
11396 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11397
11399
11400 return OMPTaskgroupDirective::Create(Context, StartLoc, EndLoc, Clauses,
11401 AStmt,
11402 DSAStack->getTaskgroupReductionRef());
11403}
11404
11406 SourceLocation StartLoc,
11407 SourceLocation EndLoc) {
11408 OMPFlushClause *FC = nullptr;
11409 OMPClause *OrderClause = nullptr;
11410 for (OMPClause *C : Clauses) {
11411 if (C->getClauseKind() == OMPC_flush)
11412 FC = cast<OMPFlushClause>(C);
11413 else
11414 OrderClause = C;
11415 }
11416 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11417 SourceLocation MemOrderLoc;
11418 for (const OMPClause *C : Clauses) {
11419 if (C->getClauseKind() == OMPC_acq_rel ||
11420 C->getClauseKind() == OMPC_acquire ||
11421 C->getClauseKind() == OMPC_release) {
11422 if (MemOrderKind != OMPC_unknown) {
11423 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11424 << getOpenMPDirectiveName(OMPD_flush) << 1
11425 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11426 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11427 << getOpenMPClauseName(MemOrderKind);
11428 } else {
11429 MemOrderKind = C->getClauseKind();
11430 MemOrderLoc = C->getBeginLoc();
11431 }
11432 }
11433 }
11434 if (FC && OrderClause) {
11435 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11436 << getOpenMPClauseName(OrderClause->getClauseKind());
11437 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11438 << getOpenMPClauseName(OrderClause->getClauseKind());
11439 return StmtError();
11440 }
11441 return OMPFlushDirective::Create(Context, StartLoc, EndLoc, Clauses);
11442}
11443
11445 SourceLocation StartLoc,
11446 SourceLocation EndLoc) {
11447 if (Clauses.empty()) {
11448 Diag(StartLoc, diag::err_omp_depobj_expected);
11449 return StmtError();
11450 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11451 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11452 return StmtError();
11453 }
11454 // Only depobj expression and another single clause is allowed.
11455 if (Clauses.size() > 2) {
11456 Diag(Clauses[2]->getBeginLoc(),
11457 diag::err_omp_depobj_single_clause_expected);
11458 return StmtError();
11459 } else if (Clauses.size() < 1) {
11460 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11461 return StmtError();
11462 }
11463 return OMPDepobjDirective::Create(Context, StartLoc, EndLoc, Clauses);
11464}
11465
11467 SourceLocation StartLoc,
11468 SourceLocation EndLoc) {
11469 // Check that exactly one clause is specified.
11470 if (Clauses.size() != 1) {
11471 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11472 diag::err_omp_scan_single_clause_expected);
11473 return StmtError();
11474 }
11475 // Check that scan directive is used in the scopeof the OpenMP loop body.
11476 if (Scope *S = DSAStack->getCurScope()) {
11477 Scope *ParentS = S->getParent();
11478 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11479 !ParentS->getBreakParent()->isOpenMPLoopScope())
11480 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11481 << getOpenMPDirectiveName(OMPD_scan) << 5);
11482 }
11483 // Check that only one instance of scan directives is used in the same outer
11484 // region.
11485 if (DSAStack->doesParentHasScanDirective()) {
11486 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11487 Diag(DSAStack->getParentScanDirectiveLoc(),
11488 diag::note_omp_previous_directive)
11489 << "scan";
11490 return StmtError();
11491 }
11492 DSAStack->setParentHasScanDirective(StartLoc);
11493 return OMPScanDirective::Create(Context, StartLoc, EndLoc, Clauses);
11494}
11495
11497 Stmt *AStmt,
11498 SourceLocation StartLoc,
11499 SourceLocation EndLoc) {
11500 const OMPClause *DependFound = nullptr;
11501 const OMPClause *DependSourceClause = nullptr;
11502 const OMPClause *DependSinkClause = nullptr;
11503 const OMPClause *DoacrossFound = nullptr;
11504 const OMPClause *DoacrossSourceClause = nullptr;
11505 const OMPClause *DoacrossSinkClause = nullptr;
11506 bool ErrorFound = false;
11507 const OMPThreadsClause *TC = nullptr;
11508 const OMPSIMDClause *SC = nullptr;
11509 for (const OMPClause *C : Clauses) {
11510 auto DOC = dyn_cast<OMPDoacrossClause>(C);
11511 auto DC = dyn_cast<OMPDependClause>(C);
11512 if (DC || DOC) {
11513 DependFound = DC ? C : nullptr;
11514 DoacrossFound = DOC ? C : nullptr;
11515 OMPDoacrossKind ODK;
11516 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11517 (DOC && (ODK.isSource(DOC)))) {
11518 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11519 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11520 << getOpenMPDirectiveName(OMPD_ordered)
11521 << getOpenMPClauseName(DC ? OMPC_depend : OMPC_doacross) << 2;
11522 ErrorFound = true;
11523 } else {
11524 if (DC)
11525 DependSourceClause = C;
11526 else
11527 DoacrossSourceClause = C;
11528 }
11529 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11530 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11531 << (DC ? "depend" : "doacross") << 0;
11532 ErrorFound = true;
11533 }
11534 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11535 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11536 if (DependSourceClause || DoacrossSourceClause) {
11537 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11538 << (DC ? "depend" : "doacross") << 1;
11539 ErrorFound = true;
11540 }
11541 if (DC)
11542 DependSinkClause = C;
11543 else
11544 DoacrossSinkClause = C;
11545 }
11546 } else if (C->getClauseKind() == OMPC_threads) {
11547 TC = cast<OMPThreadsClause>(C);
11548 } else if (C->getClauseKind() == OMPC_simd) {
11549 SC = cast<OMPSIMDClause>(C);
11550 }
11551 }
11552 if (!ErrorFound && !SC &&
11553 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11554 // OpenMP [2.8.1,simd Construct, Restrictions]
11555 // An ordered construct with the simd clause is the only OpenMP construct
11556 // that can appear in the simd region.
11557 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11558 << (LangOpts.OpenMP >= 50 ? 1 : 0);
11559 ErrorFound = true;
11560 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11561 SourceLocation Loc =
11562 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11563 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11564 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross)
11565 << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
11566 ErrorFound = true;
11567 } else if ((DependFound || DoacrossFound) &&
11568 !DSAStack->getParentOrderedRegionParam().first) {
11569 SourceLocation Loc =
11570 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11571 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11572 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross);
11573 ErrorFound = true;
11574 } else if (TC || Clauses.empty()) {
11575 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11576 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11577 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11578 << (TC != nullptr);
11579 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11580 ErrorFound = true;
11581 }
11582 }
11583 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11584 return StmtError();
11585
11586 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11587 // During execution of an iteration of a worksharing-loop or a loop nest
11588 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11589 // must not execute more than one ordered region corresponding to an ordered
11590 // construct without a depend clause.
11591 if (!DependFound && !DoacrossFound) {
11592 if (DSAStack->doesParentHasOrderedDirective()) {
11593 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11594 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11595 diag::note_omp_previous_directive)
11596 << "ordered";
11597 return StmtError();
11598 }
11599 DSAStack->setParentHasOrderedDirective(StartLoc);
11600 }
11601
11602 if (AStmt) {
11603 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11604
11606 }
11607
11608 return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
11609}
11610
11611namespace {
11612/// Helper class for checking expression in 'omp atomic [update]'
11613/// construct.
11614class OpenMPAtomicUpdateChecker {
11615 /// Error results for atomic update expressions.
11616 enum ExprAnalysisErrorCode {
11617 /// A statement is not an expression statement.
11618 NotAnExpression,
11619 /// Expression is not builtin binary or unary operation.
11620 NotABinaryOrUnaryExpression,
11621 /// Unary operation is not post-/pre- increment/decrement operation.
11622 NotAnUnaryIncDecExpression,
11623 /// An expression is not of scalar type.
11624 NotAScalarType,
11625 /// A binary operation is not an assignment operation.
11626 NotAnAssignmentOp,
11627 /// RHS part of the binary operation is not a binary expression.
11628 NotABinaryExpression,
11629 /// RHS part is not additive/multiplicative/shift/biwise binary
11630 /// expression.
11631 NotABinaryOperator,
11632 /// RHS binary operation does not have reference to the updated LHS
11633 /// part.
11634 NotAnUpdateExpression,
11635 /// An expression contains semantical error not related to
11636 /// 'omp atomic [update]'
11637 NotAValidExpression,
11638 /// No errors is found.
11639 NoError
11640 };
11641 /// Reference to Sema.
11642 Sema &SemaRef;
11643 /// A location for note diagnostics (when error is found).
11644 SourceLocation NoteLoc;
11645 /// 'x' lvalue part of the source atomic expression.
11646 Expr *X;
11647 /// 'expr' rvalue part of the source atomic expression.
11648 Expr *E;
11649 /// Helper expression of the form
11650 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11651 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11652 Expr *UpdateExpr;
11653 /// Is 'x' a LHS in a RHS part of full update expression. It is
11654 /// important for non-associative operations.
11655 bool IsXLHSInRHSPart;
11657 SourceLocation OpLoc;
11658 /// true if the source expression is a postfix unary operation, false
11659 /// if it is a prefix unary operation.
11660 bool IsPostfixUpdate;
11661
11662public:
11663 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11664 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11665 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11666 /// Check specified statement that it is suitable for 'atomic update'
11667 /// constructs and extract 'x', 'expr' and Operation from the original
11668 /// expression. If DiagId and NoteId == 0, then only check is performed
11669 /// without error notification.
11670 /// \param DiagId Diagnostic which should be emitted if error is found.
11671 /// \param NoteId Diagnostic note for the main error message.
11672 /// \return true if statement is not an update expression, false otherwise.
11673 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11674 /// Return the 'x' lvalue part of the source atomic expression.
11675 Expr *getX() const { return X; }
11676 /// Return the 'expr' rvalue part of the source atomic expression.
11677 Expr *getExpr() const { return E; }
11678 /// Return the update expression used in calculation of the updated
11679 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11680 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11681 Expr *getUpdateExpr() const { return UpdateExpr; }
11682 /// Return true if 'x' is LHS in RHS part of full update expression,
11683 /// false otherwise.
11684 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11685
11686 /// true if the source expression is a postfix unary operation, false
11687 /// if it is a prefix unary operation.
11688 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11689
11690private:
11691 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11692 unsigned NoteId = 0);
11693};
11694
11695bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11696 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11697 ExprAnalysisErrorCode ErrorFound = NoError;
11698 SourceLocation ErrorLoc, NoteLoc;
11699 SourceRange ErrorRange, NoteRange;
11700 // Allowed constructs are:
11701 // x = x binop expr;
11702 // x = expr binop x;
11703 if (AtomicBinOp->getOpcode() == BO_Assign) {
11704 X = AtomicBinOp->getLHS();
11705 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11706 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11707 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11708 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11709 AtomicInnerBinOp->isBitwiseOp()) {
11710 Op = AtomicInnerBinOp->getOpcode();
11711 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11712 Expr *LHS = AtomicInnerBinOp->getLHS();
11713 Expr *RHS = AtomicInnerBinOp->getRHS();
11714 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11715 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11716 /*Canonical=*/true);
11717 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11718 /*Canonical=*/true);
11719 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11720 /*Canonical=*/true);
11721 if (XId == LHSId) {
11722 E = RHS;
11723 IsXLHSInRHSPart = true;
11724 } else if (XId == RHSId) {
11725 E = LHS;
11726 IsXLHSInRHSPart = false;
11727 } else {
11728 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11729 ErrorRange = AtomicInnerBinOp->getSourceRange();
11730 NoteLoc = X->getExprLoc();
11731 NoteRange = X->getSourceRange();
11732 ErrorFound = NotAnUpdateExpression;
11733 }
11734 } else {
11735 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11736 ErrorRange = AtomicInnerBinOp->getSourceRange();
11737 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11738 NoteRange = SourceRange(NoteLoc, NoteLoc);
11739 ErrorFound = NotABinaryOperator;
11740 }
11741 } else {
11742 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11743 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11744 ErrorFound = NotABinaryExpression;
11745 }
11746 } else {
11747 ErrorLoc = AtomicBinOp->getExprLoc();
11748 ErrorRange = AtomicBinOp->getSourceRange();
11749 NoteLoc = AtomicBinOp->getOperatorLoc();
11750 NoteRange = SourceRange(NoteLoc, NoteLoc);
11751 ErrorFound = NotAnAssignmentOp;
11752 }
11753 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11754 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11755 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11756 return true;
11757 }
11758 if (SemaRef.CurContext->isDependentContext())
11759 E = X = UpdateExpr = nullptr;
11760 return ErrorFound != NoError;
11761}
11762
11763bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11764 unsigned NoteId) {
11765 ExprAnalysisErrorCode ErrorFound = NoError;
11766 SourceLocation ErrorLoc, NoteLoc;
11767 SourceRange ErrorRange, NoteRange;
11768 // Allowed constructs are:
11769 // x++;
11770 // x--;
11771 // ++x;
11772 // --x;
11773 // x binop= expr;
11774 // x = x binop expr;
11775 // x = expr binop x;
11776 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11777 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11778 if (AtomicBody->getType()->isScalarType() ||
11779 AtomicBody->isInstantiationDependent()) {
11780 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11781 AtomicBody->IgnoreParenImpCasts())) {
11782 // Check for Compound Assignment Operation
11784 AtomicCompAssignOp->getOpcode());
11785 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11786 E = AtomicCompAssignOp->getRHS();
11787 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11788 IsXLHSInRHSPart = true;
11789 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11790 AtomicBody->IgnoreParenImpCasts())) {
11791 // Check for Binary Operation
11792 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11793 return true;
11794 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11795 AtomicBody->IgnoreParenImpCasts())) {
11796 // Check for Unary Operation
11797 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11798 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11799 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11800 OpLoc = AtomicUnaryOp->getOperatorLoc();
11801 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11802 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11803 IsXLHSInRHSPart = true;
11804 } else {
11805 ErrorFound = NotAnUnaryIncDecExpression;
11806 ErrorLoc = AtomicUnaryOp->getExprLoc();
11807 ErrorRange = AtomicUnaryOp->getSourceRange();
11808 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11809 NoteRange = SourceRange(NoteLoc, NoteLoc);
11810 }
11811 } else if (!AtomicBody->isInstantiationDependent()) {
11812 ErrorFound = NotABinaryOrUnaryExpression;
11813 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11814 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11815 } else if (AtomicBody->containsErrors()) {
11816 ErrorFound = NotAValidExpression;
11817 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11818 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11819 }
11820 } else {
11821 ErrorFound = NotAScalarType;
11822 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11823 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11824 }
11825 } else {
11826 ErrorFound = NotAnExpression;
11827 NoteLoc = ErrorLoc = S->getBeginLoc();
11828 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11829 }
11830 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11831 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11832 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11833 return true;
11834 }
11835 if (SemaRef.CurContext->isDependentContext())
11836 E = X = UpdateExpr = nullptr;
11837 if (ErrorFound == NoError && E && X) {
11838 // Build an update expression of form 'OpaqueValueExpr(x) binop
11839 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11840 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11841 auto *OVEX = new (SemaRef.getASTContext())
11842 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11843 auto *OVEExpr = new (SemaRef.getASTContext())
11846 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11847 IsXLHSInRHSPart ? OVEExpr : OVEX);
11848 if (Update.isInvalid())
11849 return true;
11850 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11852 if (Update.isInvalid())
11853 return true;
11854 UpdateExpr = Update.get();
11855 }
11856 return ErrorFound != NoError;
11857}
11858
11859/// Get the node id of the fixed point of an expression \a S.
11860llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11861 llvm::FoldingSetNodeID Id;
11862 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11863 return Id;
11864}
11865
11866/// Check if two expressions are same.
11867bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11868 const Expr *RHS) {
11869 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11870}
11871
11872class OpenMPAtomicCompareChecker {
11873public:
11874 /// All kinds of errors that can occur in `atomic compare`
11875 enum ErrorTy {
11876 /// Empty compound statement.
11877 NoStmt = 0,
11878 /// More than one statement in a compound statement.
11879 MoreThanOneStmt,
11880 /// Not an assignment binary operator.
11881 NotAnAssignment,
11882 /// Not a conditional operator.
11883 NotCondOp,
11884 /// Wrong false expr. According to the spec, 'x' should be at the false
11885 /// expression of a conditional expression.
11886 WrongFalseExpr,
11887 /// The condition of a conditional expression is not a binary operator.
11888 NotABinaryOp,
11889 /// Invalid binary operator (not <, >, or ==).
11890 InvalidBinaryOp,
11891 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11892 InvalidComparison,
11893 /// X is not a lvalue.
11894 XNotLValue,
11895 /// Not a scalar.
11896 NotScalar,
11897 /// Not an integer.
11898 NotInteger,
11899 /// 'else' statement is not expected.
11900 UnexpectedElse,
11901 /// Not an equality operator.
11902 NotEQ,
11903 /// Invalid assignment (not v == x).
11904 InvalidAssignment,
11905 /// Not if statement
11906 NotIfStmt,
11907 /// More than two statements in a compund statement.
11908 MoreThanTwoStmts,
11909 /// Not a compound statement.
11910 NotCompoundStmt,
11911 /// No else statement.
11912 NoElse,
11913 /// Not 'if (r)'.
11914 InvalidCondition,
11915 /// No error.
11916 NoError,
11917 };
11918
11919 struct ErrorInfoTy {
11920 ErrorTy Error;
11921 SourceLocation ErrorLoc;
11922 SourceRange ErrorRange;
11923 SourceLocation NoteLoc;
11924 SourceRange NoteRange;
11925 };
11926
11927 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11928
11929 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11930 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11931
11932 Expr *getX() const { return X; }
11933 Expr *getE() const { return E; }
11934 Expr *getD() const { return D; }
11935 Expr *getCond() const { return C; }
11936 bool isXBinopExpr() const { return IsXBinopExpr; }
11937
11938protected:
11939 /// Reference to ASTContext
11940 ASTContext &ContextRef;
11941 /// 'x' lvalue part of the source atomic expression.
11942 Expr *X = nullptr;
11943 /// 'expr' or 'e' rvalue part of the source atomic expression.
11944 Expr *E = nullptr;
11945 /// 'd' rvalue part of the source atomic expression.
11946 Expr *D = nullptr;
11947 /// 'cond' part of the source atomic expression. It is in one of the following
11948 /// forms:
11949 /// expr ordop x
11950 /// x ordop expr
11951 /// x == e
11952 /// e == x
11953 Expr *C = nullptr;
11954 /// True if the cond expr is in the form of 'x ordop expr'.
11955 bool IsXBinopExpr = true;
11956
11957 /// Check if it is a valid conditional update statement (cond-update-stmt).
11958 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11959
11960 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11961 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11962
11963 /// Check if all captured values have right type.
11964 bool checkType(ErrorInfoTy &ErrorInfo) const;
11965
11966 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11967 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11968 if (E->isInstantiationDependent())
11969 return true;
11970
11971 if (ShouldBeLValue && !E->isLValue()) {
11972 ErrorInfo.Error = ErrorTy::XNotLValue;
11973 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11974 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11975 return false;
11976 }
11977
11978 QualType QTy = E->getType();
11979 if (!QTy->isScalarType()) {
11980 ErrorInfo.Error = ErrorTy::NotScalar;
11981 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11982 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11983 return false;
11984 }
11985 if (ShouldBeInteger && !QTy->isIntegerType()) {
11986 ErrorInfo.Error = ErrorTy::NotInteger;
11987 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11988 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11989 return false;
11990 }
11991
11992 return true;
11993 }
11994 };
11995
11996bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11997 ErrorInfoTy &ErrorInfo) {
11998 auto *Then = S->getThen();
11999 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12000 if (CS->body_empty()) {
12001 ErrorInfo.Error = ErrorTy::NoStmt;
12002 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12003 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12004 return false;
12005 }
12006 if (CS->size() > 1) {
12007 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12008 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12009 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12010 return false;
12011 }
12012 Then = CS->body_front();
12013 }
12014
12015 auto *BO = dyn_cast<BinaryOperator>(Then);
12016 if (!BO) {
12017 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12018 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12019 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12020 return false;
12021 }
12022 if (BO->getOpcode() != BO_Assign) {
12023 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12024 ErrorInfo.ErrorLoc = BO->getExprLoc();
12025 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12026 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12027 return false;
12028 }
12029
12030 X = BO->getLHS();
12031
12032 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12033 if (!Cond) {
12034 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12035 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12036 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12037 return false;
12038 }
12039
12040 switch (Cond->getOpcode()) {
12041 case BO_EQ: {
12042 C = Cond;
12043 D = BO->getRHS();
12044 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12045 E = Cond->getRHS();
12046 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12047 E = Cond->getLHS();
12048 } else {
12049 ErrorInfo.Error = ErrorTy::InvalidComparison;
12050 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12051 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12052 return false;
12053 }
12054 break;
12055 }
12056 case BO_LT:
12057 case BO_GT: {
12058 E = BO->getRHS();
12059 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
12060 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
12061 C = Cond;
12062 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
12063 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12064 C = Cond;
12065 IsXBinopExpr = false;
12066 } else {
12067 ErrorInfo.Error = ErrorTy::InvalidComparison;
12068 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12069 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12070 return false;
12071 }
12072 break;
12073 }
12074 default:
12075 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12076 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12077 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12078 return false;
12079 }
12080
12081 if (S->getElse()) {
12082 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12083 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
12084 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
12085 return false;
12086 }
12087
12088 return true;
12089}
12090
12091bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
12092 ErrorInfoTy &ErrorInfo) {
12093 auto *BO = dyn_cast<BinaryOperator>(S);
12094 if (!BO) {
12095 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12096 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12097 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12098 return false;
12099 }
12100 if (BO->getOpcode() != BO_Assign) {
12101 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12102 ErrorInfo.ErrorLoc = BO->getExprLoc();
12103 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12104 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12105 return false;
12106 }
12107
12108 X = BO->getLHS();
12109
12110 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
12111 if (!CO) {
12112 ErrorInfo.Error = ErrorTy::NotCondOp;
12113 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12114 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12115 return false;
12116 }
12117
12118 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
12119 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12120 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12121 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12122 CO->getFalseExpr()->getSourceRange();
12123 return false;
12124 }
12125
12126 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
12127 if (!Cond) {
12128 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12129 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12130 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12131 CO->getCond()->getSourceRange();
12132 return false;
12133 }
12134
12135 switch (Cond->getOpcode()) {
12136 case BO_EQ: {
12137 C = Cond;
12138 D = CO->getTrueExpr();
12139 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12140 E = Cond->getRHS();
12141 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12142 E = Cond->getLHS();
12143 } else {
12144 ErrorInfo.Error = ErrorTy::InvalidComparison;
12145 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12146 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12147 return false;
12148 }
12149 break;
12150 }
12151 case BO_LT:
12152 case BO_GT: {
12153 E = CO->getTrueExpr();
12154 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
12155 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
12156 C = Cond;
12157 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
12158 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12159 C = Cond;
12160 IsXBinopExpr = false;
12161 } else {
12162 ErrorInfo.Error = ErrorTy::InvalidComparison;
12163 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12164 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12165 return false;
12166 }
12167 break;
12168 }
12169 default:
12170 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12171 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12172 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12173 return false;
12174 }
12175
12176 return true;
12177}
12178
12179bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
12180 // 'x' and 'e' cannot be nullptr
12181 assert(X && E && "X and E cannot be nullptr");
12182
12183 if (!CheckValue(X, ErrorInfo, true))
12184 return false;
12185
12186 if (!CheckValue(E, ErrorInfo, false))
12187 return false;
12188
12189 if (D && !CheckValue(D, ErrorInfo, false))
12190 return false;
12191
12192 return true;
12193}
12194
12195bool OpenMPAtomicCompareChecker::checkStmt(
12196 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12197 auto *CS = dyn_cast<CompoundStmt>(S);
12198 if (CS) {
12199 if (CS->body_empty()) {
12200 ErrorInfo.Error = ErrorTy::NoStmt;
12201 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12202 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12203 return false;
12204 }
12205
12206 if (CS->size() != 1) {
12207 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12208 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12209 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12210 return false;
12211 }
12212 S = CS->body_front();
12213 }
12214
12215 auto Res = false;
12216
12217 if (auto *IS = dyn_cast<IfStmt>(S)) {
12218 // Check if the statement is in one of the following forms
12219 // (cond-update-stmt):
12220 // if (expr ordop x) { x = expr; }
12221 // if (x ordop expr) { x = expr; }
12222 // if (x == e) { x = d; }
12223 Res = checkCondUpdateStmt(IS, ErrorInfo);
12224 } else {
12225 // Check if the statement is in one of the following forms (cond-expr-stmt):
12226 // x = expr ordop x ? expr : x;
12227 // x = x ordop expr ? expr : x;
12228 // x = x == e ? d : x;
12229 Res = checkCondExprStmt(S, ErrorInfo);
12230 }
12231
12232 if (!Res)
12233 return false;
12234
12235 return checkType(ErrorInfo);
12236}
12237
12238class OpenMPAtomicCompareCaptureChecker final
12239 : public OpenMPAtomicCompareChecker {
12240public:
12241 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12242
12243 Expr *getV() const { return V; }
12244 Expr *getR() const { return R; }
12245 bool isFailOnly() const { return IsFailOnly; }
12246 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12247
12248 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12249 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12250
12251private:
12252 bool checkType(ErrorInfoTy &ErrorInfo);
12253
12254 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12255 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12256 // spec p.p. 82:
12257 // (1) { v = x; cond-update-stmt }
12258 // (2) { cond-update-stmt v = x; }
12259 // (3) if(x == e) { x = d; } else { v = x; }
12260 // (4) { r = x == e; if(r) { x = d; } }
12261 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12262
12263 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12264 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12265
12266 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12267 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12268 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12269
12270 /// 'v' lvalue part of the source atomic expression.
12271 Expr *V = nullptr;
12272 /// 'r' lvalue part of the source atomic expression.
12273 Expr *R = nullptr;
12274 /// If 'v' is only updated when the comparison fails.
12275 bool IsFailOnly = false;
12276 /// If original value of 'x' must be stored in 'v', not an updated one.
12277 bool IsPostfixUpdate = false;
12278};
12279
12280bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12281 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12282 return false;
12283
12284 if (V && !CheckValue(V, ErrorInfo, true))
12285 return false;
12286
12287 if (R && !CheckValue(R, ErrorInfo, true, true))
12288 return false;
12289
12290 return true;
12291}
12292
12293bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12294 ErrorInfoTy &ErrorInfo) {
12295 IsFailOnly = true;
12296
12297 auto *Then = S->getThen();
12298 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12299 if (CS->body_empty()) {
12300 ErrorInfo.Error = ErrorTy::NoStmt;
12301 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12302 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12303 return false;
12304 }
12305 if (CS->size() > 1) {
12306 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12307 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12308 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12309 return false;
12310 }
12311 Then = CS->body_front();
12312 }
12313
12314 auto *BO = dyn_cast<BinaryOperator>(Then);
12315 if (!BO) {
12316 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12317 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12318 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12319 return false;
12320 }
12321 if (BO->getOpcode() != BO_Assign) {
12322 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12323 ErrorInfo.ErrorLoc = BO->getExprLoc();
12324 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12325 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12326 return false;
12327 }
12328
12329 X = BO->getLHS();
12330 D = BO->getRHS();
12331
12332 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12333 if (!Cond) {
12334 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12335 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12336 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12337 return false;
12338 }
12339 if (Cond->getOpcode() != BO_EQ) {
12340 ErrorInfo.Error = ErrorTy::NotEQ;
12341 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12342 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12343 return false;
12344 }
12345
12346 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12347 E = Cond->getRHS();
12348 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12349 E = Cond->getLHS();
12350 } else {
12351 ErrorInfo.Error = ErrorTy::InvalidComparison;
12352 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12353 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12354 return false;
12355 }
12356
12357 C = Cond;
12358
12359 if (!S->getElse()) {
12360 ErrorInfo.Error = ErrorTy::NoElse;
12361 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12362 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12363 return false;
12364 }
12365
12366 auto *Else = S->getElse();
12367 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12368 if (CS->body_empty()) {
12369 ErrorInfo.Error = ErrorTy::NoStmt;
12370 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12371 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12372 return false;
12373 }
12374 if (CS->size() > 1) {
12375 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12376 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12377 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12378 return false;
12379 }
12380 Else = CS->body_front();
12381 }
12382
12383 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12384 if (!ElseBO) {
12385 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12386 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12387 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12388 return false;
12389 }
12390 if (ElseBO->getOpcode() != BO_Assign) {
12391 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12392 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12393 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12394 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12395 return false;
12396 }
12397
12398 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12399 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12400 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12401 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12402 ElseBO->getRHS()->getSourceRange();
12403 return false;
12404 }
12405
12406 V = ElseBO->getLHS();
12407
12408 return checkType(ErrorInfo);
12409}
12410
12411bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12412 ErrorInfoTy &ErrorInfo) {
12413 // We don't check here as they should be already done before call this
12414 // function.
12415 auto *CS = cast<CompoundStmt>(S);
12416 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12417 auto *S1 = cast<BinaryOperator>(CS->body_front());
12418 auto *S2 = cast<IfStmt>(CS->body_back());
12419 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12420
12421 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12422 ErrorInfo.Error = ErrorTy::InvalidCondition;
12423 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12424 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12425 return false;
12426 }
12427
12428 R = S1->getLHS();
12429
12430 auto *Then = S2->getThen();
12431 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12432 if (ThenCS->body_empty()) {
12433 ErrorInfo.Error = ErrorTy::NoStmt;
12434 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12435 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12436 return false;
12437 }
12438 if (ThenCS->size() > 1) {
12439 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12440 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12441 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12442 return false;
12443 }
12444 Then = ThenCS->body_front();
12445 }
12446
12447 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12448 if (!ThenBO) {
12449 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12450 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12451 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12452 return false;
12453 }
12454 if (ThenBO->getOpcode() != BO_Assign) {
12455 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12456 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12457 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12458 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12459 return false;
12460 }
12461
12462 X = ThenBO->getLHS();
12463 D = ThenBO->getRHS();
12464
12465 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12466 if (BO->getOpcode() != BO_EQ) {
12467 ErrorInfo.Error = ErrorTy::NotEQ;
12468 ErrorInfo.ErrorLoc = BO->getExprLoc();
12469 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12470 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12471 return false;
12472 }
12473
12474 C = BO;
12475
12476 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12477 E = BO->getRHS();
12478 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12479 E = BO->getLHS();
12480 } else {
12481 ErrorInfo.Error = ErrorTy::InvalidComparison;
12482 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12483 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12484 return false;
12485 }
12486
12487 if (S2->getElse()) {
12488 IsFailOnly = true;
12489
12490 auto *Else = S2->getElse();
12491 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12492 if (ElseCS->body_empty()) {
12493 ErrorInfo.Error = ErrorTy::NoStmt;
12494 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12495 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12496 return false;
12497 }
12498 if (ElseCS->size() > 1) {
12499 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12500 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12501 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12502 return false;
12503 }
12504 Else = ElseCS->body_front();
12505 }
12506
12507 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12508 if (!ElseBO) {
12509 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12510 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12511 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12512 return false;
12513 }
12514 if (ElseBO->getOpcode() != BO_Assign) {
12515 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12516 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12517 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12518 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12519 return false;
12520 }
12521 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12522 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12523 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12524 ErrorInfo.NoteLoc = X->getExprLoc();
12525 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12526 ErrorInfo.NoteRange = X->getSourceRange();
12527 return false;
12528 }
12529
12530 V = ElseBO->getLHS();
12531 }
12532
12533 return checkType(ErrorInfo);
12534}
12535
12536bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12537 ErrorInfoTy &ErrorInfo) {
12538 // if(x == e) { x = d; } else { v = x; }
12539 if (auto *IS = dyn_cast<IfStmt>(S))
12540 return checkForm3(IS, ErrorInfo);
12541
12542 auto *CS = dyn_cast<CompoundStmt>(S);
12543 if (!CS) {
12544 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12545 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12546 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12547 return false;
12548 }
12549 if (CS->body_empty()) {
12550 ErrorInfo.Error = ErrorTy::NoStmt;
12551 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12552 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12553 return false;
12554 }
12555
12556 // { if(x == e) { x = d; } else { v = x; } }
12557 if (CS->size() == 1) {
12558 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12559 if (!IS) {
12560 ErrorInfo.Error = ErrorTy::NotIfStmt;
12561 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12562 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12563 CS->body_front()->getSourceRange();
12564 return false;
12565 }
12566
12567 return checkForm3(IS, ErrorInfo);
12568 } else if (CS->size() == 2) {
12569 auto *S1 = CS->body_front();
12570 auto *S2 = CS->body_back();
12571
12572 Stmt *UpdateStmt = nullptr;
12573 Stmt *CondUpdateStmt = nullptr;
12574 Stmt *CondExprStmt = nullptr;
12575
12576 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12577 // It could be one of the following cases:
12578 // { v = x; cond-update-stmt }
12579 // { v = x; cond-expr-stmt }
12580 // { cond-expr-stmt; v = x; }
12581 // form 45
12582 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12583 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12584 // check if form 45
12585 if (isa<IfStmt>(S2))
12586 return checkForm45(CS, ErrorInfo);
12587 // { cond-expr-stmt; v = x; }
12588 CondExprStmt = S1;
12589 UpdateStmt = S2;
12590 } else {
12591 IsPostfixUpdate = true;
12592 UpdateStmt = S1;
12593 if (isa<IfStmt>(S2)) {
12594 // { v = x; cond-update-stmt }
12595 CondUpdateStmt = S2;
12596 } else {
12597 // { v = x; cond-expr-stmt }
12598 CondExprStmt = S2;
12599 }
12600 }
12601 } else {
12602 // { cond-update-stmt v = x; }
12603 UpdateStmt = S2;
12604 CondUpdateStmt = S1;
12605 }
12606
12607 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12608 auto *IS = dyn_cast<IfStmt>(CUS);
12609 if (!IS) {
12610 ErrorInfo.Error = ErrorTy::NotIfStmt;
12611 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12612 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12613 return false;
12614 }
12615
12616 return checkCondUpdateStmt(IS, ErrorInfo);
12617 };
12618
12619 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12620 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12621 auto *BO = dyn_cast<BinaryOperator>(US);
12622 if (!BO) {
12623 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12624 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12625 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12626 return false;
12627 }
12628 if (BO->getOpcode() != BO_Assign) {
12629 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12630 ErrorInfo.ErrorLoc = BO->getExprLoc();
12631 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12632 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12633 return false;
12634 }
12635 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12636 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12637 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12638 ErrorInfo.NoteLoc = this->X->getExprLoc();
12639 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12640 ErrorInfo.NoteRange = this->X->getSourceRange();
12641 return false;
12642 }
12643
12644 this->V = BO->getLHS();
12645
12646 return true;
12647 };
12648
12649 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12650 return false;
12651 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12652 return false;
12653 if (!CheckUpdateStmt(UpdateStmt))
12654 return false;
12655 } else {
12656 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12657 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12658 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12659 return false;
12660 }
12661
12662 return checkType(ErrorInfo);
12663}
12664} // namespace
12665
12667 Stmt *AStmt,
12668 SourceLocation StartLoc,
12669 SourceLocation EndLoc) {
12670 // Register location of the first atomic directive.
12671 DSAStack->addAtomicDirectiveLoc(StartLoc);
12672 if (!AStmt)
12673 return StmtError();
12674
12675 // 1.2.2 OpenMP Language Terminology
12676 // Structured block - An executable statement with a single entry at the
12677 // top and a single exit at the bottom.
12678 // The point of exit cannot be a branch out of the structured block.
12679 // longjmp() and throw() must not violate the entry/exit criteria.
12680 OpenMPClauseKind AtomicKind = OMPC_unknown;
12681 SourceLocation AtomicKindLoc;
12682 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12683 SourceLocation MemOrderLoc;
12684 bool MutexClauseEncountered = false;
12685 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12686 for (const OMPClause *C : Clauses) {
12687 switch (C->getClauseKind()) {
12688 case OMPC_read:
12689 case OMPC_write:
12690 case OMPC_update:
12691 MutexClauseEncountered = true;
12692 [[fallthrough]];
12693 case OMPC_capture:
12694 case OMPC_compare: {
12695 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12696 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12697 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12698 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12699 << getOpenMPClauseName(AtomicKind);
12700 } else {
12701 AtomicKind = C->getClauseKind();
12702 AtomicKindLoc = C->getBeginLoc();
12703 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12704 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12705 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12706 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12707 << getOpenMPClauseName(AtomicKind);
12708 }
12709 }
12710 break;
12711 }
12712 case OMPC_weak:
12713 case OMPC_fail: {
12714 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12715 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12716 << getOpenMPClauseName(C->getClauseKind())
12717 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12718 return StmtError();
12719 }
12720 break;
12721 }
12722 case OMPC_seq_cst:
12723 case OMPC_acq_rel:
12724 case OMPC_acquire:
12725 case OMPC_release:
12726 case OMPC_relaxed: {
12727 if (MemOrderKind != OMPC_unknown) {
12728 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12729 << getOpenMPDirectiveName(OMPD_atomic) << 0
12730 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12731 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12732 << getOpenMPClauseName(MemOrderKind);
12733 } else {
12734 MemOrderKind = C->getClauseKind();
12735 MemOrderLoc = C->getBeginLoc();
12736 }
12737 break;
12738 }
12739 // The following clauses are allowed, but we don't need to do anything here.
12740 case OMPC_hint:
12741 break;
12742 default:
12743 llvm_unreachable("unknown clause is encountered");
12744 }
12745 }
12746 bool IsCompareCapture = false;
12747 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12748 EncounteredAtomicKinds.contains(OMPC_capture)) {
12749 IsCompareCapture = true;
12750 AtomicKind = OMPC_compare;
12751 }
12752 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12753 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12754 // release.
12755 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12756 // acquire.
12757 // If atomic-clause is update or not present then memory-order-clause must not
12758 // be acq_rel or acquire.
12759 if ((AtomicKind == OMPC_read &&
12760 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12761 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12762 AtomicKind == OMPC_unknown) &&
12763 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12764 SourceLocation Loc = AtomicKindLoc;
12765 if (AtomicKind == OMPC_unknown)
12766 Loc = StartLoc;
12767 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12768 << getOpenMPClauseName(AtomicKind)
12769 << (AtomicKind == OMPC_unknown ? 1 : 0)
12770 << getOpenMPClauseName(MemOrderKind);
12771 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12772 << getOpenMPClauseName(MemOrderKind);
12773 }
12774
12775 Stmt *Body = AStmt;
12776 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12777 Body = EWC->getSubExpr();
12778
12779 Expr *X = nullptr;
12780 Expr *V = nullptr;
12781 Expr *E = nullptr;
12782 Expr *UE = nullptr;
12783 Expr *D = nullptr;
12784 Expr *CE = nullptr;
12785 Expr *R = nullptr;
12786 bool IsXLHSInRHSPart = false;
12787 bool IsPostfixUpdate = false;
12788 bool IsFailOnly = false;
12789 // OpenMP [2.12.6, atomic Construct]
12790 // In the next expressions:
12791 // * x and v (as applicable) are both l-value expressions with scalar type.
12792 // * During the execution of an atomic region, multiple syntactic
12793 // occurrences of x must designate the same storage location.
12794 // * Neither of v and expr (as applicable) may access the storage location
12795 // designated by x.
12796 // * Neither of x and expr (as applicable) may access the storage location
12797 // designated by v.
12798 // * expr is an expression with scalar type.
12799 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12800 // * binop, binop=, ++, and -- are not overloaded operators.
12801 // * The expression x binop expr must be numerically equivalent to x binop
12802 // (expr). This requirement is satisfied if the operators in expr have
12803 // precedence greater than binop, or by using parentheses around expr or
12804 // subexpressions of expr.
12805 // * The expression expr binop x must be numerically equivalent to (expr)
12806 // binop x. This requirement is satisfied if the operators in expr have
12807 // precedence equal to or greater than binop, or by using parentheses around
12808 // expr or subexpressions of expr.
12809 // * For forms that allow multiple occurrences of x, the number of times
12810 // that x is evaluated is unspecified.
12811 if (AtomicKind == OMPC_read) {
12812 enum {
12813 NotAnExpression,
12814 NotAnAssignmentOp,
12815 NotAScalarType,
12816 NotAnLValue,
12817 NoError
12818 } ErrorFound = NoError;
12819 SourceLocation ErrorLoc, NoteLoc;
12820 SourceRange ErrorRange, NoteRange;
12821 // If clause is read:
12822 // v = x;
12823 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12824 const auto *AtomicBinOp =
12825 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12826 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12827 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12828 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12829 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12830 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12831 if (!X->isLValue() || !V->isLValue()) {
12832 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12833 ErrorFound = NotAnLValue;
12834 ErrorLoc = AtomicBinOp->getExprLoc();
12835 ErrorRange = AtomicBinOp->getSourceRange();
12836 NoteLoc = NotLValueExpr->getExprLoc();
12837 NoteRange = NotLValueExpr->getSourceRange();
12838 }
12839 } else if (!X->isInstantiationDependent() ||
12840 !V->isInstantiationDependent()) {
12841 const Expr *NotScalarExpr =
12842 (X->isInstantiationDependent() || X->getType()->isScalarType())
12843 ? V
12844 : X;
12845 ErrorFound = NotAScalarType;
12846 ErrorLoc = AtomicBinOp->getExprLoc();
12847 ErrorRange = AtomicBinOp->getSourceRange();
12848 NoteLoc = NotScalarExpr->getExprLoc();
12849 NoteRange = NotScalarExpr->getSourceRange();
12850 }
12851 } else if (!AtomicBody->isInstantiationDependent()) {
12852 ErrorFound = NotAnAssignmentOp;
12853 ErrorLoc = AtomicBody->getExprLoc();
12854 ErrorRange = AtomicBody->getSourceRange();
12855 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12856 : AtomicBody->getExprLoc();
12857 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12858 : AtomicBody->getSourceRange();
12859 }
12860 } else {
12861 ErrorFound = NotAnExpression;
12862 NoteLoc = ErrorLoc = Body->getBeginLoc();
12863 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12864 }
12865 if (ErrorFound != NoError) {
12866 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12867 << ErrorRange;
12868 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12869 << ErrorFound << NoteRange;
12870 return StmtError();
12871 }
12873 V = X = nullptr;
12874 } else if (AtomicKind == OMPC_write) {
12875 enum {
12876 NotAnExpression,
12877 NotAnAssignmentOp,
12878 NotAScalarType,
12879 NotAnLValue,
12880 NoError
12881 } ErrorFound = NoError;
12882 SourceLocation ErrorLoc, NoteLoc;
12883 SourceRange ErrorRange, NoteRange;
12884 // If clause is write:
12885 // x = expr;
12886 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12887 const auto *AtomicBinOp =
12888 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12889 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12890 X = AtomicBinOp->getLHS();
12891 E = AtomicBinOp->getRHS();
12892 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12893 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
12894 if (!X->isLValue()) {
12895 ErrorFound = NotAnLValue;
12896 ErrorLoc = AtomicBinOp->getExprLoc();
12897 ErrorRange = AtomicBinOp->getSourceRange();
12898 NoteLoc = X->getExprLoc();
12899 NoteRange = X->getSourceRange();
12900 }
12901 } else if (!X->isInstantiationDependent() ||
12903 const Expr *NotScalarExpr =
12904 (X->isInstantiationDependent() || X->getType()->isScalarType())
12905 ? E
12906 : X;
12907 ErrorFound = NotAScalarType;
12908 ErrorLoc = AtomicBinOp->getExprLoc();
12909 ErrorRange = AtomicBinOp->getSourceRange();
12910 NoteLoc = NotScalarExpr->getExprLoc();
12911 NoteRange = NotScalarExpr->getSourceRange();
12912 }
12913 } else if (!AtomicBody->isInstantiationDependent()) {
12914 ErrorFound = NotAnAssignmentOp;
12915 ErrorLoc = AtomicBody->getExprLoc();
12916 ErrorRange = AtomicBody->getSourceRange();
12917 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12918 : AtomicBody->getExprLoc();
12919 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12920 : AtomicBody->getSourceRange();
12921 }
12922 } else {
12923 ErrorFound = NotAnExpression;
12924 NoteLoc = ErrorLoc = Body->getBeginLoc();
12925 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12926 }
12927 if (ErrorFound != NoError) {
12928 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12929 << ErrorRange;
12930 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12931 << ErrorFound << NoteRange;
12932 return StmtError();
12933 }
12935 E = X = nullptr;
12936 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12937 // If clause is update:
12938 // x++;
12939 // x--;
12940 // ++x;
12941 // --x;
12942 // x binop= expr;
12943 // x = x binop expr;
12944 // x = expr binop x;
12945 OpenMPAtomicUpdateChecker Checker(*this);
12946 if (Checker.checkStatement(
12947 Body,
12948 (AtomicKind == OMPC_update)
12949 ? diag::err_omp_atomic_update_not_expression_statement
12950 : diag::err_omp_atomic_not_expression_statement,
12951 diag::note_omp_atomic_update))
12952 return StmtError();
12954 E = Checker.getExpr();
12955 X = Checker.getX();
12956 UE = Checker.getUpdateExpr();
12957 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12958 }
12959 } else if (AtomicKind == OMPC_capture) {
12960 enum {
12961 NotAnAssignmentOp,
12962 NotACompoundStatement,
12963 NotTwoSubstatements,
12964 NotASpecificExpression,
12965 NoError
12966 } ErrorFound = NoError;
12967 SourceLocation ErrorLoc, NoteLoc;
12968 SourceRange ErrorRange, NoteRange;
12969 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12970 // If clause is a capture:
12971 // v = x++;
12972 // v = x--;
12973 // v = ++x;
12974 // v = --x;
12975 // v = x binop= expr;
12976 // v = x = x binop expr;
12977 // v = x = expr binop x;
12978 const auto *AtomicBinOp =
12979 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12980 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12981 V = AtomicBinOp->getLHS();
12982 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12983 OpenMPAtomicUpdateChecker Checker(*this);
12984 if (Checker.checkStatement(
12985 Body, diag::err_omp_atomic_capture_not_expression_statement,
12986 diag::note_omp_atomic_update))
12987 return StmtError();
12988 E = Checker.getExpr();
12989 X = Checker.getX();
12990 UE = Checker.getUpdateExpr();
12991 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12992 IsPostfixUpdate = Checker.isPostfixUpdate();
12993 } else if (!AtomicBody->isInstantiationDependent()) {
12994 ErrorLoc = AtomicBody->getExprLoc();
12995 ErrorRange = AtomicBody->getSourceRange();
12996 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12997 : AtomicBody->getExprLoc();
12998 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12999 : AtomicBody->getSourceRange();
13000 ErrorFound = NotAnAssignmentOp;
13001 }
13002 if (ErrorFound != NoError) {
13003 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
13004 << ErrorRange;
13005 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13006 return StmtError();
13007 }
13009 UE = V = E = X = nullptr;
13010 } else {
13011 // If clause is a capture:
13012 // { v = x; x = expr; }
13013 // { v = x; x++; }
13014 // { v = x; x--; }
13015 // { v = x; ++x; }
13016 // { v = x; --x; }
13017 // { v = x; x binop= expr; }
13018 // { v = x; x = x binop expr; }
13019 // { v = x; x = expr binop x; }
13020 // { x++; v = x; }
13021 // { x--; v = x; }
13022 // { ++x; v = x; }
13023 // { --x; v = x; }
13024 // { x binop= expr; v = x; }
13025 // { x = x binop expr; v = x; }
13026 // { x = expr binop x; v = x; }
13027 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
13028 // Check that this is { expr1; expr2; }
13029 if (CS->size() == 2) {
13030 Stmt *First = CS->body_front();
13031 Stmt *Second = CS->body_back();
13032 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
13033 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13034 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
13035 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13036 // Need to find what subexpression is 'v' and what is 'x'.
13037 OpenMPAtomicUpdateChecker Checker(*this);
13038 bool IsUpdateExprFound = !Checker.checkStatement(Second);
13039 BinaryOperator *BinOp = nullptr;
13040 if (IsUpdateExprFound) {
13041 BinOp = dyn_cast<BinaryOperator>(First);
13042 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13043 }
13044 if (IsUpdateExprFound && !CurContext->isDependentContext()) {
13045 // { v = x; x++; }
13046 // { v = x; x--; }
13047 // { v = x; ++x; }
13048 // { v = x; --x; }
13049 // { v = x; x binop= expr; }
13050 // { v = x; x = x binop expr; }
13051 // { v = x; x = expr binop x; }
13052 // Check that the first expression has form v = x.
13053 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13054 llvm::FoldingSetNodeID XId, PossibleXId;
13055 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13056 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13057 IsUpdateExprFound = XId == PossibleXId;
13058 if (IsUpdateExprFound) {
13059 V = BinOp->getLHS();
13060 X = Checker.getX();
13061 E = Checker.getExpr();
13062 UE = Checker.getUpdateExpr();
13063 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13064 IsPostfixUpdate = true;
13065 }
13066 }
13067 if (!IsUpdateExprFound) {
13068 IsUpdateExprFound = !Checker.checkStatement(First);
13069 BinOp = nullptr;
13070 if (IsUpdateExprFound) {
13071 BinOp = dyn_cast<BinaryOperator>(Second);
13072 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13073 }
13074 if (IsUpdateExprFound && !CurContext->isDependentContext()) {
13075 // { x++; v = x; }
13076 // { x--; v = x; }
13077 // { ++x; v = x; }
13078 // { --x; v = x; }
13079 // { x binop= expr; v = x; }
13080 // { x = x binop expr; v = x; }
13081 // { x = expr binop x; v = x; }
13082 // Check that the second expression has form v = x.
13083 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13084 llvm::FoldingSetNodeID XId, PossibleXId;
13085 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13086 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13087 IsUpdateExprFound = XId == PossibleXId;
13088 if (IsUpdateExprFound) {
13089 V = BinOp->getLHS();
13090 X = Checker.getX();
13091 E = Checker.getExpr();
13092 UE = Checker.getUpdateExpr();
13093 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13094 IsPostfixUpdate = false;
13095 }
13096 }
13097 }
13098 if (!IsUpdateExprFound) {
13099 // { v = x; x = expr; }
13100 auto *FirstExpr = dyn_cast<Expr>(First);
13101 auto *SecondExpr = dyn_cast<Expr>(Second);
13102 if (!FirstExpr || !SecondExpr ||
13103 !(FirstExpr->isInstantiationDependent() ||
13104 SecondExpr->isInstantiationDependent())) {
13105 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
13106 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13107 ErrorFound = NotAnAssignmentOp;
13108 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13109 : First->getBeginLoc();
13110 NoteRange = ErrorRange = FirstBinOp
13111 ? FirstBinOp->getSourceRange()
13112 : SourceRange(ErrorLoc, ErrorLoc);
13113 } else {
13114 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
13115 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13116 ErrorFound = NotAnAssignmentOp;
13117 NoteLoc = ErrorLoc = SecondBinOp
13118 ? SecondBinOp->getOperatorLoc()
13119 : Second->getBeginLoc();
13120 NoteRange = ErrorRange =
13121 SecondBinOp ? SecondBinOp->getSourceRange()
13122 : SourceRange(ErrorLoc, ErrorLoc);
13123 } else {
13124 Expr *PossibleXRHSInFirst =
13125 FirstBinOp->getRHS()->IgnoreParenImpCasts();
13126 Expr *PossibleXLHSInSecond =
13127 SecondBinOp->getLHS()->IgnoreParenImpCasts();
13128 llvm::FoldingSetNodeID X1Id, X2Id;
13129 PossibleXRHSInFirst->Profile(X1Id, Context,
13130 /*Canonical=*/true);
13131 PossibleXLHSInSecond->Profile(X2Id, Context,
13132 /*Canonical=*/true);
13133 IsUpdateExprFound = X1Id == X2Id;
13134 if (IsUpdateExprFound) {
13135 V = FirstBinOp->getLHS();
13136 X = SecondBinOp->getLHS();
13137 E = SecondBinOp->getRHS();
13138 UE = nullptr;
13139 IsXLHSInRHSPart = false;
13140 IsPostfixUpdate = true;
13141 } else {
13142 ErrorFound = NotASpecificExpression;
13143 ErrorLoc = FirstBinOp->getExprLoc();
13144 ErrorRange = FirstBinOp->getSourceRange();
13145 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13146 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13147 }
13148 }
13149 }
13150 }
13151 }
13152 } else {
13153 NoteLoc = ErrorLoc = Body->getBeginLoc();
13154 NoteRange = ErrorRange =
13155 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13156 ErrorFound = NotTwoSubstatements;
13157 }
13158 } else {
13159 NoteLoc = ErrorLoc = Body->getBeginLoc();
13160 NoteRange = ErrorRange =
13161 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13162 ErrorFound = NotACompoundStatement;
13163 }
13164 }
13165 if (ErrorFound != NoError) {
13166 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
13167 << ErrorRange;
13168 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13169 return StmtError();
13170 }
13172 UE = V = E = X = nullptr;
13173 } else if (AtomicKind == OMPC_compare) {
13174 if (IsCompareCapture) {
13175 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13176 OpenMPAtomicCompareCaptureChecker Checker(*this);
13177 if (!Checker.checkStmt(Body, ErrorInfo)) {
13178 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
13179 << ErrorInfo.ErrorRange;
13180 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13181 << ErrorInfo.Error << ErrorInfo.NoteRange;
13182 return StmtError();
13183 }
13184 X = Checker.getX();
13185 E = Checker.getE();
13186 D = Checker.getD();
13187 CE = Checker.getCond();
13188 V = Checker.getV();
13189 R = Checker.getR();
13190 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13191 IsXLHSInRHSPart = Checker.isXBinopExpr();
13192 IsFailOnly = Checker.isFailOnly();
13193 IsPostfixUpdate = Checker.isPostfixUpdate();
13194 } else {
13195 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13196 OpenMPAtomicCompareChecker Checker(*this);
13197 if (!Checker.checkStmt(Body, ErrorInfo)) {
13198 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
13199 << ErrorInfo.ErrorRange;
13200 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13201 << ErrorInfo.Error << ErrorInfo.NoteRange;
13202 return StmtError();
13203 }
13204 X = Checker.getX();
13205 E = Checker.getE();
13206 D = Checker.getD();
13207 CE = Checker.getCond();
13208 // The weak clause may only appear if the resulting atomic operation is
13209 // an atomic conditional update for which the comparison tests for
13210 // equality. It was not possible to do this check in
13211 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
13212 // could not be performed (Clauses are not available).
13213 auto *It = find_if(Clauses, [](OMPClause *C) {
13214 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13215 });
13216 if (It != Clauses.end()) {
13217 auto *Cond = dyn_cast<BinaryOperator>(CE);
13218 if (Cond->getOpcode() != BO_EQ) {
13219 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13220 ErrorInfo.ErrorLoc = Cond->getExprLoc();
13221 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
13222 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
13223
13224 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
13225 << ErrorInfo.ErrorRange;
13226 return StmtError();
13227 }
13228 }
13229 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13230 IsXLHSInRHSPart = Checker.isXBinopExpr();
13231 }
13232 }
13233
13235
13237 Context, StartLoc, EndLoc, Clauses, AStmt,
13238 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
13239}
13240
13242 Stmt *AStmt,
13243 SourceLocation StartLoc,
13244 SourceLocation EndLoc) {
13245 if (!AStmt)
13246 return StmtError();
13247
13248 auto *CS = cast<CapturedStmt>(AStmt);
13249 // 1.2.2 OpenMP Language Terminology
13250 // Structured block - An executable statement with a single entry at the
13251 // top and a single exit at the bottom.
13252 // The point of exit cannot be a branch out of the structured block.
13253 // longjmp() and throw() must not violate the entry/exit criteria.
13254 CS->getCapturedDecl()->setNothrow();
13255 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target);
13256 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13257 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13258 // 1.2.2 OpenMP Language Terminology
13259 // Structured block - An executable statement with a single entry at the
13260 // top and a single exit at the bottom.
13261 // The point of exit cannot be a branch out of the structured block.
13262 // longjmp() and throw() must not violate the entry/exit criteria.
13263 CS->getCapturedDecl()->setNothrow();
13264 }
13265
13266 // OpenMP [2.16, Nesting of Regions]
13267 // If specified, a teams construct must be contained within a target
13268 // construct. That target construct must contain no statements or directives
13269 // outside of the teams construct.
13270 if (DSAStack->hasInnerTeamsRegion()) {
13271 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13272 bool OMPTeamsFound = true;
13273 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
13274 auto I = CS->body_begin();
13275 while (I != CS->body_end()) {
13276 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13277 if (!OED || !isOpenMPTeamsDirective(OED->getDirectiveKind()) ||
13278 OMPTeamsFound) {
13279
13280 OMPTeamsFound = false;
13281 break;
13282 }
13283 ++I;
13284 }
13285 assert(I != CS->body_end() && "Not found statement");
13286 S = *I;
13287 } else {
13288 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13289 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13290 }
13291 if (!OMPTeamsFound) {
13292 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13293 Diag(DSAStack->getInnerTeamsRegionLoc(),
13294 diag::note_omp_nested_teams_construct_here);
13295 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
13296 << isa<OMPExecutableDirective>(S);
13297 return StmtError();
13298 }
13299 }
13300
13302
13303 return OMPTargetDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
13304}
13305
13308 Stmt *AStmt, SourceLocation StartLoc,
13309 SourceLocation EndLoc) {
13310 if (!AStmt)
13311 return StmtError();
13312
13313 auto *CS = cast<CapturedStmt>(AStmt);
13314 // 1.2.2 OpenMP Language Terminology
13315 // Structured block - An executable statement with a single entry at the
13316 // top and a single exit at the bottom.
13317 // The point of exit cannot be a branch out of the structured block.
13318 // longjmp() and throw() must not violate the entry/exit criteria.
13319 CS->getCapturedDecl()->setNothrow();
13320 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel);
13321 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13322 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13323 // 1.2.2 OpenMP Language Terminology
13324 // Structured block - An executable statement with a single entry at the
13325 // top and a single exit at the bottom.
13326 // The point of exit cannot be a branch out of the structured block.
13327 // longjmp() and throw() must not violate the entry/exit criteria.
13328 CS->getCapturedDecl()->setNothrow();
13329 }
13330
13332
13334 Context, StartLoc, EndLoc, Clauses, AStmt,
13335 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13336}
13337
13339 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13340 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13341 if (!AStmt)
13342 return StmtError();
13343
13344 auto *CS = cast<CapturedStmt>(AStmt);
13345 // 1.2.2 OpenMP Language Terminology
13346 // Structured block - An executable statement with a single entry at the
13347 // top and a single exit at the bottom.
13348 // The point of exit cannot be a branch out of the structured block.
13349 // longjmp() and throw() must not violate the entry/exit criteria.
13350 CS->getCapturedDecl()->setNothrow();
13351 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for);
13352 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13353 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13354 // 1.2.2 OpenMP Language Terminology
13355 // Structured block - An executable statement with a single entry at the
13356 // top and a single exit at the bottom.
13357 // The point of exit cannot be a branch out of the structured block.
13358 // longjmp() and throw() must not violate the entry/exit criteria.
13359 CS->getCapturedDecl()->setNothrow();
13360 }
13361
13363 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13364 // define the nested loops number.
13365 unsigned NestedLoopCount =
13366 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13367 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
13368 VarsWithImplicitDSA, B);
13369 if (NestedLoopCount == 0)
13370 return StmtError();
13371
13372 assert((CurContext->isDependentContext() || B.builtAll()) &&
13373 "omp target parallel for loop exprs were not built");
13374
13376 // Finalize the clauses that need pre-built expressions for CodeGen.
13377 for (OMPClause *C : Clauses) {
13378 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13379 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13380 B.NumIterations, *this, CurScope,
13381 DSAStack))
13382 return StmtError();
13383 }
13384 }
13385
13388 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13389 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13390}
13391
13392/// Check for existence of a map clause in the list of clauses.
13394 const OpenMPClauseKind K) {
13395 return llvm::any_of(
13396 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13397}
13398
13399template <typename... Params>
13401 const Params... ClauseTypes) {
13402 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13403}
13404
13405/// Check if the variables in the mapping clause are externally visible.
13407 for (const OMPClause *C : Clauses) {
13408 if (auto *TC = dyn_cast<OMPToClause>(C))
13409 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13410 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13411 (VD->isExternallyVisible() &&
13412 VD->getVisibility() != HiddenVisibility);
13413 });
13414 else if (auto *FC = dyn_cast<OMPFromClause>(C))
13415 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13416 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13417 (VD->isExternallyVisible() &&
13418 VD->getVisibility() != HiddenVisibility);
13419 });
13420 }
13421
13422 return true;
13423}
13424
13426 Stmt *AStmt,
13427 SourceLocation StartLoc,
13428 SourceLocation EndLoc) {
13429 if (!AStmt)
13430 return StmtError();
13431
13432 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13433
13434 // OpenMP [2.12.2, target data Construct, Restrictions]
13435 // At least one map, use_device_addr or use_device_ptr clause must appear on
13436 // the directive.
13437 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13438 (LangOpts.OpenMP < 50 || !hasClauses(Clauses, OMPC_use_device_addr))) {
13439 StringRef Expected;
13440 if (LangOpts.OpenMP < 50)
13441 Expected = "'map' or 'use_device_ptr'";
13442 else
13443 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13444 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13445 << Expected << getOpenMPDirectiveName(OMPD_target_data);
13446 return StmtError();
13447 }
13448
13450
13451 return OMPTargetDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13452 AStmt);
13453}
13454
13457 SourceLocation StartLoc,
13458 SourceLocation EndLoc, Stmt *AStmt) {
13459 if (!AStmt)
13460 return StmtError();
13461
13462 auto *CS = cast<CapturedStmt>(AStmt);
13463 // 1.2.2 OpenMP Language Terminology
13464 // Structured block - An executable statement with a single entry at the
13465 // top and a single exit at the bottom.
13466 // The point of exit cannot be a branch out of the structured block.
13467 // longjmp() and throw() must not violate the entry/exit criteria.
13468 CS->getCapturedDecl()->setNothrow();
13469 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_enter_data);
13470 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13471 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13472 // 1.2.2 OpenMP Language Terminology
13473 // Structured block - An executable statement with a single entry at the
13474 // top and a single exit at the bottom.
13475 // The point of exit cannot be a branch out of the structured block.
13476 // longjmp() and throw() must not violate the entry/exit criteria.
13477 CS->getCapturedDecl()->setNothrow();
13478 }
13479
13480 // OpenMP [2.10.2, Restrictions, p. 99]
13481 // At least one map clause must appear on the directive.
13482 if (!hasClauses(Clauses, OMPC_map)) {
13483 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13484 << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
13485 return StmtError();
13486 }
13487
13488 return OMPTargetEnterDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13489 AStmt);
13490}
13491
13494 SourceLocation StartLoc,
13495 SourceLocation EndLoc, Stmt *AStmt) {
13496 if (!AStmt)
13497 return StmtError();
13498
13499 auto *CS = cast<CapturedStmt>(AStmt);
13500 // 1.2.2 OpenMP Language Terminology
13501 // Structured block - An executable statement with a single entry at the
13502 // top and a single exit at the bottom.
13503 // The point of exit cannot be a branch out of the structured block.
13504 // longjmp() and throw() must not violate the entry/exit criteria.
13505 CS->getCapturedDecl()->setNothrow();
13506 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_exit_data);
13507 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13508 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13509 // 1.2.2 OpenMP Language Terminology
13510 // Structured block - An executable statement with a single entry at the
13511 // top and a single exit at the bottom.
13512 // The point of exit cannot be a branch out of the structured block.
13513 // longjmp() and throw() must not violate the entry/exit criteria.
13514 CS->getCapturedDecl()->setNothrow();
13515 }
13516
13517 // OpenMP [2.10.3, Restrictions, p. 102]
13518 // At least one map clause must appear on the directive.
13519 if (!hasClauses(Clauses, OMPC_map)) {
13520 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13521 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
13522 return StmtError();
13523 }
13524
13525 return OMPTargetExitDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13526 AStmt);
13527}
13528
13530 SourceLocation StartLoc,
13531 SourceLocation EndLoc,
13532 Stmt *AStmt) {
13533 if (!AStmt)
13534 return StmtError();
13535
13536 auto *CS = cast<CapturedStmt>(AStmt);
13537 // 1.2.2 OpenMP Language Terminology
13538 // Structured block - An executable statement with a single entry at the
13539 // top and a single exit at the bottom.
13540 // The point of exit cannot be a branch out of the structured block.
13541 // longjmp() and throw() must not violate the entry/exit criteria.
13542 CS->getCapturedDecl()->setNothrow();
13543 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_update);
13544 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13545 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13546 // 1.2.2 OpenMP Language Terminology
13547 // Structured block - An executable statement with a single entry at the
13548 // top and a single exit at the bottom.
13549 // The point of exit cannot be a branch out of the structured block.
13550 // longjmp() and throw() must not violate the entry/exit criteria.
13551 CS->getCapturedDecl()->setNothrow();
13552 }
13553
13554 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13555 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13556 return StmtError();
13557 }
13558
13559 if (!isClauseMappable(Clauses)) {
13560 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13561 return StmtError();
13562 }
13563
13564 return OMPTargetUpdateDirective::Create(Context, StartLoc, EndLoc, Clauses,
13565 AStmt);
13566}
13567
13569 Stmt *AStmt, SourceLocation StartLoc,
13570 SourceLocation EndLoc) {
13571 if (!AStmt)
13572 return StmtError();
13573
13574 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13575 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13576 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13577
13578 auto *CS = cast<CapturedStmt>(AStmt);
13579 // 1.2.2 OpenMP Language Terminology
13580 // Structured block - An executable statement with a single entry at the
13581 // top and a single exit at the bottom.
13582 // The point of exit cannot be a branch out of the structured block.
13583 // longjmp() and throw() must not violate the entry/exit criteria.
13584 CS->getCapturedDecl()->setNothrow();
13585
13587
13588 DSAStack->setParentTeamsRegionLoc(StartLoc);
13589
13590 return OMPTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
13591}
13592
13595 SourceLocation EndLoc,
13596 OpenMPDirectiveKind CancelRegion) {
13597 if (DSAStack->isParentNowaitRegion()) {
13598 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13599 return StmtError();
13600 }
13601 if (DSAStack->isParentOrderedRegion()) {
13602 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13603 return StmtError();
13604 }
13605 return OMPCancellationPointDirective::Create(Context, StartLoc, EndLoc,
13606 CancelRegion);
13607}
13608
13610 SourceLocation StartLoc,
13611 SourceLocation EndLoc,
13612 OpenMPDirectiveKind CancelRegion) {
13613 if (DSAStack->isParentNowaitRegion()) {
13614 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13615 return StmtError();
13616 }
13617 if (DSAStack->isParentOrderedRegion()) {
13618 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13619 return StmtError();
13620 }
13621 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13622 return OMPCancelDirective::Create(Context, StartLoc, EndLoc, Clauses,
13623 CancelRegion);
13624}
13625
13627 ArrayRef<OMPClause *> Clauses) {
13628 const OMPClause *ReductionClause = nullptr;
13629 const OMPClause *NogroupClause = nullptr;
13630 for (const OMPClause *C : Clauses) {
13631 if (C->getClauseKind() == OMPC_reduction) {
13632 ReductionClause = C;
13633 if (NogroupClause)
13634 break;
13635 continue;
13636 }
13637 if (C->getClauseKind() == OMPC_nogroup) {
13638 NogroupClause = C;
13639 if (ReductionClause)
13640 break;
13641 continue;
13642 }
13643 }
13644 if (ReductionClause && NogroupClause) {
13645 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13646 << SourceRange(NogroupClause->getBeginLoc(),
13647 NogroupClause->getEndLoc());
13648 return true;
13649 }
13650 return false;
13651}
13652
13654 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13655 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13656 if (!AStmt)
13657 return StmtError();
13658
13659 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13661 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13662 // define the nested loops number.
13663 unsigned NestedLoopCount =
13664 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13665 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13666 VarsWithImplicitDSA, B);
13667 if (NestedLoopCount == 0)
13668 return StmtError();
13669
13670 assert((CurContext->isDependentContext() || B.builtAll()) &&
13671 "omp for loop exprs were not built");
13672
13673 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13674 // The grainsize clause and num_tasks clause are mutually exclusive and may
13675 // not appear on the same taskloop directive.
13676 if (checkMutuallyExclusiveClauses(*this, Clauses,
13677 {OMPC_grainsize, OMPC_num_tasks}))
13678 return StmtError();
13679 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13680 // If a reduction clause is present on the taskloop directive, the nogroup
13681 // clause must not be specified.
13682 if (checkReductionClauseWithNogroup(*this, Clauses))
13683 return StmtError();
13684
13686 return OMPTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13687 NestedLoopCount, Clauses, AStmt, B,
13688 DSAStack->isCancelRegion());
13689}
13690
13692 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13693 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13694 if (!AStmt)
13695 return StmtError();
13696
13697 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13699 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13700 // define the nested loops number.
13701 unsigned NestedLoopCount =
13702 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13703 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13704 VarsWithImplicitDSA, B);
13705 if (NestedLoopCount == 0)
13706 return StmtError();
13707
13708 assert((CurContext->isDependentContext() || B.builtAll()) &&
13709 "omp for loop exprs were not built");
13710
13712 // Finalize the clauses that need pre-built expressions for CodeGen.
13713 for (OMPClause *C : Clauses) {
13714 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13715 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13716 B.NumIterations, *this, CurScope,
13717 DSAStack))
13718 return StmtError();
13719 }
13720 }
13721
13722 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13723 // The grainsize clause and num_tasks clause are mutually exclusive and may
13724 // not appear on the same taskloop directive.
13725 if (checkMutuallyExclusiveClauses(*this, Clauses,
13726 {OMPC_grainsize, OMPC_num_tasks}))
13727 return StmtError();
13728 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13729 // If a reduction clause is present on the taskloop directive, the nogroup
13730 // clause must not be specified.
13731 if (checkReductionClauseWithNogroup(*this, Clauses))
13732 return StmtError();
13733 if (checkSimdlenSafelenSpecified(*this, Clauses))
13734 return StmtError();
13735
13737 return OMPTaskLoopSimdDirective::Create(Context, StartLoc, EndLoc,
13738 NestedLoopCount, Clauses, AStmt, B);
13739}
13740
13742 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13743 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13744 if (!AStmt)
13745 return StmtError();
13746
13747 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13749 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13750 // define the nested loops number.
13751 unsigned NestedLoopCount =
13752 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13753 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13754 VarsWithImplicitDSA, B);
13755 if (NestedLoopCount == 0)
13756 return StmtError();
13757
13758 assert((CurContext->isDependentContext() || B.builtAll()) &&
13759 "omp for loop exprs were not built");
13760
13761 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13762 // The grainsize clause and num_tasks clause are mutually exclusive and may
13763 // not appear on the same taskloop directive.
13764 if (checkMutuallyExclusiveClauses(*this, Clauses,
13765 {OMPC_grainsize, OMPC_num_tasks}))
13766 return StmtError();
13767 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13768 // If a reduction clause is present on the taskloop directive, the nogroup
13769 // clause must not be specified.
13770 if (checkReductionClauseWithNogroup(*this, Clauses))
13771 return StmtError();
13772
13774 return OMPMasterTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13775 NestedLoopCount, Clauses, AStmt, B,
13776 DSAStack->isCancelRegion());
13777}
13778
13780 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13781 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13782 if (!AStmt)
13783 return StmtError();
13784
13785 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13787 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13788 // define the nested loops number.
13789 unsigned NestedLoopCount =
13790 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13791 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13792 VarsWithImplicitDSA, B);
13793 if (NestedLoopCount == 0)
13794 return StmtError();
13795
13796 assert((CurContext->isDependentContext() || B.builtAll()) &&
13797 "omp for loop exprs were not built");
13798
13799 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13800 // The grainsize clause and num_tasks clause are mutually exclusive and may
13801 // not appear on the same taskloop directive.
13802 if (checkMutuallyExclusiveClauses(*this, Clauses,
13803 {OMPC_grainsize, OMPC_num_tasks}))
13804 return StmtError();
13805 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13806 // If a reduction clause is present on the taskloop directive, the nogroup
13807 // clause must not be specified.
13808 if (checkReductionClauseWithNogroup(*this, Clauses))
13809 return StmtError();
13810
13812 return OMPMaskedTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13813 NestedLoopCount, Clauses, AStmt, B,
13814 DSAStack->isCancelRegion());
13815}
13816
13818 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13819 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13820 if (!AStmt)
13821 return StmtError();
13822
13823 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13825 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13826 // define the nested loops number.
13827 unsigned NestedLoopCount =
13828 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13829 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13830 VarsWithImplicitDSA, B);
13831 if (NestedLoopCount == 0)
13832 return StmtError();
13833
13834 assert((CurContext->isDependentContext() || B.builtAll()) &&
13835 "omp for loop exprs were not built");
13836
13838 // Finalize the clauses that need pre-built expressions for CodeGen.
13839 for (OMPClause *C : Clauses) {
13840 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13841 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13842 B.NumIterations, *this, CurScope,
13843 DSAStack))
13844 return StmtError();
13845 }
13846 }
13847
13848 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13849 // The grainsize clause and num_tasks clause are mutually exclusive and may
13850 // not appear on the same taskloop directive.
13851 if (checkMutuallyExclusiveClauses(*this, Clauses,
13852 {OMPC_grainsize, OMPC_num_tasks}))
13853 return StmtError();
13854 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13855 // If a reduction clause is present on the taskloop directive, the nogroup
13856 // clause must not be specified.
13857 if (checkReductionClauseWithNogroup(*this, Clauses))
13858 return StmtError();
13859 if (checkSimdlenSafelenSpecified(*this, Clauses))
13860 return StmtError();
13861
13864 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13865}
13866
13868 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13869 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13870 if (!AStmt)
13871 return StmtError();
13872
13873 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13875 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13876 // define the nested loops number.
13877 unsigned NestedLoopCount =
13878 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13879 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
13880 VarsWithImplicitDSA, B);
13881 if (NestedLoopCount == 0)
13882 return StmtError();
13883
13884 assert((CurContext->isDependentContext() || B.builtAll()) &&
13885 "omp for loop exprs were not built");
13886
13888 // Finalize the clauses that need pre-built expressions for CodeGen.
13889 for (OMPClause *C : Clauses) {
13890 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13891 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13892 B.NumIterations, *this, CurScope,
13893 DSAStack))
13894 return StmtError();
13895 }
13896 }
13897
13898 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13899 // The grainsize clause and num_tasks clause are mutually exclusive and may
13900 // not appear on the same taskloop directive.
13901 if (checkMutuallyExclusiveClauses(*this, Clauses,
13902 {OMPC_grainsize, OMPC_num_tasks}))
13903 return StmtError();
13904 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13905 // If a reduction clause is present on the taskloop directive, the nogroup
13906 // clause must not be specified.
13907 if (checkReductionClauseWithNogroup(*this, Clauses))
13908 return StmtError();
13909 if (checkSimdlenSafelenSpecified(*this, Clauses))
13910 return StmtError();
13911
13914 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13915}
13916
13918 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13919 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13920 if (!AStmt)
13921 return StmtError();
13922
13923 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13924 auto *CS = cast<CapturedStmt>(AStmt);
13925 // 1.2.2 OpenMP Language Terminology
13926 // Structured block - An executable statement with a single entry at the
13927 // top and a single exit at the bottom.
13928 // The point of exit cannot be a branch out of the structured block.
13929 // longjmp() and throw() must not violate the entry/exit criteria.
13930 CS->getCapturedDecl()->setNothrow();
13931 for (int ThisCaptureLevel =
13932 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop);
13933 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13934 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13935 // 1.2.2 OpenMP Language Terminology
13936 // Structured block - An executable statement with a single entry at the
13937 // top and a single exit at the bottom.
13938 // The point of exit cannot be a branch out of the structured block.
13939 // longjmp() and throw() must not violate the entry/exit criteria.
13940 CS->getCapturedDecl()->setNothrow();
13941 }
13942
13944 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13945 // define the nested loops number.
13946 unsigned NestedLoopCount = checkOpenMPLoop(
13947 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13948 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
13949 VarsWithImplicitDSA, B);
13950 if (NestedLoopCount == 0)
13951 return StmtError();
13952
13953 assert((CurContext->isDependentContext() || B.builtAll()) &&
13954 "omp for loop exprs were not built");
13955
13956 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13957 // The grainsize clause and num_tasks clause are mutually exclusive and may
13958 // not appear on the same taskloop directive.
13959 if (checkMutuallyExclusiveClauses(*this, Clauses,
13960 {OMPC_grainsize, OMPC_num_tasks}))
13961 return StmtError();
13962 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13963 // If a reduction clause is present on the taskloop directive, the nogroup
13964 // clause must not be specified.
13965 if (checkReductionClauseWithNogroup(*this, Clauses))
13966 return StmtError();
13967
13970 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13971 DSAStack->isCancelRegion());
13972}
13973
13975 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13976 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13977 if (!AStmt)
13978 return StmtError();
13979
13980 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13981 auto *CS = cast<CapturedStmt>(AStmt);
13982 // 1.2.2 OpenMP Language Terminology
13983 // Structured block - An executable statement with a single entry at the
13984 // top and a single exit at the bottom.
13985 // The point of exit cannot be a branch out of the structured block.
13986 // longjmp() and throw() must not violate the entry/exit criteria.
13987 CS->getCapturedDecl()->setNothrow();
13988 for (int ThisCaptureLevel =
13989 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop);
13990 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13991 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13992 // 1.2.2 OpenMP Language Terminology
13993 // Structured block - An executable statement with a single entry at the
13994 // top and a single exit at the bottom.
13995 // The point of exit cannot be a branch out of the structured block.
13996 // longjmp() and throw() must not violate the entry/exit criteria.
13997 CS->getCapturedDecl()->setNothrow();
13998 }
13999
14001 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14002 // define the nested loops number.
14003 unsigned NestedLoopCount = checkOpenMPLoop(
14004 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
14005 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
14006 VarsWithImplicitDSA, B);
14007 if (NestedLoopCount == 0)
14008 return StmtError();
14009
14010 assert((CurContext->isDependentContext() || B.builtAll()) &&
14011 "omp for loop exprs were not built");
14012
14013 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14014 // The grainsize clause and num_tasks clause are mutually exclusive and may
14015 // not appear on the same taskloop directive.
14016 if (checkMutuallyExclusiveClauses(*this, Clauses,
14017 {OMPC_grainsize, OMPC_num_tasks}))
14018 return StmtError();
14019 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14020 // If a reduction clause is present on the taskloop directive, the nogroup
14021 // clause must not be specified.
14022 if (checkReductionClauseWithNogroup(*this, Clauses))
14023 return StmtError();
14024
14027 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14028 DSAStack->isCancelRegion());
14029}
14030
14032 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14033 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14034 if (!AStmt)
14035 return StmtError();
14036
14037 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14038 auto *CS = cast<CapturedStmt>(AStmt);
14039 // 1.2.2 OpenMP Language Terminology
14040 // Structured block - An executable statement with a single entry at the
14041 // top and a single exit at the bottom.
14042 // The point of exit cannot be a branch out of the structured block.
14043 // longjmp() and throw() must not violate the entry/exit criteria.
14044 CS->getCapturedDecl()->setNothrow();
14045 for (int ThisCaptureLevel =
14046 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop_simd);
14047 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14048 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14049 // 1.2.2 OpenMP Language Terminology
14050 // Structured block - An executable statement with a single entry at the
14051 // top and a single exit at the bottom.
14052 // The point of exit cannot be a branch out of the structured block.
14053 // longjmp() and throw() must not violate the entry/exit criteria.
14054 CS->getCapturedDecl()->setNothrow();
14055 }
14056
14058 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14059 // define the nested loops number.
14060 unsigned NestedLoopCount = checkOpenMPLoop(
14061 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
14062 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
14063 VarsWithImplicitDSA, B);
14064 if (NestedLoopCount == 0)
14065 return StmtError();
14066
14067 assert((CurContext->isDependentContext() || B.builtAll()) &&
14068 "omp for loop exprs were not built");
14069
14071 // Finalize the clauses that need pre-built expressions for CodeGen.
14072 for (OMPClause *C : Clauses) {
14073 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14074 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14075 B.NumIterations, *this, CurScope,
14076 DSAStack))
14077 return StmtError();
14078 }
14079 }
14080
14081 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14082 // The grainsize clause and num_tasks clause are mutually exclusive and may
14083 // not appear on the same taskloop directive.
14084 if (checkMutuallyExclusiveClauses(*this, Clauses,
14085 {OMPC_grainsize, OMPC_num_tasks}))
14086 return StmtError();
14087 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14088 // If a reduction clause is present on the taskloop directive, the nogroup
14089 // clause must not be specified.
14090 if (checkReductionClauseWithNogroup(*this, Clauses))
14091 return StmtError();
14092 if (checkSimdlenSafelenSpecified(*this, Clauses))
14093 return StmtError();
14094
14097 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14098}
14099
14101 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14102 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14103 if (!AStmt)
14104 return StmtError();
14105
14106 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14107 auto *CS = cast<CapturedStmt>(AStmt);
14108 // 1.2.2 OpenMP Language Terminology
14109 // Structured block - An executable statement with a single entry at the
14110 // top and a single exit at the bottom.
14111 // The point of exit cannot be a branch out of the structured block.
14112 // longjmp() and throw() must not violate the entry/exit criteria.
14113 CS->getCapturedDecl()->setNothrow();
14114 for (int ThisCaptureLevel =
14115 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop_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
14127 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14128 // define the nested loops number.
14129 unsigned NestedLoopCount = checkOpenMPLoop(
14130 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
14131 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack,
14132 VarsWithImplicitDSA, B);
14133 if (NestedLoopCount == 0)
14134 return StmtError();
14135
14136 assert((CurContext->isDependentContext() || B.builtAll()) &&
14137 "omp for loop exprs were not built");
14138
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 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14151 // The grainsize clause and num_tasks clause are mutually exclusive and may
14152 // not appear on the same taskloop directive.
14153 if (checkMutuallyExclusiveClauses(*this, Clauses,
14154 {OMPC_grainsize, OMPC_num_tasks}))
14155 return StmtError();
14156 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14157 // If a reduction clause is present on the taskloop directive, the nogroup
14158 // clause must not be specified.
14159 if (checkReductionClauseWithNogroup(*this, Clauses))
14160 return StmtError();
14161 if (checkSimdlenSafelenSpecified(*this, Clauses))
14162 return StmtError();
14163
14166 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14167}
14168
14170 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14171 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14172 if (!AStmt)
14173 return StmtError();
14174
14175 if (!checkLastPrivateForMappedDirectives(Clauses))
14176 return StmtError();
14177
14178 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14180 // In presence of clause 'collapse' with number of loops, it will
14181 // define the nested loops number.
14182 unsigned NestedLoopCount =
14183 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
14184 nullptr /*ordered not a clause on distribute*/, AStmt,
14185 *this, *DSAStack, VarsWithImplicitDSA, B);
14186 if (NestedLoopCount == 0)
14187 return StmtError();
14188
14189 assert((CurContext->isDependentContext() || B.builtAll()) &&
14190 "omp for loop exprs were not built");
14191
14193 auto *DistributeDirective = OMPDistributeDirective::Create(
14194 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14195 DSAStack->getMappedDirective());
14196 return DistributeDirective;
14197}
14198
14200 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14201 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14202 if (!AStmt)
14203 return StmtError();
14204
14205 auto *CS = cast<CapturedStmt>(AStmt);
14206 // 1.2.2 OpenMP Language Terminology
14207 // Structured block - An executable statement with a single entry at the
14208 // top and a single exit at the bottom.
14209 // The point of exit cannot be a branch out of the structured block.
14210 // longjmp() and throw() must not violate the entry/exit criteria.
14211 CS->getCapturedDecl()->setNothrow();
14212 for (int ThisCaptureLevel =
14213 getOpenMPCaptureLevels(OMPD_distribute_parallel_for);
14214 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14215 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14216 // 1.2.2 OpenMP Language Terminology
14217 // Structured block - An executable statement with a single entry at the
14218 // top and a single exit at the bottom.
14219 // The point of exit cannot be a branch out of the structured block.
14220 // longjmp() and throw() must not violate the entry/exit criteria.
14221 CS->getCapturedDecl()->setNothrow();
14222 }
14223
14225 // In presence of clause 'collapse' with number of loops, it will
14226 // define the nested loops number.
14227 unsigned NestedLoopCount = checkOpenMPLoop(
14228 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14229 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14230 VarsWithImplicitDSA, B);
14231 if (NestedLoopCount == 0)
14232 return StmtError();
14233
14234 assert((CurContext->isDependentContext() || B.builtAll()) &&
14235 "omp for loop exprs were not built");
14236
14239 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14240 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14241}
14242
14244 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14245 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14246 if (!AStmt)
14247 return StmtError();
14248
14249 auto *CS = cast<CapturedStmt>(AStmt);
14250 // 1.2.2 OpenMP Language Terminology
14251 // Structured block - An executable statement with a single entry at the
14252 // top and a single exit at the bottom.
14253 // The point of exit cannot be a branch out of the structured block.
14254 // longjmp() and throw() must not violate the entry/exit criteria.
14255 CS->getCapturedDecl()->setNothrow();
14256 for (int ThisCaptureLevel =
14257 getOpenMPCaptureLevels(OMPD_distribute_parallel_for_simd);
14258 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14259 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14260 // 1.2.2 OpenMP Language Terminology
14261 // Structured block - An executable statement with a single entry at the
14262 // top and a single exit at the bottom.
14263 // The point of exit cannot be a branch out of the structured block.
14264 // longjmp() and throw() must not violate the entry/exit criteria.
14265 CS->getCapturedDecl()->setNothrow();
14266 }
14267
14269 // In presence of clause 'collapse' with number of loops, it will
14270 // define the nested loops number.
14271 unsigned NestedLoopCount = checkOpenMPLoop(
14272 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14273 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14274 VarsWithImplicitDSA, B);
14275 if (NestedLoopCount == 0)
14276 return StmtError();
14277
14278 assert((CurContext->isDependentContext() || B.builtAll()) &&
14279 "omp for loop exprs were not built");
14280
14282 // Finalize the clauses that need pre-built expressions for CodeGen.
14283 for (OMPClause *C : Clauses) {
14284 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14285 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14286 B.NumIterations, *this, CurScope,
14287 DSAStack))
14288 return StmtError();
14289 }
14290 }
14291
14292 if (checkSimdlenSafelenSpecified(*this, Clauses))
14293 return StmtError();
14294
14297 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14298}
14299
14301 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14302 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14303 if (!AStmt)
14304 return StmtError();
14305
14306 auto *CS = cast<CapturedStmt>(AStmt);
14307 // 1.2.2 OpenMP Language Terminology
14308 // Structured block - An executable statement with a single entry at the
14309 // top and a single exit at the bottom.
14310 // The point of exit cannot be a branch out of the structured block.
14311 // longjmp() and throw() must not violate the entry/exit criteria.
14312 CS->getCapturedDecl()->setNothrow();
14313 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_distribute_simd);
14314 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14315 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14316 // 1.2.2 OpenMP Language Terminology
14317 // Structured block - An executable statement with a single entry at the
14318 // top and a single exit at the bottom.
14319 // The point of exit cannot be a branch out of the structured block.
14320 // longjmp() and throw() must not violate the entry/exit criteria.
14321 CS->getCapturedDecl()->setNothrow();
14322 }
14323
14325 // In presence of clause 'collapse' with number of loops, it will
14326 // define the nested loops number.
14327 unsigned NestedLoopCount =
14328 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
14329 nullptr /*ordered not a clause on distribute*/, CS, *this,
14330 *DSAStack, VarsWithImplicitDSA, B);
14331 if (NestedLoopCount == 0)
14332 return StmtError();
14333
14334 assert((CurContext->isDependentContext() || B.builtAll()) &&
14335 "omp for loop exprs were not built");
14336
14338 // Finalize the clauses that need pre-built expressions for CodeGen.
14339 for (OMPClause *C : Clauses) {
14340 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14341 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14342 B.NumIterations, *this, CurScope,
14343 DSAStack))
14344 return StmtError();
14345 }
14346 }
14347
14348 if (checkSimdlenSafelenSpecified(*this, Clauses))
14349 return StmtError();
14350
14352 return OMPDistributeSimdDirective::Create(Context, StartLoc, EndLoc,
14353 NestedLoopCount, Clauses, AStmt, B);
14354}
14355
14357 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14358 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14359 if (!AStmt)
14360 return StmtError();
14361
14362 auto *CS = cast<CapturedStmt>(AStmt);
14363 // 1.2.2 OpenMP Language Terminology
14364 // Structured block - An executable statement with a single entry at the
14365 // top and a single exit at the bottom.
14366 // The point of exit cannot be a branch out of the structured block.
14367 // longjmp() and throw() must not violate the entry/exit criteria.
14368 CS->getCapturedDecl()->setNothrow();
14369 for (int ThisCaptureLevel =
14370 getOpenMPCaptureLevels(OMPD_target_parallel_for_simd);
14371 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14372 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14373 // 1.2.2 OpenMP Language Terminology
14374 // Structured block - An executable statement with a single entry at the
14375 // top and a single exit at the bottom.
14376 // The point of exit cannot be a branch out of the structured block.
14377 // longjmp() and throw() must not violate the entry/exit criteria.
14378 CS->getCapturedDecl()->setNothrow();
14379 }
14380
14382 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14383 // define the nested loops number.
14384 unsigned NestedLoopCount = checkOpenMPLoop(
14385 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
14386 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack, VarsWithImplicitDSA,
14387 B);
14388 if (NestedLoopCount == 0)
14389 return StmtError();
14390
14391 assert((CurContext->isDependentContext() || B.builtAll()) &&
14392 "omp target parallel for simd loop exprs were not built");
14393
14395 // Finalize the clauses that need pre-built expressions for CodeGen.
14396 for (OMPClause *C : Clauses) {
14397 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14398 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14399 B.NumIterations, *this, CurScope,
14400 DSAStack))
14401 return StmtError();
14402 }
14403 }
14404 if (checkSimdlenSafelenSpecified(*this, Clauses))
14405 return StmtError();
14406
14409 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14410}
14411
14413 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14414 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14415 if (!AStmt)
14416 return StmtError();
14417
14418 auto *CS = cast<CapturedStmt>(AStmt);
14419 // 1.2.2 OpenMP Language Terminology
14420 // Structured block - An executable statement with a single entry at the
14421 // top and a single exit at the bottom.
14422 // The point of exit cannot be a branch out of the structured block.
14423 // longjmp() and throw() must not violate the entry/exit criteria.
14424 CS->getCapturedDecl()->setNothrow();
14425 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_simd);
14426 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14427 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14428 // 1.2.2 OpenMP Language Terminology
14429 // Structured block - An executable statement with a single entry at the
14430 // top and a single exit at the bottom.
14431 // The point of exit cannot be a branch out of the structured block.
14432 // longjmp() and throw() must not violate the entry/exit criteria.
14433 CS->getCapturedDecl()->setNothrow();
14434 }
14435
14437 // In presence of clause 'collapse' with number of loops, it will define the
14438 // nested loops number.
14439 unsigned NestedLoopCount =
14440 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
14441 getOrderedNumberExpr(Clauses), CS, *this, *DSAStack,
14442 VarsWithImplicitDSA, B);
14443 if (NestedLoopCount == 0)
14444 return StmtError();
14445
14446 assert((CurContext->isDependentContext() || B.builtAll()) &&
14447 "omp target simd loop exprs were not built");
14448
14450 // Finalize the clauses that need pre-built expressions for CodeGen.
14451 for (OMPClause *C : Clauses) {
14452 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14453 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14454 B.NumIterations, *this, CurScope,
14455 DSAStack))
14456 return StmtError();
14457 }
14458 }
14459
14460 if (checkSimdlenSafelenSpecified(*this, Clauses))
14461 return StmtError();
14462
14464 return OMPTargetSimdDirective::Create(Context, StartLoc, EndLoc,
14465 NestedLoopCount, Clauses, AStmt, B);
14466}
14467
14469 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14470 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14471 if (!AStmt)
14472 return StmtError();
14473
14474 auto *CS = cast<CapturedStmt>(AStmt);
14475 // 1.2.2 OpenMP Language Terminology
14476 // Structured block - An executable statement with a single entry at the
14477 // top and a single exit at the bottom.
14478 // The point of exit cannot be a branch out of the structured block.
14479 // longjmp() and throw() must not violate the entry/exit criteria.
14480 CS->getCapturedDecl()->setNothrow();
14481 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_distribute);
14482 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14483 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14484 // 1.2.2 OpenMP Language Terminology
14485 // Structured block - An executable statement with a single entry at the
14486 // top and a single exit at the bottom.
14487 // The point of exit cannot be a branch out of the structured block.
14488 // longjmp() and throw() must not violate the entry/exit criteria.
14489 CS->getCapturedDecl()->setNothrow();
14490 }
14491
14493 // In presence of clause 'collapse' with number of loops, it will
14494 // define the nested loops number.
14495 unsigned NestedLoopCount =
14496 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
14497 nullptr /*ordered not a clause on distribute*/, CS, *this,
14498 *DSAStack, VarsWithImplicitDSA, B);
14499 if (NestedLoopCount == 0)
14500 return StmtError();
14501
14502 assert((CurContext->isDependentContext() || B.builtAll()) &&
14503 "omp teams distribute loop exprs were not built");
14504
14506
14507 DSAStack->setParentTeamsRegionLoc(StartLoc);
14508
14510 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14511}
14512
14514 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14515 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14516 if (!AStmt)
14517 return StmtError();
14518
14519 auto *CS = cast<CapturedStmt>(AStmt);
14520 // 1.2.2 OpenMP Language Terminology
14521 // Structured block - An executable statement with a single entry at the
14522 // top and a single exit at the bottom.
14523 // The point of exit cannot be a branch out of the structured block.
14524 // longjmp() and throw() must not violate the entry/exit criteria.
14525 CS->getCapturedDecl()->setNothrow();
14526 for (int ThisCaptureLevel =
14527 getOpenMPCaptureLevels(OMPD_teams_distribute_simd);
14528 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14529 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14530 // 1.2.2 OpenMP Language Terminology
14531 // Structured block - An executable statement with a single entry at the
14532 // top and a single exit at the bottom.
14533 // The point of exit cannot be a branch out of the structured block.
14534 // longjmp() and throw() must not violate the entry/exit criteria.
14535 CS->getCapturedDecl()->setNothrow();
14536 }
14537
14539 // In presence of clause 'collapse' with number of loops, it will
14540 // define the nested loops number.
14541 unsigned NestedLoopCount = checkOpenMPLoop(
14542 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14543 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14544 VarsWithImplicitDSA, B);
14545
14546 if (NestedLoopCount == 0)
14547 return StmtError();
14548
14549 assert((CurContext->isDependentContext() || B.builtAll()) &&
14550 "omp teams distribute simd loop exprs were not built");
14551
14553 // Finalize the clauses that need pre-built expressions for CodeGen.
14554 for (OMPClause *C : Clauses) {
14555 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14556 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14557 B.NumIterations, *this, CurScope,
14558 DSAStack))
14559 return StmtError();
14560 }
14561 }
14562
14563 if (checkSimdlenSafelenSpecified(*this, Clauses))
14564 return StmtError();
14565
14567
14568 DSAStack->setParentTeamsRegionLoc(StartLoc);
14569
14571 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14572}
14573
14575 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14576 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14577 if (!AStmt)
14578 return StmtError();
14579
14580 auto *CS = cast<CapturedStmt>(AStmt);
14581 // 1.2.2 OpenMP Language Terminology
14582 // Structured block - An executable statement with a single entry at the
14583 // top and a single exit at the bottom.
14584 // The point of exit cannot be a branch out of the structured block.
14585 // longjmp() and throw() must not violate the entry/exit criteria.
14586 CS->getCapturedDecl()->setNothrow();
14587
14588 for (int ThisCaptureLevel =
14589 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for_simd);
14590 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14591 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14592 // 1.2.2 OpenMP Language Terminology
14593 // Structured block - An executable statement with a single entry at the
14594 // top and a single exit at the bottom.
14595 // The point of exit cannot be a branch out of the structured block.
14596 // longjmp() and throw() must not violate the entry/exit criteria.
14597 CS->getCapturedDecl()->setNothrow();
14598 }
14599
14601 // In presence of clause 'collapse' with number of loops, it will
14602 // define the nested loops number.
14603 unsigned NestedLoopCount = checkOpenMPLoop(
14604 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14605 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14606 VarsWithImplicitDSA, B);
14607
14608 if (NestedLoopCount == 0)
14609 return StmtError();
14610
14611 assert((CurContext->isDependentContext() || B.builtAll()) &&
14612 "omp for loop exprs were not built");
14613
14615 // Finalize the clauses that need pre-built expressions for CodeGen.
14616 for (OMPClause *C : Clauses) {
14617 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14618 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14619 B.NumIterations, *this, CurScope,
14620 DSAStack))
14621 return StmtError();
14622 }
14623 }
14624
14625 if (checkSimdlenSafelenSpecified(*this, Clauses))
14626 return StmtError();
14627
14629
14630 DSAStack->setParentTeamsRegionLoc(StartLoc);
14631
14633 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14634}
14635
14637 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14638 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14639 if (!AStmt)
14640 return StmtError();
14641
14642 auto *CS = cast<CapturedStmt>(AStmt);
14643 // 1.2.2 OpenMP Language Terminology
14644 // Structured block - An executable statement with a single entry at the
14645 // top and a single exit at the bottom.
14646 // The point of exit cannot be a branch out of the structured block.
14647 // longjmp() and throw() must not violate the entry/exit criteria.
14648 CS->getCapturedDecl()->setNothrow();
14649
14650 for (int ThisCaptureLevel =
14651 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for);
14652 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14653 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14654 // 1.2.2 OpenMP Language Terminology
14655 // Structured block - An executable statement with a single entry at the
14656 // top and a single exit at the bottom.
14657 // The point of exit cannot be a branch out of the structured block.
14658 // longjmp() and throw() must not violate the entry/exit criteria.
14659 CS->getCapturedDecl()->setNothrow();
14660 }
14661
14663 // In presence of clause 'collapse' with number of loops, it will
14664 // define the nested loops number.
14665 unsigned NestedLoopCount = checkOpenMPLoop(
14666 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14667 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14668 VarsWithImplicitDSA, B);
14669
14670 if (NestedLoopCount == 0)
14671 return StmtError();
14672
14673 assert((CurContext->isDependentContext() || B.builtAll()) &&
14674 "omp for loop exprs were not built");
14675
14677
14678 DSAStack->setParentTeamsRegionLoc(StartLoc);
14679
14681 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14682 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14683}
14684
14686 Stmt *AStmt,
14687 SourceLocation StartLoc,
14688 SourceLocation EndLoc) {
14689 if (!AStmt)
14690 return StmtError();
14691
14692 auto *CS = cast<CapturedStmt>(AStmt);
14693 // 1.2.2 OpenMP Language Terminology
14694 // Structured block - An executable statement with a single entry at the
14695 // top and a single exit at the bottom.
14696 // The point of exit cannot be a branch out of the structured block.
14697 // longjmp() and throw() must not violate the entry/exit criteria.
14698 CS->getCapturedDecl()->setNothrow();
14699
14700 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams);
14701 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14702 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14703 // 1.2.2 OpenMP Language Terminology
14704 // Structured block - An executable statement with a single entry at the
14705 // top and a single exit at the bottom.
14706 // The point of exit cannot be a branch out of the structured block.
14707 // longjmp() and throw() must not violate the entry/exit criteria.
14708 CS->getCapturedDecl()->setNothrow();
14709 }
14711
14712 const OMPClause *BareClause = nullptr;
14713 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) &&
14714 hasClauses(Clauses, OMPC_thread_limit);
14715 bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) {
14716 BareClause = C;
14717 return C->getClauseKind() == OMPC_ompx_bare;
14718 });
14719
14720 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14721 Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
14722 return StmtError();
14723 }
14724
14725 return OMPTargetTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses,
14726 AStmt);
14727}
14728
14730 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14731 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14732 if (!AStmt)
14733 return StmtError();
14734
14735 auto *CS = cast<CapturedStmt>(AStmt);
14736 // 1.2.2 OpenMP Language Terminology
14737 // Structured block - An executable statement with a single entry at the
14738 // top and a single exit at the bottom.
14739 // The point of exit cannot be a branch out of the structured block.
14740 // longjmp() and throw() must not violate the entry/exit criteria.
14741 CS->getCapturedDecl()->setNothrow();
14742 for (int ThisCaptureLevel =
14743 getOpenMPCaptureLevels(OMPD_target_teams_distribute);
14744 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14745 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14746 // 1.2.2 OpenMP Language Terminology
14747 // Structured block - An executable statement with a single entry at the
14748 // top and a single exit at the bottom.
14749 // The point of exit cannot be a branch out of the structured block.
14750 // longjmp() and throw() must not violate the entry/exit criteria.
14751 CS->getCapturedDecl()->setNothrow();
14752 }
14753
14755 // In presence of clause 'collapse' with number of loops, it will
14756 // define the nested loops number.
14757 unsigned NestedLoopCount = checkOpenMPLoop(
14758 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14759 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14760 VarsWithImplicitDSA, B);
14761 if (NestedLoopCount == 0)
14762 return StmtError();
14763
14764 assert((CurContext->isDependentContext() || B.builtAll()) &&
14765 "omp target teams distribute loop exprs were not built");
14766
14769 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14770}
14771
14773 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14774 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14775 if (!AStmt)
14776 return StmtError();
14777
14778 auto *CS = cast<CapturedStmt>(AStmt);
14779 // 1.2.2 OpenMP Language Terminology
14780 // Structured block - An executable statement with a single entry at the
14781 // top and a single exit at the bottom.
14782 // The point of exit cannot be a branch out of the structured block.
14783 // longjmp() and throw() must not violate the entry/exit criteria.
14784 CS->getCapturedDecl()->setNothrow();
14785 for (int ThisCaptureLevel =
14786 getOpenMPCaptureLevels(OMPD_target_teams_distribute_parallel_for);
14787 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14788 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14789 // 1.2.2 OpenMP Language Terminology
14790 // Structured block - An executable statement with a single entry at the
14791 // top and a single exit at the bottom.
14792 // The point of exit cannot be a branch out of the structured block.
14793 // longjmp() and throw() must not violate the entry/exit criteria.
14794 CS->getCapturedDecl()->setNothrow();
14795 }
14796
14798 // In presence of clause 'collapse' with number of loops, it will
14799 // define the nested loops number.
14800 unsigned NestedLoopCount = checkOpenMPLoop(
14801 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14802 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14803 VarsWithImplicitDSA, B);
14804 if (NestedLoopCount == 0)
14805 return StmtError();
14806
14807 assert((CurContext->isDependentContext() || B.builtAll()) &&
14808 "omp target teams distribute parallel for loop exprs were not built");
14809
14811 // Finalize the clauses that need pre-built expressions for CodeGen.
14812 for (OMPClause *C : Clauses) {
14813 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14814 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14815 B.NumIterations, *this, CurScope,
14816 DSAStack))
14817 return StmtError();
14818 }
14819 }
14820
14823 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14824 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14825}
14826
14828 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14829 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14830 if (!AStmt)
14831 return StmtError();
14832
14833 auto *CS = cast<CapturedStmt>(AStmt);
14834 // 1.2.2 OpenMP Language Terminology
14835 // Structured block - An executable statement with a single entry at the
14836 // top and a single exit at the bottom.
14837 // The point of exit cannot be a branch out of the structured block.
14838 // longjmp() and throw() must not violate the entry/exit criteria.
14839 CS->getCapturedDecl()->setNothrow();
14840 for (int ThisCaptureLevel = getOpenMPCaptureLevels(
14841 OMPD_target_teams_distribute_parallel_for_simd);
14842 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14843 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14844 // 1.2.2 OpenMP Language Terminology
14845 // Structured block - An executable statement with a single entry at the
14846 // top and a single exit at the bottom.
14847 // The point of exit cannot be a branch out of the structured block.
14848 // longjmp() and throw() must not violate the entry/exit criteria.
14849 CS->getCapturedDecl()->setNothrow();
14850 }
14851
14853 // In presence of clause 'collapse' with number of loops, it will
14854 // define the nested loops number.
14855 unsigned NestedLoopCount =
14856 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14857 getCollapseNumberExpr(Clauses),
14858 nullptr /*ordered not a clause on distribute*/, CS, *this,
14859 *DSAStack, VarsWithImplicitDSA, B);
14860 if (NestedLoopCount == 0)
14861 return StmtError();
14862
14863 assert((CurContext->isDependentContext() || B.builtAll()) &&
14864 "omp target teams distribute parallel for simd loop exprs were not "
14865 "built");
14866
14868 // Finalize the clauses that need pre-built expressions for CodeGen.
14869 for (OMPClause *C : Clauses) {
14870 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14871 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14872 B.NumIterations, *this, CurScope,
14873 DSAStack))
14874 return StmtError();
14875 }
14876 }
14877
14878 if (checkSimdlenSafelenSpecified(*this, Clauses))
14879 return StmtError();
14880
14883 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14884}
14885
14887 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14888 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14889 if (!AStmt)
14890 return StmtError();
14891
14892 auto *CS = cast<CapturedStmt>(AStmt);
14893 // 1.2.2 OpenMP Language Terminology
14894 // Structured block - An executable statement with a single entry at the
14895 // top and a single exit at the bottom.
14896 // The point of exit cannot be a branch out of the structured block.
14897 // longjmp() and throw() must not violate the entry/exit criteria.
14898 CS->getCapturedDecl()->setNothrow();
14899 for (int ThisCaptureLevel =
14900 getOpenMPCaptureLevels(OMPD_target_teams_distribute_simd);
14901 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14902 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14903 // 1.2.2 OpenMP Language Terminology
14904 // Structured block - An executable statement with a single entry at the
14905 // top and a single exit at the bottom.
14906 // The point of exit cannot be a branch out of the structured block.
14907 // longjmp() and throw() must not violate the entry/exit criteria.
14908 CS->getCapturedDecl()->setNothrow();
14909 }
14910
14912 // In presence of clause 'collapse' with number of loops, it will
14913 // define the nested loops number.
14914 unsigned NestedLoopCount = checkOpenMPLoop(
14915 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14916 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStack,
14917 VarsWithImplicitDSA, B);
14918 if (NestedLoopCount == 0)
14919 return StmtError();
14920
14921 assert((CurContext->isDependentContext() || B.builtAll()) &&
14922 "omp target teams distribute simd loop exprs were not built");
14923
14925 // Finalize the clauses that need pre-built expressions for CodeGen.
14926 for (OMPClause *C : Clauses) {
14927 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14928 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14929 B.NumIterations, *this, CurScope,
14930 DSAStack))
14931 return StmtError();
14932 }
14933 }
14934
14935 if (checkSimdlenSafelenSpecified(*this, Clauses))
14936 return StmtError();
14937
14940 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14941}
14942
14943bool Sema::checkTransformableLoopNest(
14944 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14946 Stmt *&Body,
14947 SmallVectorImpl<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>>
14948 &OriginalInits) {
14949 OriginalInits.emplace_back();
14951 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14952 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14953 Stmt *CurStmt) {
14954 VarsWithInheritedDSAType TmpDSA;
14955 unsigned SingleNumLoops =
14956 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, *this, *DSAStack,
14957 TmpDSA, LoopHelpers[Cnt]);
14958 if (SingleNumLoops == 0)
14959 return true;
14960 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14961 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14962 OriginalInits.back().push_back(For->getInit());
14963 Body = For->getBody();
14964 } else {
14965 assert(isa<CXXForRangeStmt>(CurStmt) &&
14966 "Expected canonical for or range-based for loops.");
14967 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14968 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14969 Body = CXXFor->getBody();
14970 }
14971 OriginalInits.emplace_back();
14972 return false;
14973 },
14974 [&OriginalInits](OMPLoopBasedDirective *Transform) {
14975 Stmt *DependentPreInits;
14976 if (auto *Dir = dyn_cast<OMPTileDirective>(Transform))
14977 DependentPreInits = Dir->getPreInits();
14978 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
14979 DependentPreInits = Dir->getPreInits();
14980 else
14981 llvm_unreachable("Unhandled loop transformation");
14982 if (!DependentPreInits)
14983 return;
14984 llvm::append_range(OriginalInits.back(),
14985 cast<DeclStmt>(DependentPreInits)->getDeclGroup());
14986 });
14987 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14988 OriginalInits.pop_back();
14989 return Result;
14990}
14991
14993 Stmt *AStmt, SourceLocation StartLoc,
14994 SourceLocation EndLoc) {
14995 auto SizesClauses =
14996 OMPExecutableDirective::getClausesOfKind<OMPSizesClause>(Clauses);
14997 if (SizesClauses.empty()) {
14998 // A missing 'sizes' clause is already reported by the parser.
14999 return StmtError();
15000 }
15001 const OMPSizesClause *SizesClause = *SizesClauses.begin();
15002 unsigned NumLoops = SizesClause->getNumSizes();
15003
15004 // Empty statement should only be possible if there already was an error.
15005 if (!AStmt)
15006 return StmtError();
15007
15008 // Verify and diagnose loop nest.
15010 Stmt *Body = nullptr;
15012 OriginalInits;
15013 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
15014 OriginalInits))
15015 return StmtError();
15016
15017 // Delay tiling to when template is completely instantiated.
15019 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
15020 NumLoops, AStmt, nullptr, nullptr);
15021
15022 SmallVector<Decl *, 4> PreInits;
15023
15024 // Create iteration variables for the generated loops.
15025 SmallVector<VarDecl *, 4> FloorIndVars;
15026 SmallVector<VarDecl *, 4> TileIndVars;
15027 FloorIndVars.resize(NumLoops);
15028 TileIndVars.resize(NumLoops);
15029 for (unsigned I = 0; I < NumLoops; ++I) {
15030 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15031
15032 assert(LoopHelper.Counters.size() == 1 &&
15033 "Expect single-dimensional loop iteration space");
15034 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15035 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15036 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15037 QualType CntTy = IterVarRef->getType();
15038
15039 // Iteration variable for the floor (i.e. outer) loop.
15040 {
15041 std::string FloorCntName =
15042 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15043 VarDecl *FloorCntDecl =
15044 buildVarDecl(*this, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
15045 FloorIndVars[I] = FloorCntDecl;
15046 }
15047
15048 // Iteration variable for the tile (i.e. inner) loop.
15049 {
15050 std::string TileCntName =
15051 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15052
15053 // Reuse the iteration variable created by checkOpenMPLoop. It is also
15054 // used by the expressions to derive the original iteration variable's
15055 // value from the logical iteration number.
15056 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15057 TileCntDecl->setDeclName(&PP.getIdentifierTable().get(TileCntName));
15058 TileIndVars[I] = TileCntDecl;
15059 }
15060 for (auto &P : OriginalInits[I]) {
15061 if (auto *D = P.dyn_cast<Decl *>())
15062 PreInits.push_back(D);
15063 else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
15064 PreInits.append(PI->decl_begin(), PI->decl_end());
15065 }
15066 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
15067 PreInits.append(PI->decl_begin(), PI->decl_end());
15068 // Gather declarations for the data members used as counters.
15069 for (Expr *CounterRef : LoopHelper.Counters) {
15070 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
15071 if (isa<OMPCapturedExprDecl>(CounterDecl))
15072 PreInits.push_back(CounterDecl);
15073 }
15074 }
15075
15076 // Once the original iteration values are set, append the innermost body.
15077 Stmt *Inner = Body;
15078
15079 // Create tile loops from the inside to the outside.
15080 for (int I = NumLoops - 1; I >= 0; --I) {
15081 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15082 Expr *NumIterations = LoopHelper.NumIterations;
15083 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15084 QualType CntTy = OrigCntVar->getType();
15085 Expr *DimTileSize = SizesClause->getSizesRefs()[I];
15086 Scope *CurScope = getCurScope();
15087
15088 // Commonly used variables.
15089 DeclRefExpr *TileIV = buildDeclRefExpr(*this, TileIndVars[I], CntTy,
15090 OrigCntVar->getExprLoc());
15091 DeclRefExpr *FloorIV = buildDeclRefExpr(*this, FloorIndVars[I], CntTy,
15092 OrigCntVar->getExprLoc());
15093
15094 // For init-statement: auto .tile.iv = .floor.iv
15095 AddInitializerToDecl(TileIndVars[I], DefaultLvalueConversion(FloorIV).get(),
15096 /*DirectInit=*/false);
15097 Decl *CounterDecl = TileIndVars[I];
15098 StmtResult InitStmt = new (Context)
15099 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15100 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15101 if (!InitStmt.isUsable())
15102 return StmtError();
15103
15104 // For cond-expression: .tile.iv < min(.floor.iv + DimTileSize,
15105 // NumIterations)
15106 ExprResult EndOfTile = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15107 BO_Add, FloorIV, DimTileSize);
15108 if (!EndOfTile.isUsable())
15109 return StmtError();
15110 ExprResult IsPartialTile =
15111 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15112 NumIterations, EndOfTile.get());
15113 if (!IsPartialTile.isUsable())
15114 return StmtError();
15115 ExprResult MinTileAndIterSpace = ActOnConditionalOp(
15116 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15117 IsPartialTile.get(), NumIterations, EndOfTile.get());
15118 if (!MinTileAndIterSpace.isUsable())
15119 return StmtError();
15120 ExprResult CondExpr = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15121 BO_LT, TileIV, MinTileAndIterSpace.get());
15122 if (!CondExpr.isUsable())
15123 return StmtError();
15124
15125 // For incr-statement: ++.tile.iv
15126 ExprResult IncrStmt =
15127 BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, TileIV);
15128 if (!IncrStmt.isUsable())
15129 return StmtError();
15130
15131 // Statements to set the original iteration variable's value from the
15132 // logical iteration number.
15133 // Generated for loop is:
15134 // Original_for_init;
15135 // for (auto .tile.iv = .floor.iv; .tile.iv < min(.floor.iv + DimTileSize,
15136 // NumIterations); ++.tile.iv) {
15137 // Original_Body;
15138 // Original_counter_update;
15139 // }
15140 // FIXME: If the innermost body is an loop itself, inserting these
15141 // statements stops it being recognized as a perfectly nested loop (e.g.
15142 // for applying tiling again). If this is the case, sink the expressions
15143 // further into the inner loop.
15144 SmallVector<Stmt *, 4> BodyParts;
15145 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15146 BodyParts.push_back(Inner);
15147 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15148 Inner->getBeginLoc(), Inner->getEndLoc());
15149 Inner = new (Context)
15150 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15151 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15152 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15153 }
15154
15155 // Create floor loops from the inside to the outside.
15156 for (int I = NumLoops - 1; I >= 0; --I) {
15157 auto &LoopHelper = LoopHelpers[I];
15158 Expr *NumIterations = LoopHelper.NumIterations;
15159 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15160 QualType CntTy = OrigCntVar->getType();
15161 Expr *DimTileSize = SizesClause->getSizesRefs()[I];
15162 Scope *CurScope = getCurScope();
15163
15164 // Commonly used variables.
15165 DeclRefExpr *FloorIV = buildDeclRefExpr(*this, FloorIndVars[I], CntTy,
15166 OrigCntVar->getExprLoc());
15167
15168 // For init-statement: auto .floor.iv = 0
15170 FloorIndVars[I],
15171 ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15172 /*DirectInit=*/false);
15173 Decl *CounterDecl = FloorIndVars[I];
15174 StmtResult InitStmt = new (Context)
15175 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15176 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15177 if (!InitStmt.isUsable())
15178 return StmtError();
15179
15180 // For cond-expression: .floor.iv < NumIterations
15181 ExprResult CondExpr = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15182 BO_LT, FloorIV, NumIterations);
15183 if (!CondExpr.isUsable())
15184 return StmtError();
15185
15186 // For incr-statement: .floor.iv += DimTileSize
15187 ExprResult IncrStmt = BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(),
15188 BO_AddAssign, FloorIV, DimTileSize);
15189 if (!IncrStmt.isUsable())
15190 return StmtError();
15191
15192 Inner = new (Context)
15193 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15194 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15195 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15196 }
15197
15198 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
15199 AStmt, Inner,
15200 buildPreInits(Context, PreInits));
15201}
15202
15204 Stmt *AStmt,
15205 SourceLocation StartLoc,
15206 SourceLocation EndLoc) {
15207 // Empty statement should only be possible if there already was an error.
15208 if (!AStmt)
15209 return StmtError();
15210
15211 if (checkMutuallyExclusiveClauses(*this, Clauses, {OMPC_partial, OMPC_full}))
15212 return StmtError();
15213
15214 const OMPFullClause *FullClause =
15215 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15216 const OMPPartialClause *PartialClause =
15217 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15218 assert(!(FullClause && PartialClause) &&
15219 "mutual exclusivity must have been checked before");
15220
15221 constexpr unsigned NumLoops = 1;
15222 Stmt *Body = nullptr;
15224 NumLoops);
15226 OriginalInits;
15227 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15228 Body, OriginalInits))
15229 return StmtError();
15230
15231 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
15232
15233 // Delay unrolling to when template is completely instantiated.
15235 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15236 NumGeneratedLoops, nullptr, nullptr);
15237
15238 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15239
15240 if (FullClause) {
15242 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
15243 /*SuppressExprDiags=*/true)
15244 .isUsable()) {
15245 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
15246 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
15247 << "#pragma omp unroll full";
15248 return StmtError();
15249 }
15250 }
15251
15252 // The generated loop may only be passed to other loop-associated directive
15253 // when a partial clause is specified. Without the requirement it is
15254 // sufficient to generate loop unroll metadata at code-generation.
15255 if (NumGeneratedLoops == 0)
15256 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15257 NumGeneratedLoops, nullptr, nullptr);
15258
15259 // Otherwise, we need to provide a de-sugared/transformed AST that can be
15260 // associated with another loop directive.
15261 //
15262 // The canonical loop analysis return by checkTransformableLoopNest assumes
15263 // the following structure to be the same loop without transformations or
15264 // directives applied: \code OriginalInits; LoopHelper.PreInits;
15265 // LoopHelper.Counters;
15266 // for (; IV < LoopHelper.NumIterations; ++IV) {
15267 // LoopHelper.Updates;
15268 // Body;
15269 // }
15270 // \endcode
15271 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
15272 // and referenced by LoopHelper.IterationVarRef.
15273 //
15274 // The unrolling directive transforms this into the following loop:
15275 // \code
15276 // OriginalInits; \
15277 // LoopHelper.PreInits; > NewPreInits
15278 // LoopHelper.Counters; /
15279 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
15280 // #pragma clang loop unroll_count(Factor)
15281 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
15282 // {
15283 // LoopHelper.Updates;
15284 // Body;
15285 // }
15286 // }
15287 // \endcode
15288 // where UIV is a new logical iteration counter. IV must be the same VarDecl
15289 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
15290 // references it. If the partially unrolled loop is associated with another
15291 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
15292 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
15293 // OpenMP canonical loop. The inner loop is not an associable canonical loop
15294 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
15295 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
15296 // property of the OMPLoopBasedDirective instead of statements in
15297 // CompoundStatement. This is to allow the loop to become a non-outermost loop
15298 // of a canonical loop nest where these PreInits are emitted before the
15299 // outermost directive.
15300
15301 // Determine the PreInit declarations.
15302 SmallVector<Decl *, 4> PreInits;
15303 assert(OriginalInits.size() == 1 &&
15304 "Expecting a single-dimensional loop iteration space");
15305 for (auto &P : OriginalInits[0]) {
15306 if (auto *D = P.dyn_cast<Decl *>())
15307 PreInits.push_back(D);
15308 else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
15309 PreInits.append(PI->decl_begin(), PI->decl_end());
15310 }
15311 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
15312 PreInits.append(PI->decl_begin(), PI->decl_end());
15313 // Gather declarations for the data members used as counters.
15314 for (Expr *CounterRef : LoopHelper.Counters) {
15315 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
15316 if (isa<OMPCapturedExprDecl>(CounterDecl))
15317 PreInits.push_back(CounterDecl);
15318 }
15319
15320 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15321 QualType IVTy = IterationVarRef->getType();
15322 assert(LoopHelper.Counters.size() == 1 &&
15323 "Expecting a single-dimensional loop iteration space");
15324 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15325
15326 // Determine the unroll factor.
15327 uint64_t Factor;
15328 SourceLocation FactorLoc;
15329 if (Expr *FactorVal = PartialClause->getFactor()) {
15330 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15331 FactorLoc = FactorVal->getExprLoc();
15332 } else {
15333 // TODO: Use a better profitability model.
15334 Factor = 2;
15335 }
15336 assert(Factor > 0 && "Expected positive unroll factor");
15337 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
15339 Context, llvm::APInt(Context.getIntWidth(IVTy), Factor), IVTy,
15340 FactorLoc);
15341 };
15342
15343 // Iteration variable SourceLocations.
15344 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15345 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15346 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15347
15348 // Internal variable names.
15349 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15350 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
15351 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
15352 std::string InnerTripCountName =
15353 (Twine(".unroll_inner.tripcount.") + OrigVarName).str();
15354
15355 // Create the iteration variable for the unrolled loop.
15356 VarDecl *OuterIVDecl =
15357 buildVarDecl(*this, {}, IVTy, OuterIVName, nullptr, OrigVar);
15358 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
15359 return buildDeclRefExpr(*this, OuterIVDecl, IVTy, OrigVarLoc);
15360 };
15361
15362 // Iteration variable for the inner loop: Reuse the iteration variable created
15363 // by checkOpenMPLoop.
15364 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15365 InnerIVDecl->setDeclName(&PP.getIdentifierTable().get(InnerIVName));
15366 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
15367 return buildDeclRefExpr(*this, InnerIVDecl, IVTy, OrigVarLoc);
15368 };
15369
15370 // Make a copy of the NumIterations expression for each use: By the AST
15371 // constraints, every expression object in a DeclContext must be unique.
15372 CaptureVars CopyTransformer(*this);
15373 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15374 return AssertSuccess(
15375 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15376 };
15377
15378 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15379 ExprResult LValueConv = DefaultLvalueConversion(MakeOuterRef());
15380 AddInitializerToDecl(InnerIVDecl, LValueConv.get(), /*DirectInit=*/false);
15381 StmtResult InnerInit = new (Context)
15382 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15383 if (!InnerInit.isUsable())
15384 return StmtError();
15385
15386 // Inner For cond-expression:
15387 // \code
15388 // .unroll_inner.iv < .unrolled.iv + Factor &&
15389 // .unroll_inner.iv < NumIterations
15390 // \endcode
15391 // This conjunction of two conditions allows ScalarEvolution to derive the
15392 // maximum trip count of the inner loop.
15393 ExprResult EndOfTile = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15394 BO_Add, MakeOuterRef(), MakeFactorExpr());
15395 if (!EndOfTile.isUsable())
15396 return StmtError();
15397 ExprResult InnerCond1 = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15398 BO_LT, MakeInnerRef(), EndOfTile.get());
15399 if (!InnerCond1.isUsable())
15400 return StmtError();
15401 ExprResult InnerCond2 =
15402 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeInnerRef(),
15403 MakeNumIterations());
15404 if (!InnerCond2.isUsable())
15405 return StmtError();
15406 ExprResult InnerCond =
15407 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15408 InnerCond1.get(), InnerCond2.get());
15409 if (!InnerCond.isUsable())
15410 return StmtError();
15411
15412 // Inner For incr-statement: ++.unroll_inner.iv
15413 ExprResult InnerIncr = BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
15414 UO_PreInc, MakeInnerRef());
15415 if (!InnerIncr.isUsable())
15416 return StmtError();
15417
15418 // Inner For statement.
15419 SmallVector<Stmt *> InnerBodyStmts;
15420 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15421 InnerBodyStmts.push_back(Body);
15422 CompoundStmt *InnerBody =
15424 Body->getBeginLoc(), Body->getEndLoc());
15425 ForStmt *InnerFor = new (Context)
15426 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15427 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15428 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15429
15430 // Unroll metadata for the inner loop.
15431 // This needs to take into account the remainder portion of the unrolled loop,
15432 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15433 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15434 // the maximum trip count, which will also generate a remainder loop. Just
15435 // `unroll(enable)` (which could have been useful if the user has not
15436 // specified a concrete factor; even though the outer loop cannot be
15437 // influenced anymore, would avoid more code bloat than necessary) will refuse
15438 // the loop because "Won't unroll; remainder loop could not be generated when
15439 // assuming runtime trip count". Even if it did work, it must not choose a
15440 // larger unroll factor than the maximum loop length, or it would always just
15441 // execute the remainder loop.
15442 LoopHintAttr *UnrollHintAttr =
15443 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15444 LoopHintAttr::Numeric, MakeFactorExpr());
15445 AttributedStmt *InnerUnrolled =
15446 AttributedStmt::Create(Context, StartLoc, {UnrollHintAttr}, InnerFor);
15447
15448 // Outer For init-statement: auto .unrolled.iv = 0
15450 OuterIVDecl, ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15451 /*DirectInit=*/false);
15452 StmtResult OuterInit = new (Context)
15453 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15454 if (!OuterInit.isUsable())
15455 return StmtError();
15456
15457 // Outer For cond-expression: .unrolled.iv < NumIterations
15458 ExprResult OuterConde =
15459 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeOuterRef(),
15460 MakeNumIterations());
15461 if (!OuterConde.isUsable())
15462 return StmtError();
15463
15464 // Outer For incr-statement: .unrolled.iv += Factor
15465 ExprResult OuterIncr =
15466 BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15467 MakeOuterRef(), MakeFactorExpr());
15468 if (!OuterIncr.isUsable())
15469 return StmtError();
15470
15471 // Outer For statement.
15472 ForStmt *OuterFor = new (Context)
15473 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15474 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15475 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15476
15477 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15478 NumGeneratedLoops, OuterFor,
15479 buildPreInits(Context, PreInits));
15480}
15481
15483 SourceLocation StartLoc,
15484 SourceLocation LParenLoc,
15485 SourceLocation EndLoc) {
15486 OMPClause *Res = nullptr;
15487 switch (Kind) {
15488 case OMPC_final:
15489 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
15490 break;
15491 case OMPC_num_threads:
15492 Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
15493 break;
15494 case OMPC_safelen:
15495 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
15496 break;
15497 case OMPC_simdlen:
15498 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
15499 break;
15500 case OMPC_allocator:
15501 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
15502 break;
15503 case OMPC_collapse:
15504 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
15505 break;
15506 case OMPC_ordered:
15507 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
15508 break;
15509 case OMPC_num_teams:
15510 Res = ActOnOpenMPNumTeamsClause(Expr, StartLoc, LParenLoc, EndLoc);
15511 break;
15512 case OMPC_thread_limit:
15513 Res = ActOnOpenMPThreadLimitClause(Expr, StartLoc, LParenLoc, EndLoc);
15514 break;
15515 case OMPC_priority:
15516 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
15517 break;
15518 case OMPC_hint:
15519 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
15520 break;
15521 case OMPC_depobj:
15522 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
15523 break;
15524 case OMPC_detach:
15525 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
15526 break;
15527 case OMPC_novariants:
15528 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
15529 break;
15530 case OMPC_nocontext:
15531 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
15532 break;
15533 case OMPC_filter:
15534 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
15535 break;
15536 case OMPC_partial:
15537 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
15538 break;
15539 case OMPC_message:
15540 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
15541 break;
15542 case OMPC_align:
15543 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
15544 break;
15545 case OMPC_ompx_dyn_cgroup_mem:
15546 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
15547 break;
15548 case OMPC_grainsize:
15549 case OMPC_num_tasks:
15550 case OMPC_device:
15551 case OMPC_if:
15552 case OMPC_default:
15553 case OMPC_proc_bind:
15554 case OMPC_schedule:
15555 case OMPC_private:
15556 case OMPC_firstprivate:
15557 case OMPC_lastprivate:
15558 case OMPC_shared:
15559 case OMPC_reduction:
15560 case OMPC_task_reduction:
15561 case OMPC_in_reduction:
15562 case OMPC_linear:
15563 case OMPC_aligned:
15564 case OMPC_copyin:
15565 case OMPC_copyprivate:
15566 case OMPC_nowait:
15567 case OMPC_untied:
15568 case OMPC_mergeable:
15569 case OMPC_threadprivate:
15570 case OMPC_sizes:
15571 case OMPC_allocate:
15572 case OMPC_flush:
15573 case OMPC_read:
15574 case OMPC_write:
15575 case OMPC_update:
15576 case OMPC_capture:
15577 case OMPC_compare:
15578 case OMPC_seq_cst:
15579 case OMPC_acq_rel:
15580 case OMPC_acquire:
15581 case OMPC_release:
15582 case OMPC_relaxed:
15583 case OMPC_depend:
15584 case OMPC_threads:
15585 case OMPC_simd:
15586 case OMPC_map:
15587 case OMPC_nogroup:
15588 case OMPC_dist_schedule:
15589 case OMPC_defaultmap:
15590 case OMPC_unknown:
15591 case OMPC_uniform:
15592 case OMPC_to:
15593 case OMPC_from:
15594 case OMPC_use_device_ptr:
15595 case OMPC_use_device_addr:
15596 case OMPC_is_device_ptr:
15597 case OMPC_unified_address:
15598 case OMPC_unified_shared_memory:
15599 case OMPC_reverse_offload:
15600 case OMPC_dynamic_allocators:
15601 case OMPC_atomic_default_mem_order:
15602 case OMPC_device_type:
15603 case OMPC_match:
15604 case OMPC_nontemporal:
15605 case OMPC_order:
15606 case OMPC_at:
15607 case OMPC_severity:
15608 case OMPC_destroy:
15609 case OMPC_inclusive:
15610 case OMPC_exclusive:
15611 case OMPC_uses_allocators:
15612 case OMPC_affinity:
15613 case OMPC_when:
15614 case OMPC_bind:
15615 default:
15616 llvm_unreachable("Clause is not allowed.");
15617 }
15618 return Res;
15619}
15620
15621// An OpenMP directive such as 'target parallel' has two captured regions:
15622// for the 'target' and 'parallel' respectively. This function returns
15623// the region in which to capture expressions associated with a clause.
15624// A return value of OMPD_unknown signifies that the expression should not
15625// be captured.
15627 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15628 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15629 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15630 switch (CKind) {
15631 case OMPC_if:
15632 switch (DKind) {
15633 case OMPD_target_parallel_for_simd:
15634 if (OpenMPVersion >= 50 &&
15635 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15636 CaptureRegion = OMPD_parallel;
15637 break;
15638 }
15639 [[fallthrough]];
15640 case OMPD_target_parallel:
15641 case OMPD_target_parallel_for:
15642 case OMPD_target_parallel_loop:
15643 // If this clause applies to the nested 'parallel' region, capture within
15644 // the 'target' region, otherwise do not capture.
15645 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15646 CaptureRegion = OMPD_target;
15647 break;
15648 case OMPD_target_teams_distribute_parallel_for_simd:
15649 if (OpenMPVersion >= 50 &&
15650 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15651 CaptureRegion = OMPD_parallel;
15652 break;
15653 }
15654 [[fallthrough]];
15655 case OMPD_target_teams_loop:
15656 case OMPD_target_teams_distribute_parallel_for:
15657 // If this clause applies to the nested 'parallel' region, capture within
15658 // the 'teams' region, otherwise do not capture.
15659 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15660 CaptureRegion = OMPD_teams;
15661 break;
15662 case OMPD_teams_distribute_parallel_for_simd:
15663 if (OpenMPVersion >= 50 &&
15664 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15665 CaptureRegion = OMPD_parallel;
15666 break;
15667 }
15668 [[fallthrough]];
15669 case OMPD_teams_distribute_parallel_for:
15670 CaptureRegion = OMPD_teams;
15671 break;
15672 case OMPD_target_update:
15673 case OMPD_target_enter_data:
15674 case OMPD_target_exit_data:
15675 CaptureRegion = OMPD_task;
15676 break;
15677 case OMPD_parallel_masked_taskloop:
15678 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15679 CaptureRegion = OMPD_parallel;
15680 break;
15681 case OMPD_parallel_master_taskloop:
15682 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15683 CaptureRegion = OMPD_parallel;
15684 break;
15685 case OMPD_parallel_masked_taskloop_simd:
15686 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15687 NameModifier == OMPD_taskloop) {
15688 CaptureRegion = OMPD_parallel;
15689 break;
15690 }
15691 if (OpenMPVersion <= 45)
15692 break;
15693 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15694 CaptureRegion = OMPD_taskloop;
15695 break;
15696 case OMPD_parallel_master_taskloop_simd:
15697 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15698 NameModifier == OMPD_taskloop) {
15699 CaptureRegion = OMPD_parallel;
15700 break;
15701 }
15702 if (OpenMPVersion <= 45)
15703 break;
15704 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15705 CaptureRegion = OMPD_taskloop;
15706 break;
15707 case OMPD_parallel_for_simd:
15708 if (OpenMPVersion <= 45)
15709 break;
15710 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15711 CaptureRegion = OMPD_parallel;
15712 break;
15713 case OMPD_taskloop_simd:
15714 case OMPD_master_taskloop_simd:
15715 case OMPD_masked_taskloop_simd:
15716 if (OpenMPVersion <= 45)
15717 break;
15718 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15719 CaptureRegion = OMPD_taskloop;
15720 break;
15721 case OMPD_distribute_parallel_for_simd:
15722 if (OpenMPVersion <= 45)
15723 break;
15724 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15725 CaptureRegion = OMPD_parallel;
15726 break;
15727 case OMPD_target_simd:
15728 if (OpenMPVersion >= 50 &&
15729 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15730 CaptureRegion = OMPD_target;
15731 break;
15732 case OMPD_teams_distribute_simd:
15733 case OMPD_target_teams_distribute_simd:
15734 if (OpenMPVersion >= 50 &&
15735 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15736 CaptureRegion = OMPD_teams;
15737 break;
15738 case OMPD_cancel:
15739 case OMPD_parallel:
15740 case OMPD_parallel_master:
15741 case OMPD_parallel_masked:
15742 case OMPD_parallel_sections:
15743 case OMPD_parallel_for:
15744 case OMPD_parallel_loop:
15745 case OMPD_target:
15746 case OMPD_target_teams:
15747 case OMPD_target_teams_distribute:
15748 case OMPD_distribute_parallel_for:
15749 case OMPD_task:
15750 case OMPD_taskloop:
15751 case OMPD_master_taskloop:
15752 case OMPD_masked_taskloop:
15753 case OMPD_target_data:
15754 case OMPD_simd:
15755 case OMPD_for_simd:
15756 case OMPD_distribute_simd:
15757 // Do not capture if-clause expressions.
15758 break;
15759 case OMPD_threadprivate:
15760 case OMPD_allocate:
15761 case OMPD_taskyield:
15762 case OMPD_error:
15763 case OMPD_barrier:
15764 case OMPD_taskwait:
15765 case OMPD_cancellation_point:
15766 case OMPD_flush:
15767 case OMPD_depobj:
15768 case OMPD_scan:
15769 case OMPD_declare_reduction:
15770 case OMPD_declare_mapper:
15771 case OMPD_declare_simd:
15772 case OMPD_declare_variant:
15773 case OMPD_begin_declare_variant:
15774 case OMPD_end_declare_variant:
15775 case OMPD_declare_target:
15776 case OMPD_end_declare_target:
15777 case OMPD_loop:
15778 case OMPD_teams_loop:
15779 case OMPD_teams:
15780 case OMPD_tile:
15781 case OMPD_unroll:
15782 case OMPD_for:
15783 case OMPD_sections:
15784 case OMPD_section:
15785 case OMPD_single:
15786 case OMPD_master:
15787 case OMPD_masked:
15788 case OMPD_critical:
15789 case OMPD_taskgroup:
15790 case OMPD_distribute:
15791 case OMPD_ordered:
15792 case OMPD_atomic:
15793 case OMPD_teams_distribute:
15794 case OMPD_requires:
15795 case OMPD_metadirective:
15796 llvm_unreachable("Unexpected OpenMP directive with if-clause");
15797 case OMPD_unknown:
15798 default:
15799 llvm_unreachable("Unknown OpenMP directive");
15800 }
15801 break;
15802 case OMPC_num_threads:
15803 switch (DKind) {
15804 case OMPD_target_parallel:
15805 case OMPD_target_parallel_for:
15806 case OMPD_target_parallel_for_simd:
15807 case OMPD_target_parallel_loop:
15808 CaptureRegion = OMPD_target;
15809 break;
15810 case OMPD_teams_distribute_parallel_for:
15811 case OMPD_teams_distribute_parallel_for_simd:
15812 case OMPD_target_teams_distribute_parallel_for:
15813 case OMPD_target_teams_distribute_parallel_for_simd:
15814 CaptureRegion = OMPD_teams;
15815 break;
15816 case OMPD_parallel:
15817 case OMPD_parallel_master:
15818 case OMPD_parallel_masked:
15819 case OMPD_parallel_sections:
15820 case OMPD_parallel_for:
15821 case OMPD_parallel_for_simd:
15822 case OMPD_parallel_loop:
15823 case OMPD_distribute_parallel_for:
15824 case OMPD_distribute_parallel_for_simd:
15825 case OMPD_parallel_master_taskloop:
15826 case OMPD_parallel_masked_taskloop:
15827 case OMPD_parallel_master_taskloop_simd:
15828 case OMPD_parallel_masked_taskloop_simd:
15829 // Do not capture num_threads-clause expressions.
15830 break;
15831 case OMPD_target_data:
15832 case OMPD_target_enter_data:
15833 case OMPD_target_exit_data:
15834 case OMPD_target_update:
15835 case OMPD_target:
15836 case OMPD_target_simd:
15837 case OMPD_target_teams:
15838 case OMPD_target_teams_distribute:
15839 case OMPD_target_teams_distribute_simd:
15840 case OMPD_cancel:
15841 case OMPD_task:
15842 case OMPD_taskloop:
15843 case OMPD_taskloop_simd:
15844 case OMPD_master_taskloop:
15845 case OMPD_masked_taskloop:
15846 case OMPD_master_taskloop_simd:
15847 case OMPD_masked_taskloop_simd:
15848 case OMPD_threadprivate:
15849 case OMPD_allocate:
15850 case OMPD_taskyield:
15851 case OMPD_error:
15852 case OMPD_barrier:
15853 case OMPD_taskwait:
15854 case OMPD_cancellation_point:
15855 case OMPD_flush:
15856 case OMPD_depobj:
15857 case OMPD_scan:
15858 case OMPD_declare_reduction:
15859 case OMPD_declare_mapper:
15860 case OMPD_declare_simd:
15861 case OMPD_declare_variant:
15862 case OMPD_begin_declare_variant:
15863 case OMPD_end_declare_variant:
15864 case OMPD_declare_target:
15865 case OMPD_end_declare_target:
15866 case OMPD_loop:
15867 case OMPD_teams_loop:
15868 case OMPD_target_teams_loop:
15869 case OMPD_teams:
15870 case OMPD_simd:
15871 case OMPD_tile:
15872 case OMPD_unroll:
15873 case OMPD_for:
15874 case OMPD_for_simd:
15875 case OMPD_sections:
15876 case OMPD_section:
15877 case OMPD_single:
15878 case OMPD_master:
15879 case OMPD_masked:
15880 case OMPD_critical:
15881 case OMPD_taskgroup:
15882 case OMPD_distribute:
15883 case OMPD_ordered:
15884 case OMPD_atomic:
15885 case OMPD_distribute_simd:
15886 case OMPD_teams_distribute:
15887 case OMPD_teams_distribute_simd:
15888 case OMPD_requires:
15889 case OMPD_metadirective:
15890 llvm_unreachable("Unexpected OpenMP directive with num_threads-clause");
15891 case OMPD_unknown:
15892 default:
15893 llvm_unreachable("Unknown OpenMP directive");
15894 }
15895 break;
15896 case OMPC_num_teams:
15897 switch (DKind) {
15898 case OMPD_target_teams:
15899 case OMPD_target_teams_distribute:
15900 case OMPD_target_teams_distribute_simd:
15901 case OMPD_target_teams_distribute_parallel_for:
15902 case OMPD_target_teams_distribute_parallel_for_simd:
15903 case OMPD_target_teams_loop:
15904 CaptureRegion = OMPD_target;
15905 break;
15906 case OMPD_teams_distribute_parallel_for:
15907 case OMPD_teams_distribute_parallel_for_simd:
15908 case OMPD_teams:
15909 case OMPD_teams_distribute:
15910 case OMPD_teams_distribute_simd:
15911 case OMPD_teams_loop:
15912 // Do not capture num_teams-clause expressions.
15913 break;
15914 case OMPD_distribute_parallel_for:
15915 case OMPD_distribute_parallel_for_simd:
15916 case OMPD_task:
15917 case OMPD_taskloop:
15918 case OMPD_taskloop_simd:
15919 case OMPD_master_taskloop:
15920 case OMPD_masked_taskloop:
15921 case OMPD_master_taskloop_simd:
15922 case OMPD_masked_taskloop_simd:
15923 case OMPD_parallel_master_taskloop:
15924 case OMPD_parallel_masked_taskloop:
15925 case OMPD_parallel_master_taskloop_simd:
15926 case OMPD_parallel_masked_taskloop_simd:
15927 case OMPD_target_data:
15928 case OMPD_target_enter_data:
15929 case OMPD_target_exit_data:
15930 case OMPD_target_update:
15931 case OMPD_cancel:
15932 case OMPD_parallel:
15933 case OMPD_parallel_master:
15934 case OMPD_parallel_masked:
15935 case OMPD_parallel_sections:
15936 case OMPD_parallel_for:
15937 case OMPD_parallel_for_simd:
15938 case OMPD_parallel_loop:
15939 case OMPD_target:
15940 case OMPD_target_simd:
15941 case OMPD_target_parallel:
15942 case OMPD_target_parallel_for:
15943 case OMPD_target_parallel_for_simd:
15944 case OMPD_target_parallel_loop:
15945 case OMPD_threadprivate:
15946 case OMPD_allocate:
15947 case OMPD_taskyield:
15948 case OMPD_error:
15949 case OMPD_barrier:
15950 case OMPD_taskwait:
15951 case OMPD_cancellation_point:
15952 case OMPD_flush:
15953 case OMPD_depobj:
15954 case OMPD_scan:
15955 case OMPD_declare_reduction:
15956 case OMPD_declare_mapper:
15957 case OMPD_declare_simd:
15958 case OMPD_declare_variant:
15959 case OMPD_begin_declare_variant:
15960 case OMPD_end_declare_variant:
15961 case OMPD_declare_target:
15962 case OMPD_end_declare_target:
15963 case OMPD_loop:
15964 case OMPD_simd:
15965 case OMPD_tile:
15966 case OMPD_unroll:
15967 case OMPD_for:
15968 case OMPD_for_simd:
15969 case OMPD_sections:
15970 case OMPD_section:
15971 case OMPD_single:
15972 case OMPD_master:
15973 case OMPD_masked:
15974 case OMPD_critical:
15975 case OMPD_taskgroup:
15976 case OMPD_distribute:
15977 case OMPD_ordered:
15978 case OMPD_atomic:
15979 case OMPD_distribute_simd:
15980 case OMPD_requires:
15981 case OMPD_metadirective:
15982 llvm_unreachable("Unexpected OpenMP directive with num_teams-clause");
15983 case OMPD_unknown:
15984 default:
15985 llvm_unreachable("Unknown OpenMP directive");
15986 }
15987 break;
15988 case OMPC_thread_limit:
15989 switch (DKind) {
15990 case OMPD_target:
15991 case OMPD_target_teams:
15992 case OMPD_target_teams_distribute:
15993 case OMPD_target_teams_distribute_simd:
15994 case OMPD_target_teams_distribute_parallel_for:
15995 case OMPD_target_teams_distribute_parallel_for_simd:
15996 case OMPD_target_teams_loop:
15997 case OMPD_target_simd:
15998 case OMPD_target_parallel:
15999 case OMPD_target_parallel_for:
16000 case OMPD_target_parallel_for_simd:
16001 case OMPD_target_parallel_loop:
16002 CaptureRegion = OMPD_target;
16003 break;
16004 case OMPD_teams_distribute_parallel_for:
16005 case OMPD_teams_distribute_parallel_for_simd:
16006 case OMPD_teams:
16007 case OMPD_teams_distribute:
16008 case OMPD_teams_distribute_simd:
16009 case OMPD_teams_loop:
16010 // Do not capture thread_limit-clause expressions.
16011 break;
16012 case OMPD_distribute_parallel_for:
16013 case OMPD_distribute_parallel_for_simd:
16014 case OMPD_task:
16015 case OMPD_taskloop:
16016 case OMPD_taskloop_simd:
16017 case OMPD_master_taskloop:
16018 case OMPD_masked_taskloop:
16019 case OMPD_master_taskloop_simd:
16020 case OMPD_masked_taskloop_simd:
16021 case OMPD_parallel_master_taskloop:
16022 case OMPD_parallel_masked_taskloop:
16023 case OMPD_parallel_master_taskloop_simd:
16024 case OMPD_parallel_masked_taskloop_simd:
16025 case OMPD_target_data:
16026 case OMPD_target_enter_data:
16027 case OMPD_target_exit_data:
16028 case OMPD_target_update:
16029 case OMPD_cancel:
16030 case OMPD_parallel:
16031 case OMPD_parallel_master:
16032 case OMPD_parallel_masked:
16033 case OMPD_parallel_sections:
16034 case OMPD_parallel_for:
16035 case OMPD_parallel_for_simd:
16036 case OMPD_parallel_loop:
16037 case OMPD_threadprivate:
16038 case OMPD_allocate:
16039 case OMPD_taskyield:
16040 case OMPD_error:
16041 case OMPD_barrier:
16042 case OMPD_taskwait:
16043 case OMPD_cancellation_point:
16044 case OMPD_flush:
16045 case OMPD_depobj:
16046 case OMPD_scan:
16047 case OMPD_declare_reduction:
16048 case OMPD_declare_mapper:
16049 case OMPD_declare_simd:
16050 case OMPD_declare_variant:
16051 case OMPD_begin_declare_variant:
16052 case OMPD_end_declare_variant:
16053 case OMPD_declare_target:
16054 case OMPD_end_declare_target:
16055 case OMPD_loop:
16056 case OMPD_simd:
16057 case OMPD_tile:
16058 case OMPD_unroll:
16059 case OMPD_for:
16060 case OMPD_for_simd:
16061 case OMPD_sections:
16062 case OMPD_section:
16063 case OMPD_single:
16064 case OMPD_master:
16065 case OMPD_masked:
16066 case OMPD_critical:
16067 case OMPD_taskgroup:
16068 case OMPD_distribute:
16069 case OMPD_ordered:
16070 case OMPD_atomic:
16071 case OMPD_distribute_simd:
16072 case OMPD_requires:
16073 case OMPD_metadirective:
16074 llvm_unreachable("Unexpected OpenMP directive with thread_limit-clause");
16075 case OMPD_unknown:
16076 default:
16077 llvm_unreachable("Unknown OpenMP directive");
16078 }
16079 break;
16080 case OMPC_schedule:
16081 switch (DKind) {
16082 case OMPD_parallel_for:
16083 case OMPD_parallel_for_simd:
16084 case OMPD_distribute_parallel_for:
16085 case OMPD_distribute_parallel_for_simd:
16086 case OMPD_teams_distribute_parallel_for:
16087 case OMPD_teams_distribute_parallel_for_simd:
16088 case OMPD_target_parallel_for:
16089 case OMPD_target_parallel_for_simd:
16090 case OMPD_target_teams_distribute_parallel_for:
16091 case OMPD_target_teams_distribute_parallel_for_simd:
16092 CaptureRegion = OMPD_parallel;
16093 break;
16094 case OMPD_for:
16095 case OMPD_for_simd:
16096 // Do not capture schedule-clause expressions.
16097 break;
16098 case OMPD_task:
16099 case OMPD_taskloop:
16100 case OMPD_taskloop_simd:
16101 case OMPD_master_taskloop:
16102 case OMPD_masked_taskloop:
16103 case OMPD_master_taskloop_simd:
16104 case OMPD_masked_taskloop_simd:
16105 case OMPD_parallel_master_taskloop:
16106 case OMPD_parallel_masked_taskloop:
16107 case OMPD_parallel_master_taskloop_simd:
16108 case OMPD_parallel_masked_taskloop_simd:
16109 case OMPD_target_data:
16110 case OMPD_target_enter_data:
16111 case OMPD_target_exit_data:
16112 case OMPD_target_update:
16113 case OMPD_teams:
16114 case OMPD_teams_distribute:
16115 case OMPD_teams_distribute_simd:
16116 case OMPD_target_teams_distribute:
16117 case OMPD_target_teams_distribute_simd:
16118 case OMPD_target:
16119 case OMPD_target_simd:
16120 case OMPD_target_parallel:
16121 case OMPD_cancel:
16122 case OMPD_parallel:
16123 case OMPD_parallel_master:
16124 case OMPD_parallel_masked:
16125 case OMPD_parallel_sections:
16126 case OMPD_threadprivate:
16127 case OMPD_allocate:
16128 case OMPD_taskyield:
16129 case OMPD_error:
16130 case OMPD_barrier:
16131 case OMPD_taskwait:
16132 case OMPD_cancellation_point:
16133 case OMPD_flush:
16134 case OMPD_depobj:
16135 case OMPD_scan:
16136 case OMPD_declare_reduction:
16137 case OMPD_declare_mapper:
16138 case OMPD_declare_simd:
16139 case OMPD_declare_variant:
16140 case OMPD_begin_declare_variant:
16141 case OMPD_end_declare_variant:
16142 case OMPD_declare_target:
16143 case OMPD_end_declare_target:
16144 case OMPD_loop:
16145 case OMPD_teams_loop:
16146 case OMPD_target_teams_loop:
16147 case OMPD_parallel_loop:
16148 case OMPD_target_parallel_loop:
16149 case OMPD_simd:
16150 case OMPD_tile:
16151 case OMPD_unroll:
16152 case OMPD_sections:
16153 case OMPD_section:
16154 case OMPD_single:
16155 case OMPD_master:
16156 case OMPD_masked:
16157 case OMPD_critical:
16158 case OMPD_taskgroup:
16159 case OMPD_distribute:
16160 case OMPD_ordered:
16161 case OMPD_atomic:
16162 case OMPD_distribute_simd:
16163 case OMPD_target_teams:
16164 case OMPD_requires:
16165 case OMPD_metadirective:
16166 llvm_unreachable("Unexpected OpenMP directive with schedule clause");
16167 case OMPD_unknown:
16168 default:
16169 llvm_unreachable("Unknown OpenMP directive");
16170 }
16171 break;
16172 case OMPC_dist_schedule:
16173 switch (DKind) {
16174 case OMPD_teams_distribute_parallel_for:
16175 case OMPD_teams_distribute_parallel_for_simd:
16176 case OMPD_teams_distribute:
16177 case OMPD_teams_distribute_simd:
16178 case OMPD_target_teams_distribute_parallel_for:
16179 case OMPD_target_teams_distribute_parallel_for_simd:
16180 case OMPD_target_teams_distribute:
16181 case OMPD_target_teams_distribute_simd:
16182 CaptureRegion = OMPD_teams;
16183 break;
16184 case OMPD_distribute_parallel_for:
16185 case OMPD_distribute_parallel_for_simd:
16186 case OMPD_distribute:
16187 case OMPD_distribute_simd:
16188 // Do not capture dist_schedule-clause expressions.
16189 break;
16190 case OMPD_parallel_for:
16191 case OMPD_parallel_for_simd:
16192 case OMPD_target_parallel_for_simd:
16193 case OMPD_target_parallel_for:
16194 case OMPD_task:
16195 case OMPD_taskloop:
16196 case OMPD_taskloop_simd:
16197 case OMPD_master_taskloop:
16198 case OMPD_masked_taskloop:
16199 case OMPD_master_taskloop_simd:
16200 case OMPD_masked_taskloop_simd:
16201 case OMPD_parallel_master_taskloop:
16202 case OMPD_parallel_masked_taskloop:
16203 case OMPD_parallel_master_taskloop_simd:
16204 case OMPD_parallel_masked_taskloop_simd:
16205 case OMPD_target_data:
16206 case OMPD_target_enter_data:
16207 case OMPD_target_exit_data:
16208 case OMPD_target_update:
16209 case OMPD_teams:
16210 case OMPD_target:
16211 case OMPD_target_simd:
16212 case OMPD_target_parallel:
16213 case OMPD_cancel:
16214 case OMPD_parallel:
16215 case OMPD_parallel_master:
16216 case OMPD_parallel_masked:
16217 case OMPD_parallel_sections:
16218 case OMPD_threadprivate:
16219 case OMPD_allocate:
16220 case OMPD_taskyield:
16221 case OMPD_error:
16222 case OMPD_barrier:
16223 case OMPD_taskwait:
16224 case OMPD_cancellation_point:
16225 case OMPD_flush:
16226 case OMPD_depobj:
16227 case OMPD_scan:
16228 case OMPD_declare_reduction:
16229 case OMPD_declare_mapper:
16230 case OMPD_declare_simd:
16231 case OMPD_declare_variant:
16232 case OMPD_begin_declare_variant:
16233 case OMPD_end_declare_variant:
16234 case OMPD_declare_target:
16235 case OMPD_end_declare_target:
16236 case OMPD_loop:
16237 case OMPD_teams_loop:
16238 case OMPD_target_teams_loop:
16239 case OMPD_parallel_loop:
16240 case OMPD_target_parallel_loop:
16241 case OMPD_simd:
16242 case OMPD_tile:
16243 case OMPD_unroll:
16244 case OMPD_for:
16245 case OMPD_for_simd:
16246 case OMPD_sections:
16247 case OMPD_section:
16248 case OMPD_single:
16249 case OMPD_master:
16250 case OMPD_masked:
16251 case OMPD_critical:
16252 case OMPD_taskgroup:
16253 case OMPD_ordered:
16254 case OMPD_atomic:
16255 case OMPD_target_teams:
16256 case OMPD_requires:
16257 case OMPD_metadirective:
16258 llvm_unreachable("Unexpected OpenMP directive with dist_schedule clause");
16259 case OMPD_unknown:
16260 default:
16261 llvm_unreachable("Unknown OpenMP directive");
16262 }
16263 break;
16264 case OMPC_ompx_dyn_cgroup_mem:
16265 switch (DKind) {
16266 case OMPD_target:
16267 case OMPD_target_simd:
16268 case OMPD_target_teams:
16269 case OMPD_target_parallel:
16270 case OMPD_target_teams_distribute:
16271 case OMPD_target_teams_distribute_simd:
16272 case OMPD_target_parallel_for:
16273 case OMPD_target_parallel_for_simd:
16274 case OMPD_target_parallel_loop:
16275 case OMPD_target_teams_distribute_parallel_for:
16276 case OMPD_target_teams_distribute_parallel_for_simd:
16277 case OMPD_target_teams_loop:
16278 CaptureRegion = OMPD_target;
16279 break;
16280 default:
16281 llvm_unreachable("Unknown OpenMP directive");
16282 }
16283 break;
16284 case OMPC_device:
16285 switch (DKind) {
16286 case OMPD_target_update:
16287 case OMPD_target_enter_data:
16288 case OMPD_target_exit_data:
16289 case OMPD_target:
16290 case OMPD_target_simd:
16291 case OMPD_target_teams:
16292 case OMPD_target_parallel:
16293 case OMPD_target_teams_distribute:
16294 case OMPD_target_teams_distribute_simd:
16295 case OMPD_target_parallel_for:
16296 case OMPD_target_parallel_for_simd:
16297 case OMPD_target_parallel_loop:
16298 case OMPD_target_teams_distribute_parallel_for:
16299 case OMPD_target_teams_distribute_parallel_for_simd:
16300 case OMPD_target_teams_loop:
16301 case OMPD_dispatch:
16302 CaptureRegion = OMPD_task;
16303 break;
16304 case OMPD_target_data:
16305 case OMPD_interop:
16306 // Do not capture device-clause expressions.
16307 break;
16308 case OMPD_teams_distribute_parallel_for:
16309 case OMPD_teams_distribute_parallel_for_simd:
16310 case OMPD_teams:
16311 case OMPD_teams_distribute:
16312 case OMPD_teams_distribute_simd:
16313 case OMPD_distribute_parallel_for:
16314 case OMPD_distribute_parallel_for_simd:
16315 case OMPD_task:
16316 case OMPD_taskloop:
16317 case OMPD_taskloop_simd:
16318 case OMPD_master_taskloop:
16319 case OMPD_masked_taskloop:
16320 case OMPD_master_taskloop_simd:
16321 case OMPD_masked_taskloop_simd:
16322 case OMPD_parallel_master_taskloop:
16323 case OMPD_parallel_masked_taskloop:
16324 case OMPD_parallel_master_taskloop_simd:
16325 case OMPD_parallel_masked_taskloop_simd:
16326 case OMPD_cancel:
16327 case OMPD_parallel:
16328 case OMPD_parallel_master:
16329 case OMPD_parallel_masked:
16330 case OMPD_parallel_sections:
16331 case OMPD_parallel_for:
16332 case OMPD_parallel_for_simd:
16333 case OMPD_threadprivate:
16334 case OMPD_allocate:
16335 case OMPD_taskyield:
16336 case OMPD_error:
16337 case OMPD_barrier:
16338 case OMPD_taskwait:
16339 case OMPD_cancellation_point:
16340 case OMPD_flush:
16341 case OMPD_depobj:
16342 case OMPD_scan:
16343 case OMPD_declare_reduction:
16344 case OMPD_declare_mapper:
16345 case OMPD_declare_simd:
16346 case OMPD_declare_variant:
16347 case OMPD_begin_declare_variant:
16348 case OMPD_end_declare_variant:
16349 case OMPD_declare_target:
16350 case OMPD_end_declare_target:
16351 case OMPD_loop:
16352 case OMPD_teams_loop:
16353 case OMPD_parallel_loop:
16354 case OMPD_simd:
16355 case OMPD_tile:
16356 case OMPD_unroll:
16357 case OMPD_for:
16358 case OMPD_for_simd:
16359 case OMPD_sections:
16360 case OMPD_section:
16361 case OMPD_single:
16362 case OMPD_master:
16363 case OMPD_masked:
16364 case OMPD_critical:
16365 case OMPD_taskgroup:
16366 case OMPD_distribute:
16367 case OMPD_ordered:
16368 case OMPD_atomic:
16369 case OMPD_distribute_simd:
16370 case OMPD_requires:
16371 case OMPD_metadirective:
16372 llvm_unreachable("Unexpected OpenMP directive with device-clause");
16373 case OMPD_unknown:
16374 default:
16375 llvm_unreachable("Unknown OpenMP directive");
16376 }
16377 break;
16378 case OMPC_grainsize:
16379 case OMPC_num_tasks:
16380 case OMPC_final:
16381 case OMPC_priority:
16382 switch (DKind) {
16383 case OMPD_task:
16384 case OMPD_taskloop:
16385 case OMPD_taskloop_simd:
16386 case OMPD_master_taskloop:
16387 case OMPD_masked_taskloop:
16388 case OMPD_master_taskloop_simd:
16389 case OMPD_masked_taskloop_simd:
16390 break;
16391 case OMPD_parallel_masked_taskloop:
16392 case OMPD_parallel_masked_taskloop_simd:
16393 case OMPD_parallel_master_taskloop:
16394 case OMPD_parallel_master_taskloop_simd:
16395 CaptureRegion = OMPD_parallel;
16396 break;
16397 case OMPD_target_update:
16398 case OMPD_target_enter_data:
16399 case OMPD_target_exit_data:
16400 case OMPD_target:
16401 case OMPD_target_simd:
16402 case OMPD_target_teams:
16403 case OMPD_target_parallel:
16404 case OMPD_target_teams_distribute:
16405 case OMPD_target_teams_distribute_simd:
16406 case OMPD_target_parallel_for:
16407 case OMPD_target_parallel_for_simd:
16408 case OMPD_target_teams_distribute_parallel_for:
16409 case OMPD_target_teams_distribute_parallel_for_simd:
16410 case OMPD_target_data:
16411 case OMPD_teams_distribute_parallel_for:
16412 case OMPD_teams_distribute_parallel_for_simd:
16413 case OMPD_teams:
16414 case OMPD_teams_distribute:
16415 case OMPD_teams_distribute_simd:
16416 case OMPD_distribute_parallel_for:
16417 case OMPD_distribute_parallel_for_simd:
16418 case OMPD_cancel:
16419 case OMPD_parallel:
16420 case OMPD_parallel_master:
16421 case OMPD_parallel_masked:
16422 case OMPD_parallel_sections:
16423 case OMPD_parallel_for:
16424 case OMPD_parallel_for_simd:
16425 case OMPD_threadprivate:
16426 case OMPD_allocate:
16427 case OMPD_taskyield:
16428 case OMPD_error:
16429 case OMPD_barrier:
16430 case OMPD_taskwait:
16431 case OMPD_cancellation_point:
16432 case OMPD_flush:
16433 case OMPD_depobj:
16434 case OMPD_scan:
16435 case OMPD_declare_reduction:
16436 case OMPD_declare_mapper:
16437 case OMPD_declare_simd:
16438 case OMPD_declare_variant:
16439 case OMPD_begin_declare_variant:
16440 case OMPD_end_declare_variant:
16441 case OMPD_declare_target:
16442 case OMPD_end_declare_target:
16443 case OMPD_loop:
16444 case OMPD_teams_loop:
16445 case OMPD_target_teams_loop:
16446 case OMPD_parallel_loop:
16447 case OMPD_target_parallel_loop:
16448 case OMPD_simd:
16449 case OMPD_tile:
16450 case OMPD_unroll:
16451 case OMPD_for:
16452 case OMPD_for_simd:
16453 case OMPD_sections:
16454 case OMPD_section:
16455 case OMPD_single:
16456 case OMPD_master:
16457 case OMPD_masked:
16458 case OMPD_critical:
16459 case OMPD_taskgroup:
16460 case OMPD_distribute:
16461 case OMPD_ordered:
16462 case OMPD_atomic:
16463 case OMPD_distribute_simd:
16464 case OMPD_requires:
16465 case OMPD_metadirective:
16466 llvm_unreachable("Unexpected OpenMP directive with grainsize-clause");
16467 case OMPD_unknown:
16468 default:
16469 llvm_unreachable("Unknown OpenMP directive");
16470 }
16471 break;
16472 case OMPC_novariants:
16473 case OMPC_nocontext:
16474 switch (DKind) {
16475 case OMPD_dispatch:
16476 CaptureRegion = OMPD_task;
16477 break;
16478 default:
16479 llvm_unreachable("Unexpected OpenMP directive");
16480 }
16481 break;
16482 case OMPC_filter:
16483 // Do not capture filter-clause expressions.
16484 break;
16485 case OMPC_when:
16486 if (DKind == OMPD_metadirective) {
16487 CaptureRegion = OMPD_metadirective;
16488 } else if (DKind == OMPD_unknown) {
16489 llvm_unreachable("Unknown OpenMP directive");
16490 } else {
16491 llvm_unreachable("Unexpected OpenMP directive with when clause");
16492 }
16493 break;
16494 case OMPC_firstprivate:
16495 case OMPC_lastprivate:
16496 case OMPC_reduction:
16497 case OMPC_task_reduction:
16498 case OMPC_in_reduction:
16499 case OMPC_linear:
16500 case OMPC_default:
16501 case OMPC_proc_bind:
16502 case OMPC_safelen:
16503 case OMPC_simdlen:
16504 case OMPC_sizes:
16505 case OMPC_allocator:
16506 case OMPC_collapse:
16507 case OMPC_private:
16508 case OMPC_shared:
16509 case OMPC_aligned:
16510 case OMPC_copyin:
16511 case OMPC_copyprivate:
16512 case OMPC_ordered:
16513 case OMPC_nowait:
16514 case OMPC_untied:
16515 case OMPC_mergeable:
16516 case OMPC_threadprivate:
16517 case OMPC_allocate:
16518 case OMPC_flush:
16519 case OMPC_depobj:
16520 case OMPC_read:
16521 case OMPC_write:
16522 case OMPC_update:
16523 case OMPC_capture:
16524 case OMPC_compare:
16525 case OMPC_seq_cst:
16526 case OMPC_acq_rel:
16527 case OMPC_acquire:
16528 case OMPC_release:
16529 case OMPC_relaxed:
16530 case OMPC_depend:
16531 case OMPC_threads:
16532 case OMPC_simd:
16533 case OMPC_map:
16534 case OMPC_nogroup:
16535 case OMPC_hint:
16536 case OMPC_defaultmap:
16537 case OMPC_unknown:
16538 case OMPC_uniform:
16539 case OMPC_to:
16540 case OMPC_from:
16541 case OMPC_use_device_ptr:
16542 case OMPC_use_device_addr:
16543 case OMPC_is_device_ptr:
16544 case OMPC_unified_address:
16545 case OMPC_unified_shared_memory:
16546 case OMPC_reverse_offload:
16547 case OMPC_dynamic_allocators:
16548 case OMPC_atomic_default_mem_order:
16549 case OMPC_device_type:
16550 case OMPC_match:
16551 case OMPC_nontemporal:
16552 case OMPC_order:
16553 case OMPC_at:
16554 case OMPC_severity:
16555 case OMPC_message:
16556 case OMPC_destroy:
16557 case OMPC_detach:
16558 case OMPC_inclusive:
16559 case OMPC_exclusive:
16560 case OMPC_uses_allocators:
16561 case OMPC_affinity:
16562 case OMPC_bind:
16563 default:
16564 llvm_unreachable("Unexpected OpenMP clause.");
16565 }
16566 return CaptureRegion;
16567}
16568
16570 Expr *Condition, SourceLocation StartLoc,
16571 SourceLocation LParenLoc,
16572 SourceLocation NameModifierLoc,
16573 SourceLocation ColonLoc,
16574 SourceLocation EndLoc) {
16575 Expr *ValExpr = Condition;
16576 Stmt *HelperValStmt = nullptr;
16577 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16578 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16579 !Condition->isInstantiationDependent() &&
16580 !Condition->containsUnexpandedParameterPack()) {
16582 if (Val.isInvalid())
16583 return nullptr;
16584
16585 ValExpr = Val.get();
16586
16587 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16588 CaptureRegion = getOpenMPCaptureRegionForClause(
16589 DKind, OMPC_if, LangOpts.OpenMP, NameModifier);
16590 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16591 ValExpr = MakeFullExpr(ValExpr).get();
16592 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16593 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16594 HelperValStmt = buildPreInits(Context, Captures);
16595 }
16596 }
16597
16598 return new (Context)
16599 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16600 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16601}
16602
16604 SourceLocation StartLoc,
16605 SourceLocation LParenLoc,
16606 SourceLocation EndLoc) {
16607 Expr *ValExpr = Condition;
16608 Stmt *HelperValStmt = nullptr;
16609 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16610 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16611 !Condition->isInstantiationDependent() &&
16612 !Condition->containsUnexpandedParameterPack()) {
16614 if (Val.isInvalid())
16615 return nullptr;
16616
16617 ValExpr = MakeFullExpr(Val.get()).get();
16618
16619 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16620 CaptureRegion =
16621 getOpenMPCaptureRegionForClause(DKind, OMPC_final, LangOpts.OpenMP);
16622 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16623 ValExpr = MakeFullExpr(ValExpr).get();
16624 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16625 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16626 HelperValStmt = buildPreInits(Context, Captures);
16627 }
16628 }
16629
16630 return new (Context) OMPFinalClause(ValExpr, HelperValStmt, CaptureRegion,
16631 StartLoc, LParenLoc, EndLoc);
16632}
16633
16635 Expr *Op) {
16636 if (!Op)
16637 return ExprError();
16638
16639 class IntConvertDiagnoser : public ICEConvertDiagnoser {
16640 public:
16641 IntConvertDiagnoser()
16642 : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {}
16643 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
16644 QualType T) override {
16645 return S.Diag(Loc, diag::err_omp_not_integral) << T;
16646 }
16647 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
16648 QualType T) override {
16649 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
16650 }
16651 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
16652 QualType T,
16653 QualType ConvTy) override {
16654 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
16655 }
16656 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
16657 QualType ConvTy) override {
16658 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16659 << ConvTy->isEnumeralType() << ConvTy;
16660 }
16661 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
16662 QualType T) override {
16663 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
16664 }
16665 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
16666 QualType ConvTy) override {
16667 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16668 << ConvTy->isEnumeralType() << ConvTy;
16669 }
16670 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
16671 QualType) override {
16672 llvm_unreachable("conversion functions are permitted");
16673 }
16674 } ConvertDiagnoser;
16675 return PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16676}
16677
16678static bool
16680 bool StrictlyPositive, bool BuildCapture = false,
16681 OpenMPDirectiveKind DKind = OMPD_unknown,
16682 OpenMPDirectiveKind *CaptureRegion = nullptr,
16683 Stmt **HelperValStmt = nullptr) {
16684 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
16685 !ValExpr->isInstantiationDependent()) {
16686 SourceLocation Loc = ValExpr->getExprLoc();
16688 SemaRef.PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
16689 if (Value.isInvalid())
16690 return false;
16691
16692 ValExpr = Value.get();
16693 // The expression must evaluate to a non-negative integer value.
16694 if (std::optional<llvm::APSInt> Result =
16695 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
16696 if (Result->isSigned() &&
16697 !((!StrictlyPositive && Result->isNonNegative()) ||
16698 (StrictlyPositive && Result->isStrictlyPositive()))) {
16699 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
16700 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16701 << ValExpr->getSourceRange();
16702 return false;
16703 }
16704 }
16705 if (!BuildCapture)
16706 return true;
16707 *CaptureRegion =
16708 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
16709 if (*CaptureRegion != OMPD_unknown &&
16710 !SemaRef.CurContext->isDependentContext()) {
16711 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16712 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16713 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16714 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
16715 }
16716 }
16717 return true;
16718}
16719
16721 SourceLocation StartLoc,
16722 SourceLocation LParenLoc,
16723 SourceLocation EndLoc) {
16724 Expr *ValExpr = NumThreads;
16725 Stmt *HelperValStmt = nullptr;
16726
16727 // OpenMP [2.5, Restrictions]
16728 // The num_threads expression must evaluate to a positive integer value.
16729 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_threads,
16730 /*StrictlyPositive=*/true))
16731 return nullptr;
16732
16733 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16734 OpenMPDirectiveKind CaptureRegion =
16735 getOpenMPCaptureRegionForClause(DKind, OMPC_num_threads, LangOpts.OpenMP);
16736 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16737 ValExpr = MakeFullExpr(ValExpr).get();
16738 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16739 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16740 HelperValStmt = buildPreInits(Context, Captures);
16741 }
16742
16743 return new (Context) OMPNumThreadsClause(
16744 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16745}
16746
16748 OpenMPClauseKind CKind,
16749 bool StrictlyPositive,
16750 bool SuppressExprDiags) {
16751 if (!E)
16752 return ExprError();
16753 if (E->isValueDependent() || E->isTypeDependent() ||
16755 return E;
16756
16757 llvm::APSInt Result;
16758 ExprResult ICE;
16759 if (SuppressExprDiags) {
16760 // Use a custom diagnoser that suppresses 'note' diagnostics about the
16761 // expression.
16762 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
16763 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
16764 Sema::SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
16765 SourceLocation Loc) override {
16766 llvm_unreachable("Diagnostic suppressed");
16767 }
16768 } Diagnoser;
16769 ICE = VerifyIntegerConstantExpression(E, &Result, Diagnoser, AllowFold);
16770 } else {
16771 ICE = VerifyIntegerConstantExpression(E, &Result, /*FIXME*/ AllowFold);
16772 }
16773 if (ICE.isInvalid())
16774 return ExprError();
16775
16776 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
16777 (!StrictlyPositive && !Result.isNonNegative())) {
16778 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
16779 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16780 << E->getSourceRange();
16781 return ExprError();
16782 }
16783 if ((CKind == OMPC_aligned || CKind == OMPC_align) && !Result.isPowerOf2()) {
16784 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
16785 << E->getSourceRange();
16786 return ExprError();
16787 }
16788 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
16789 DSAStack->setAssociatedLoops(Result.getExtValue());
16790 else if (CKind == OMPC_ordered)
16791 DSAStack->setAssociatedLoops(Result.getExtValue());
16792 return ICE;
16793}
16794
16796 SourceLocation LParenLoc,
16797 SourceLocation EndLoc) {
16798 // OpenMP [2.8.1, simd construct, Description]
16799 // The parameter of the safelen clause must be a constant
16800 // positive integer expression.
16801 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
16802 if (Safelen.isInvalid())
16803 return nullptr;
16804 return new (Context)
16805 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
16806}
16807
16809 SourceLocation LParenLoc,
16810 SourceLocation EndLoc) {
16811 // OpenMP [2.8.1, simd construct, Description]
16812 // The parameter of the simdlen clause must be a constant
16813 // positive integer expression.
16814 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
16815 if (Simdlen.isInvalid())
16816 return nullptr;
16817 return new (Context)
16818 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
16819}
16820
16821/// Tries to find omp_allocator_handle_t type.
16823 DSAStackTy *Stack) {
16824 if (!Stack->getOMPAllocatorHandleT().isNull())
16825 return true;
16826
16827 // Set the allocator handle type.
16828 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
16829 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
16830 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
16831 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16832 << "omp_allocator_handle_t";
16833 return false;
16834 }
16835 QualType AllocatorHandleEnumTy = PT.get();
16836 AllocatorHandleEnumTy.addConst();
16837 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
16838
16839 // Fill the predefined allocator map.
16840 bool ErrorFound = false;
16841 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
16842 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
16843 StringRef Allocator =
16844 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
16845 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
16846 auto *VD = dyn_cast_or_null<ValueDecl>(
16847 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
16848 if (!VD) {
16849 ErrorFound = true;
16850 break;
16851 }
16852 QualType AllocatorType =
16854 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
16855 if (!Res.isUsable()) {
16856 ErrorFound = true;
16857 break;
16858 }
16859 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
16861 /* AllowExplicit */ true);
16862 if (!Res.isUsable()) {
16863 ErrorFound = true;
16864 break;
16865 }
16866 Stack->setAllocator(AllocatorKind, Res.get());
16867 }
16868 if (ErrorFound) {
16869 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16870 << "omp_allocator_handle_t";
16871 return false;
16872 }
16873
16874 return true;
16875}
16876
16878 SourceLocation LParenLoc,
16879 SourceLocation EndLoc) {
16880 // OpenMP [2.11.3, allocate Directive, Description]
16881 // allocator is an expression of omp_allocator_handle_t type.
16882 if (!findOMPAllocatorHandleT(*this, A->getExprLoc(), DSAStack))
16883 return nullptr;
16884
16885 ExprResult Allocator = DefaultLvalueConversion(A);
16886 if (Allocator.isInvalid())
16887 return nullptr;
16888 Allocator = PerformImplicitConversion(Allocator.get(),
16889 DSAStack->getOMPAllocatorHandleT(),
16891 /*AllowExplicit=*/true);
16892 if (Allocator.isInvalid())
16893 return nullptr;
16894 return new (Context)
16895 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
16896}
16897
16899 SourceLocation StartLoc,
16900 SourceLocation LParenLoc,
16901 SourceLocation EndLoc) {
16902 // OpenMP [2.7.1, loop construct, Description]
16903 // OpenMP [2.8.1, simd construct, Description]
16904 // OpenMP [2.9.6, distribute construct, Description]
16905 // The parameter of the collapse clause must be a constant
16906 // positive integer expression.
16907 ExprResult NumForLoopsResult =
16908 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
16909 if (NumForLoopsResult.isInvalid())
16910 return nullptr;
16911 return new (Context)
16912 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
16913}
16914
16916 SourceLocation EndLoc,
16917 SourceLocation LParenLoc,
16918 Expr *NumForLoops) {
16919 // OpenMP [2.7.1, loop construct, Description]
16920 // OpenMP [2.8.1, simd construct, Description]
16921 // OpenMP [2.9.6, distribute construct, Description]
16922 // The parameter of the ordered clause must be a constant
16923 // positive integer expression if any.
16924 if (NumForLoops && LParenLoc.isValid()) {
16925 ExprResult NumForLoopsResult =
16926 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
16927 if (NumForLoopsResult.isInvalid())
16928 return nullptr;
16929 NumForLoops = NumForLoopsResult.get();
16930 } else {
16931 NumForLoops = nullptr;
16932 }
16933 auto *Clause = OMPOrderedClause::Create(
16934 Context, NumForLoops, NumForLoops ? DSAStack->getAssociatedLoops() : 0,
16935 StartLoc, LParenLoc, EndLoc);
16936 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
16937 return Clause;
16938}
16939
16941 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
16942 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16943 OMPClause *Res = nullptr;
16944 switch (Kind) {
16945 case OMPC_default:
16946 Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument),
16947 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16948 break;
16949 case OMPC_proc_bind:
16950 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
16951 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16952 break;
16953 case OMPC_atomic_default_mem_order:
16955 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
16956 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16957 break;
16958 case OMPC_fail:
16960 static_cast<OpenMPClauseKind>(Argument),
16961 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16962 break;
16963 case OMPC_update:
16964 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
16965 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16966 break;
16967 case OMPC_bind:
16968 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
16969 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16970 break;
16971 case OMPC_at:
16972 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
16973 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16974 break;
16975 case OMPC_severity:
16977 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
16978 LParenLoc, EndLoc);
16979 break;
16980 case OMPC_if:
16981 case OMPC_final:
16982 case OMPC_num_threads:
16983 case OMPC_safelen:
16984 case OMPC_simdlen:
16985 case OMPC_sizes:
16986 case OMPC_allocator:
16987 case OMPC_collapse:
16988 case OMPC_schedule:
16989 case OMPC_private:
16990 case OMPC_firstprivate:
16991 case OMPC_lastprivate:
16992 case OMPC_shared:
16993 case OMPC_reduction:
16994 case OMPC_task_reduction:
16995 case OMPC_in_reduction:
16996 case OMPC_linear:
16997 case OMPC_aligned:
16998 case OMPC_copyin:
16999 case OMPC_copyprivate:
17000 case OMPC_ordered:
17001 case OMPC_nowait:
17002 case OMPC_untied:
17003 case OMPC_mergeable:
17004 case OMPC_threadprivate:
17005 case OMPC_allocate:
17006 case OMPC_flush:
17007 case OMPC_depobj:
17008 case OMPC_read:
17009 case OMPC_write:
17010 case OMPC_capture:
17011 case OMPC_compare:
17012 case OMPC_seq_cst:
17013 case OMPC_acq_rel:
17014 case OMPC_acquire:
17015 case OMPC_release:
17016 case OMPC_relaxed:
17017 case OMPC_depend:
17018 case OMPC_device:
17019 case OMPC_threads:
17020 case OMPC_simd:
17021 case OMPC_map:
17022 case OMPC_num_teams:
17023 case OMPC_thread_limit:
17024 case OMPC_priority:
17025 case OMPC_grainsize:
17026 case OMPC_nogroup:
17027 case OMPC_num_tasks:
17028 case OMPC_hint:
17029 case OMPC_dist_schedule:
17030 case OMPC_defaultmap:
17031 case OMPC_unknown:
17032 case OMPC_uniform:
17033 case OMPC_to:
17034 case OMPC_from:
17035 case OMPC_use_device_ptr:
17036 case OMPC_use_device_addr:
17037 case OMPC_is_device_ptr:
17038 case OMPC_has_device_addr:
17039 case OMPC_unified_address:
17040 case OMPC_unified_shared_memory:
17041 case OMPC_reverse_offload:
17042 case OMPC_dynamic_allocators:
17043 case OMPC_device_type:
17044 case OMPC_match:
17045 case OMPC_nontemporal:
17046 case OMPC_destroy:
17047 case OMPC_novariants:
17048 case OMPC_nocontext:
17049 case OMPC_detach:
17050 case OMPC_inclusive:
17051 case OMPC_exclusive:
17052 case OMPC_uses_allocators:
17053 case OMPC_affinity:
17054 case OMPC_when:
17055 case OMPC_message:
17056 default:
17057 llvm_unreachable("Clause is not allowed.");
17058 }
17059 return Res;
17060}
17061
17062static std::string
17064 ArrayRef<unsigned> Exclude = std::nullopt) {
17065 SmallString<256> Buffer;
17066 llvm::raw_svector_ostream Out(Buffer);
17067 unsigned Skipped = Exclude.size();
17068 for (unsigned I = First; I < Last; ++I) {
17069 if (llvm::is_contained(Exclude, I)) {
17070 --Skipped;
17071 continue;
17072 }
17073 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
17074 if (I + Skipped + 2 == Last)
17075 Out << " or ";
17076 else if (I + Skipped + 1 != Last)
17077 Out << ", ";
17078 }
17079 return std::string(Out.str());
17080}
17081
17083 SourceLocation KindKwLoc,
17084 SourceLocation StartLoc,
17085 SourceLocation LParenLoc,
17086 SourceLocation EndLoc) {
17087 if (Kind == OMP_DEFAULT_unknown) {
17088 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17089 << getListOfPossibleValues(OMPC_default, /*First=*/0,
17090 /*Last=*/unsigned(OMP_DEFAULT_unknown))
17091 << getOpenMPClauseName(OMPC_default);
17092 return nullptr;
17093 }
17094
17095 switch (Kind) {
17096 case OMP_DEFAULT_none:
17097 DSAStack->setDefaultDSANone(KindKwLoc);
17098 break;
17099 case OMP_DEFAULT_shared:
17100 DSAStack->setDefaultDSAShared(KindKwLoc);
17101 break;
17102 case OMP_DEFAULT_firstprivate:
17103 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
17104 break;
17105 case OMP_DEFAULT_private:
17106 DSAStack->setDefaultDSAPrivate(KindKwLoc);
17107 break;
17108 default:
17109 llvm_unreachable("DSA unexpected in OpenMP default clause");
17110 }
17111
17112 return new (Context)
17113 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17114}
17115
17117 SourceLocation KindKwLoc,
17118 SourceLocation StartLoc,
17119 SourceLocation LParenLoc,
17120 SourceLocation EndLoc) {
17121 if (Kind == OMP_PROC_BIND_unknown) {
17122 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17123 << getListOfPossibleValues(OMPC_proc_bind,
17124 /*First=*/unsigned(OMP_PROC_BIND_master),
17125 /*Last=*/
17126 unsigned(LangOpts.OpenMP > 50
17127 ? OMP_PROC_BIND_primary
17128 : OMP_PROC_BIND_spread) +
17129 1)
17130 << getOpenMPClauseName(OMPC_proc_bind);
17131 return nullptr;
17132 }
17133 if (Kind == OMP_PROC_BIND_primary && LangOpts.OpenMP < 51)
17134 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17135 << getListOfPossibleValues(OMPC_proc_bind,
17136 /*First=*/unsigned(OMP_PROC_BIND_master),
17137 /*Last=*/
17138 unsigned(OMP_PROC_BIND_spread) + 1)
17139 << getOpenMPClauseName(OMPC_proc_bind);
17140 return new (Context)
17141 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17142}
17143
17146 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17148 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17150 OMPC_atomic_default_mem_order, /*First=*/0,
17152 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
17153 return nullptr;
17154 }
17155 return new (Context) OMPAtomicDefaultMemOrderClause(Kind, KindKwLoc, StartLoc,
17156 LParenLoc, EndLoc);
17157}
17158
17160 SourceLocation KindKwLoc,
17161 SourceLocation StartLoc,
17162 SourceLocation LParenLoc,
17163 SourceLocation EndLoc) {
17164 if (Kind == OMPC_AT_unknown) {
17165 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17166 << getListOfPossibleValues(OMPC_at, /*First=*/0,
17167 /*Last=*/OMPC_AT_unknown)
17168 << getOpenMPClauseName(OMPC_at);
17169 return nullptr;
17170 }
17171 return new (Context)
17172 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17173}
17174
17176 SourceLocation KindKwLoc,
17177 SourceLocation StartLoc,
17178 SourceLocation LParenLoc,
17179 SourceLocation EndLoc) {
17180 if (Kind == OMPC_SEVERITY_unknown) {
17181 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17182 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
17183 /*Last=*/OMPC_SEVERITY_unknown)
17184 << getOpenMPClauseName(OMPC_severity);
17185 return nullptr;
17186 }
17187 return new (Context)
17188 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17189}
17190
17192 SourceLocation LParenLoc,
17193 SourceLocation EndLoc) {
17194 assert(ME && "NULL expr in Message clause");
17195 if (!isa<StringLiteral>(ME)) {
17196 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
17197 << getOpenMPClauseName(OMPC_message);
17198 return nullptr;
17199 }
17200 return new (Context) OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc);
17201}
17202
17205 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
17206 SourceLocation KindLoc, SourceLocation EndLoc) {
17207 if (Kind != OMPC_ORDER_concurrent ||
17208 (LangOpts.OpenMP < 51 && MLoc.isValid())) {
17209 // Kind should be concurrent,
17210 // Modifiers introduced in OpenMP 5.1
17211 static_assert(OMPC_ORDER_unknown > 0,
17212 "OMPC_ORDER_unknown not greater than 0");
17213
17214 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17215 << getListOfPossibleValues(OMPC_order,
17216 /*First=*/0,
17217 /*Last=*/OMPC_ORDER_unknown)
17218 << getOpenMPClauseName(OMPC_order);
17219 return nullptr;
17220 }
17221 if (LangOpts.OpenMP >= 51) {
17222 if (Modifier == OMPC_ORDER_MODIFIER_unknown && MLoc.isValid()) {
17223 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17224 << getListOfPossibleValues(OMPC_order,
17225 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
17226 /*Last=*/OMPC_ORDER_MODIFIER_last)
17227 << getOpenMPClauseName(OMPC_order);
17228 } else {
17229 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
17230 if (DSAStack->getCurScope()) {
17231 // mark the current scope with 'order' flag
17232 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
17233 DSAStack->getCurScope()->setFlags(existingFlags |
17235 }
17236 }
17237 }
17238 return new (Context) OMPOrderClause(Kind, KindLoc, StartLoc, LParenLoc,
17239 EndLoc, Modifier, MLoc);
17240}
17241
17243 SourceLocation KindKwLoc,
17244 SourceLocation StartLoc,
17245 SourceLocation LParenLoc,
17246 SourceLocation EndLoc) {
17247 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
17248 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
17249 SmallVector<unsigned> Except = {
17250 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
17251 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
17252 if (LangOpts.OpenMP < 51)
17253 Except.push_back(OMPC_DEPEND_inoutset);
17254 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17255 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
17256 /*Last=*/OMPC_DEPEND_unknown, Except)
17257 << getOpenMPClauseName(OMPC_update);
17258 return nullptr;
17259 }
17260 return OMPUpdateClause::Create(Context, StartLoc, LParenLoc, KindKwLoc, Kind,
17261 EndLoc);
17262}
17263
17265 SourceLocation StartLoc,
17266 SourceLocation LParenLoc,
17267 SourceLocation EndLoc) {
17268 for (Expr *SizeExpr : SizeExprs) {
17270 SizeExpr, OMPC_sizes, /*StrictlyPositive=*/true);
17271 if (!NumForLoopsResult.isUsable())
17272 return nullptr;
17273 }
17274
17275 DSAStack->setAssociatedLoops(SizeExprs.size());
17276 return OMPSizesClause::Create(Context, StartLoc, LParenLoc, EndLoc,
17277 SizeExprs);
17278}
17279
17281 SourceLocation EndLoc) {
17282 return OMPFullClause::Create(Context, StartLoc, EndLoc);
17283}
17284
17286 SourceLocation StartLoc,
17287 SourceLocation LParenLoc,
17288 SourceLocation EndLoc) {
17289 if (FactorExpr) {
17290 // If an argument is specified, it must be a constant (or an unevaluated
17291 // template expression).
17293 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
17294 if (FactorResult.isInvalid())
17295 return nullptr;
17296 FactorExpr = FactorResult.get();
17297 }
17298
17299 return OMPPartialClause::Create(Context, StartLoc, LParenLoc, EndLoc,
17300 FactorExpr);
17301}
17302
17304 SourceLocation LParenLoc,
17305 SourceLocation EndLoc) {
17306 ExprResult AlignVal;
17307 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
17308 if (AlignVal.isInvalid())
17309 return nullptr;
17310 return OMPAlignClause::Create(Context, AlignVal.get(), StartLoc, LParenLoc,
17311 EndLoc);
17312}
17313
17316 SourceLocation StartLoc, SourceLocation LParenLoc,
17317 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
17318 SourceLocation EndLoc) {
17319 OMPClause *Res = nullptr;
17320 switch (Kind) {
17321 case OMPC_schedule:
17322 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
17323 assert(Argument.size() == NumberOfElements &&
17324 ArgumentLoc.size() == NumberOfElements);
17326 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
17327 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
17328 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
17329 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
17330 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
17331 break;
17332 case OMPC_if:
17333 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17334 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
17335 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
17336 DelimLoc, EndLoc);
17337 break;
17338 case OMPC_dist_schedule:
17340 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
17341 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
17342 break;
17343 case OMPC_defaultmap:
17344 enum { Modifier, DefaultmapKind };
17346 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
17347 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
17348 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
17349 EndLoc);
17350 break;
17351 case OMPC_order:
17352 enum { OrderModifier, OrderKind };
17354 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
17355 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
17356 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
17357 break;
17358 case OMPC_device:
17359 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17361 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
17362 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17363 break;
17364 case OMPC_grainsize:
17365 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17366 "Modifier for grainsize clause and its location are expected.");
17368 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
17369 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17370 break;
17371 case OMPC_num_tasks:
17372 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17373 "Modifier for num_tasks clause and its location are expected.");
17375 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
17376 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17377 break;
17378 case OMPC_final:
17379 case OMPC_num_threads:
17380 case OMPC_safelen:
17381 case OMPC_simdlen:
17382 case OMPC_sizes:
17383 case OMPC_allocator:
17384 case OMPC_collapse:
17385 case OMPC_default:
17386 case OMPC_proc_bind:
17387 case OMPC_private:
17388 case OMPC_firstprivate:
17389 case OMPC_lastprivate:
17390 case OMPC_shared:
17391 case OMPC_reduction:
17392 case OMPC_task_reduction:
17393 case OMPC_in_reduction:
17394 case OMPC_linear:
17395 case OMPC_aligned:
17396 case OMPC_copyin:
17397 case OMPC_copyprivate:
17398 case OMPC_ordered:
17399 case OMPC_nowait:
17400 case OMPC_untied:
17401 case OMPC_mergeable:
17402 case OMPC_threadprivate:
17403 case OMPC_allocate:
17404 case OMPC_flush:
17405 case OMPC_depobj:
17406 case OMPC_read:
17407 case OMPC_write:
17408 case OMPC_update:
17409 case OMPC_capture:
17410 case OMPC_compare:
17411 case OMPC_seq_cst:
17412 case OMPC_acq_rel:
17413 case OMPC_acquire:
17414 case OMPC_release:
17415 case OMPC_relaxed:
17416 case OMPC_depend:
17417 case OMPC_threads:
17418 case OMPC_simd:
17419 case OMPC_map:
17420 case OMPC_num_teams:
17421 case OMPC_thread_limit:
17422 case OMPC_priority:
17423 case OMPC_nogroup:
17424 case OMPC_hint:
17425 case OMPC_unknown:
17426 case OMPC_uniform:
17427 case OMPC_to:
17428 case OMPC_from:
17429 case OMPC_use_device_ptr:
17430 case OMPC_use_device_addr:
17431 case OMPC_is_device_ptr:
17432 case OMPC_has_device_addr:
17433 case OMPC_unified_address:
17434 case OMPC_unified_shared_memory:
17435 case OMPC_reverse_offload:
17436 case OMPC_dynamic_allocators:
17437 case OMPC_atomic_default_mem_order:
17438 case OMPC_device_type:
17439 case OMPC_match:
17440 case OMPC_nontemporal:
17441 case OMPC_at:
17442 case OMPC_severity:
17443 case OMPC_message:
17444 case OMPC_destroy:
17445 case OMPC_novariants:
17446 case OMPC_nocontext:
17447 case OMPC_detach:
17448 case OMPC_inclusive:
17449 case OMPC_exclusive:
17450 case OMPC_uses_allocators:
17451 case OMPC_affinity:
17452 case OMPC_when:
17453 case OMPC_bind:
17454 default:
17455 llvm_unreachable("Clause is not allowed.");
17456 }
17457 return Res;
17458}
17459
17462 SourceLocation M1Loc, SourceLocation M2Loc) {
17463 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
17464 SmallVector<unsigned, 2> Excluded;
17466 Excluded.push_back(M2);
17467 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
17468 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
17469 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
17470 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
17471 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
17472 << getListOfPossibleValues(OMPC_schedule,
17473 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
17475 Excluded)
17476 << getOpenMPClauseName(OMPC_schedule);
17477 return true;
17478 }
17479 return false;
17480}
17481
17484 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
17485 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
17486 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
17487 if (checkScheduleModifiers(*this, M1, M2, M1Loc, M2Loc) ||
17488 checkScheduleModifiers(*this, M2, M1, M2Loc, M1Loc))
17489 return nullptr;
17490 // OpenMP, 2.7.1, Loop Construct, Restrictions
17491 // Either the monotonic modifier or the nonmonotonic modifier can be specified
17492 // but not both.
17493 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
17494 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
17495 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
17496 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
17497 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
17498 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
17499 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
17500 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
17501 return nullptr;
17502 }
17503 if (Kind == OMPC_SCHEDULE_unknown) {
17504 std::string Values;
17505 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
17506 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
17507 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17509 Exclude);
17510 } else {
17511 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17512 /*Last=*/OMPC_SCHEDULE_unknown);
17513 }
17514 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17515 << Values << getOpenMPClauseName(OMPC_schedule);
17516 return nullptr;
17517 }
17518 // OpenMP, 2.7.1, Loop Construct, Restrictions
17519 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
17520 // schedule(guided).
17521 // OpenMP 5.0 does not have this restriction.
17522 if (LangOpts.OpenMP < 50 &&
17523 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
17524 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
17525 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
17526 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
17527 diag::err_omp_schedule_nonmonotonic_static);
17528 return nullptr;
17529 }
17530 Expr *ValExpr = ChunkSize;
17531 Stmt *HelperValStmt = nullptr;
17532 if (ChunkSize) {
17533 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
17534 !ChunkSize->isInstantiationDependent() &&
17535 !ChunkSize->containsUnexpandedParameterPack()) {
17536 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
17537 ExprResult Val =
17538 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
17539 if (Val.isInvalid())
17540 return nullptr;
17541
17542 ValExpr = Val.get();
17543
17544 // OpenMP [2.7.1, Restrictions]
17545 // chunk_size must be a loop invariant integer expression with a positive
17546 // value.
17547 if (std::optional<llvm::APSInt> Result =
17548 ValExpr->getIntegerConstantExpr(Context)) {
17549 if (Result->isSigned() && !Result->isStrictlyPositive()) {
17550 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
17551 << "schedule" << 1 << ChunkSize->getSourceRange();
17552 return nullptr;
17553 }
17555 DSAStack->getCurrentDirective(), OMPC_schedule,
17556 LangOpts.OpenMP) != OMPD_unknown &&
17558 ValExpr = MakeFullExpr(ValExpr).get();
17559 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17560 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17561 HelperValStmt = buildPreInits(Context, Captures);
17562 }
17563 }
17564 }
17565
17566 return new (Context)
17567 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
17568 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
17569}
17570
17572 SourceLocation StartLoc,
17573 SourceLocation EndLoc) {
17574 OMPClause *Res = nullptr;
17575 switch (Kind) {
17576 case OMPC_ordered:
17577 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
17578 break;
17579 case OMPC_nowait:
17580 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
17581 break;
17582 case OMPC_untied:
17583 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
17584 break;
17585 case OMPC_mergeable:
17586 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
17587 break;
17588 case OMPC_read:
17589 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
17590 break;
17591 case OMPC_write:
17592 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
17593 break;
17594 case OMPC_update:
17595 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
17596 break;
17597 case OMPC_capture:
17598 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
17599 break;
17600 case OMPC_compare:
17601 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
17602 break;
17603 case OMPC_fail:
17604 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
17605 break;
17606 case OMPC_seq_cst:
17607 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
17608 break;
17609 case OMPC_acq_rel:
17610 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
17611 break;
17612 case OMPC_acquire:
17613 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
17614 break;
17615 case OMPC_release:
17616 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
17617 break;
17618 case OMPC_relaxed:
17619 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
17620 break;
17621 case OMPC_weak:
17622 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
17623 break;
17624 case OMPC_threads:
17625 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
17626 break;
17627 case OMPC_simd:
17628 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
17629 break;
17630 case OMPC_nogroup:
17631 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
17632 break;
17633 case OMPC_unified_address:
17634 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
17635 break;
17636 case OMPC_unified_shared_memory:
17637 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17638 break;
17639 case OMPC_reverse_offload:
17640 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
17641 break;
17642 case OMPC_dynamic_allocators:
17643 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
17644 break;
17645 case OMPC_destroy:
17646 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
17647 /*LParenLoc=*/SourceLocation(),
17648 /*VarLoc=*/SourceLocation(), EndLoc);
17649 break;
17650 case OMPC_full:
17651 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
17652 break;
17653 case OMPC_partial:
17654 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
17655 break;
17656 case OMPC_ompx_bare:
17657 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
17658 break;
17659 case OMPC_if:
17660 case OMPC_final:
17661 case OMPC_num_threads:
17662 case OMPC_safelen:
17663 case OMPC_simdlen:
17664 case OMPC_sizes:
17665 case OMPC_allocator:
17666 case OMPC_collapse:
17667 case OMPC_schedule:
17668 case OMPC_private:
17669 case OMPC_firstprivate:
17670 case OMPC_lastprivate:
17671 case OMPC_shared:
17672 case OMPC_reduction:
17673 case OMPC_task_reduction:
17674 case OMPC_in_reduction:
17675 case OMPC_linear:
17676 case OMPC_aligned:
17677 case OMPC_copyin:
17678 case OMPC_copyprivate:
17679 case OMPC_default:
17680 case OMPC_proc_bind:
17681 case OMPC_threadprivate:
17682 case OMPC_allocate:
17683 case OMPC_flush:
17684 case OMPC_depobj:
17685 case OMPC_depend:
17686 case OMPC_device:
17687 case OMPC_map:
17688 case OMPC_num_teams:
17689 case OMPC_thread_limit:
17690 case OMPC_priority:
17691 case OMPC_grainsize:
17692 case OMPC_num_tasks:
17693 case OMPC_hint:
17694 case OMPC_dist_schedule:
17695 case OMPC_defaultmap:
17696 case OMPC_unknown:
17697 case OMPC_uniform:
17698 case OMPC_to:
17699 case OMPC_from:
17700 case OMPC_use_device_ptr:
17701 case OMPC_use_device_addr:
17702 case OMPC_is_device_ptr:
17703 case OMPC_has_device_addr:
17704 case OMPC_atomic_default_mem_order:
17705 case OMPC_device_type:
17706 case OMPC_match:
17707 case OMPC_nontemporal:
17708 case OMPC_order:
17709 case OMPC_at:
17710 case OMPC_severity:
17711 case OMPC_message:
17712 case OMPC_novariants:
17713 case OMPC_nocontext:
17714 case OMPC_detach:
17715 case OMPC_inclusive:
17716 case OMPC_exclusive:
17717 case OMPC_uses_allocators:
17718 case OMPC_affinity:
17719 case OMPC_when:
17720 case OMPC_ompx_dyn_cgroup_mem:
17721 default:
17722 llvm_unreachable("Clause is not allowed.");
17723 }
17724 return Res;
17725}
17726
17728 SourceLocation EndLoc) {
17729 DSAStack->setNowaitRegion();
17730 return new (Context) OMPNowaitClause(StartLoc, EndLoc);
17731}
17732
17734 SourceLocation EndLoc) {
17735 DSAStack->setUntiedRegion();
17736 return new (Context) OMPUntiedClause(StartLoc, EndLoc);
17737}
17738
17740 SourceLocation EndLoc) {
17741 return new (Context) OMPMergeableClause(StartLoc, EndLoc);
17742}
17743
17745 SourceLocation EndLoc) {
17746 return new (Context) OMPReadClause(StartLoc, EndLoc);
17747}
17748
17750 SourceLocation EndLoc) {
17751 return new (Context) OMPWriteClause(StartLoc, EndLoc);
17752}
17753
17755 SourceLocation EndLoc) {
17756 return OMPUpdateClause::Create(Context, StartLoc, EndLoc);
17757}
17758
17760 SourceLocation EndLoc) {
17761 return new (Context) OMPCaptureClause(StartLoc, EndLoc);
17762}
17763
17765 SourceLocation EndLoc) {
17766 return new (Context) OMPCompareClause(StartLoc, EndLoc);
17767}
17768
17770 SourceLocation EndLoc) {
17771 return new (Context) OMPFailClause(StartLoc, EndLoc);
17772}
17773
17776 SourceLocation StartLoc, SourceLocation LParenLoc,
17777 SourceLocation EndLoc) {
17778
17780 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
17781 return nullptr;
17782 }
17783 return new (Context)
17784 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
17785}
17786
17788 SourceLocation EndLoc) {
17789 return new (Context) OMPSeqCstClause(StartLoc, EndLoc);
17790}
17791
17793 SourceLocation EndLoc) {
17794 return new (Context) OMPAcqRelClause(StartLoc, EndLoc);
17795}
17796
17798 SourceLocation EndLoc) {
17799 return new (Context) OMPAcquireClause(StartLoc, EndLoc);
17800}
17801
17803 SourceLocation EndLoc) {
17804 return new (Context) OMPReleaseClause(StartLoc, EndLoc);
17805}
17806
17808 SourceLocation EndLoc) {
17809 return new (Context) OMPRelaxedClause(StartLoc, EndLoc);
17810}
17811
17813 SourceLocation EndLoc) {
17814 return new (Context) OMPWeakClause(StartLoc, EndLoc);
17815}
17816
17818 SourceLocation EndLoc) {
17819 return new (Context) OMPThreadsClause(StartLoc, EndLoc);
17820}
17821
17823 SourceLocation EndLoc) {
17824 return new (Context) OMPSIMDClause(StartLoc, EndLoc);
17825}
17826
17828 SourceLocation EndLoc) {
17829 return new (Context) OMPNogroupClause(StartLoc, EndLoc);
17830}
17831
17833 SourceLocation EndLoc) {
17834 return new (Context) OMPUnifiedAddressClause(StartLoc, EndLoc);
17835}
17836
17838 SourceLocation EndLoc) {
17839 return new (Context) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17840}
17841
17843 SourceLocation EndLoc) {
17844 return new (Context) OMPReverseOffloadClause(StartLoc, EndLoc);
17845}
17846
17848 SourceLocation EndLoc) {
17849 return new (Context) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
17850}
17851
17853 SourceLocation StartLoc,
17854 SourceLocation EndLoc) {
17855
17856 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17857 // At least one action-clause must appear on a directive.
17858 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
17859 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
17860 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
17861 << Expected << getOpenMPDirectiveName(OMPD_interop);
17862 return StmtError();
17863 }
17864
17865 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17866 // A depend clause can only appear on the directive if a targetsync
17867 // interop-type is present or the interop-var was initialized with
17868 // the targetsync interop-type.
17869
17870 // If there is any 'init' clause diagnose if there is no 'init' clause with
17871 // interop-type of 'targetsync'. Cases involving other directives cannot be
17872 // diagnosed.
17873 const OMPDependClause *DependClause = nullptr;
17874 bool HasInitClause = false;
17875 bool IsTargetSync = false;
17876 for (const OMPClause *C : Clauses) {
17877 if (IsTargetSync)
17878 break;
17879 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
17880 HasInitClause = true;
17881 if (InitClause->getIsTargetSync())
17882 IsTargetSync = true;
17883 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
17884 DependClause = DC;
17885 }
17886 }
17887 if (DependClause && HasInitClause && !IsTargetSync) {
17888 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
17889 return StmtError();
17890 }
17891
17892 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17893 // Each interop-var may be specified for at most one action-clause of each
17894 // interop construct.
17896 for (OMPClause *C : Clauses) {
17897 OpenMPClauseKind ClauseKind = C->getClauseKind();
17898 std::pair<ValueDecl *, bool> DeclResult;
17899 SourceLocation ELoc;
17900 SourceRange ERange;
17901
17902 if (ClauseKind == OMPC_init) {
17903 auto *E = cast<OMPInitClause>(C)->getInteropVar();
17904 DeclResult = getPrivateItem(*this, E, ELoc, ERange);
17905 } else if (ClauseKind == OMPC_use) {
17906 auto *E = cast<OMPUseClause>(C)->getInteropVar();
17907 DeclResult = getPrivateItem(*this, E, ELoc, ERange);
17908 } else if (ClauseKind == OMPC_destroy) {
17909 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
17910 DeclResult = getPrivateItem(*this, E, ELoc, ERange);
17911 }
17912
17913 if (DeclResult.first) {
17914 if (!InteropVars.insert(DeclResult.first).second) {
17915 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
17916 << DeclResult.first;
17917 return StmtError();
17918 }
17919 }
17920 }
17921
17922 return OMPInteropDirective::Create(Context, StartLoc, EndLoc, Clauses);
17923}
17924
17925static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
17926 SourceLocation VarLoc,
17927 OpenMPClauseKind Kind) {
17928 SourceLocation ELoc;
17929 SourceRange ERange;
17930 Expr *RefExpr = InteropVarExpr;
17931 auto Res =
17932 getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
17933 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
17934
17935 if (Res.second) {
17936 // It will be analyzed later.
17937 return true;
17938 }
17939
17940 if (!Res.first)
17941 return false;
17942
17943 // Interop variable should be of type omp_interop_t.
17944 bool HasError = false;
17945 QualType InteropType;
17946 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
17947 VarLoc, Sema::LookupOrdinaryName);
17948 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
17949 NamedDecl *ND = Result.getFoundDecl();
17950 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
17951 InteropType = QualType(TD->getTypeForDecl(), 0);
17952 } else {
17953 HasError = true;
17954 }
17955 } else {
17956 HasError = true;
17957 }
17958
17959 if (HasError) {
17960 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
17961 << "omp_interop_t";
17962 return false;
17963 }
17964
17965 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
17966 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
17967 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
17968 return false;
17969 }
17970
17971 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17972 // The interop-var passed to init or destroy must be non-const.
17973 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
17974 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
17975 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
17976 << /*non-const*/ 1;
17977 return false;
17978 }
17979 return true;
17980}
17981
17982OMPClause *
17984 SourceLocation StartLoc, SourceLocation LParenLoc,
17985 SourceLocation VarLoc, SourceLocation EndLoc) {
17986
17987 if (!isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_init))
17988 return nullptr;
17989
17990 // Check prefer_type values. These foreign-runtime-id values are either
17991 // string literals or constant integral expressions.
17992 for (const Expr *E : InteropInfo.PreferTypes) {
17993 if (E->isValueDependent() || E->isTypeDependent() ||
17995 continue;
17997 continue;
17998 if (isa<StringLiteral>(E))
17999 continue;
18000 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
18001 return nullptr;
18002 }
18003
18004 return OMPInitClause::Create(Context, InteropVar, InteropInfo, StartLoc,
18005 LParenLoc, VarLoc, EndLoc);
18006}
18007
18009 SourceLocation LParenLoc,
18010 SourceLocation VarLoc,
18011 SourceLocation EndLoc) {
18012
18013 if (!isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_use))
18014 return nullptr;
18015
18016 return new (Context)
18017 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18018}
18019
18021 SourceLocation StartLoc,
18022 SourceLocation LParenLoc,
18023 SourceLocation VarLoc,
18024 SourceLocation EndLoc) {
18025 if (!InteropVar && LangOpts.OpenMP >= 52 &&
18026 DSAStack->getCurrentDirective() == OMPD_depobj) {
18027 Diag(StartLoc, diag::err_omp_expected_clause_argument)
18028 << getOpenMPClauseName(OMPC_destroy)
18029 << getOpenMPDirectiveName(OMPD_depobj);
18030 return nullptr;
18031 }
18032 if (InteropVar &&
18033 !isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_destroy))
18034 return nullptr;
18035
18036 return new (Context)
18037 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18038}
18039
18041 SourceLocation StartLoc,
18042 SourceLocation LParenLoc,
18043 SourceLocation EndLoc) {
18044 Expr *ValExpr = Condition;
18045 Stmt *HelperValStmt = nullptr;
18046 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18047 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18048 !Condition->isInstantiationDependent() &&
18049 !Condition->containsUnexpandedParameterPack()) {
18051 if (Val.isInvalid())
18052 return nullptr;
18053
18054 ValExpr = MakeFullExpr(Val.get()).get();
18055
18056 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18057 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
18058 LangOpts.OpenMP);
18059 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
18060 ValExpr = MakeFullExpr(ValExpr).get();
18061 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18062 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
18063 HelperValStmt = buildPreInits(Context, Captures);
18064 }
18065 }
18066
18067 return new (Context) OMPNovariantsClause(
18068 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18069}
18070
18072 SourceLocation StartLoc,
18073 SourceLocation LParenLoc,
18074 SourceLocation EndLoc) {
18075 Expr *ValExpr = Condition;
18076 Stmt *HelperValStmt = nullptr;
18077 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18078 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18079 !Condition->isInstantiationDependent() &&
18080 !Condition->containsUnexpandedParameterPack()) {
18082 if (Val.isInvalid())
18083 return nullptr;
18084
18085 ValExpr = MakeFullExpr(Val.get()).get();
18086
18087 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18088 CaptureRegion =
18089 getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext, LangOpts.OpenMP);
18090 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
18091 ValExpr = MakeFullExpr(ValExpr).get();
18092 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18093 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
18094 HelperValStmt = buildPreInits(Context, Captures);
18095 }
18096 }
18097
18098 return new (Context) OMPNocontextClause(ValExpr, HelperValStmt, CaptureRegion,
18099 StartLoc, LParenLoc, EndLoc);
18100}
18101
18103 SourceLocation StartLoc,
18104 SourceLocation LParenLoc,
18105 SourceLocation EndLoc) {
18106 Expr *ValExpr = ThreadID;
18107 Stmt *HelperValStmt = nullptr;
18108
18109 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18110 OpenMPDirectiveKind CaptureRegion =
18111 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, LangOpts.OpenMP);
18112 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
18113 ValExpr = MakeFullExpr(ValExpr).get();
18114 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18115 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
18116 HelperValStmt = buildPreInits(Context, Captures);
18117 }
18118
18119 return new (Context) OMPFilterClause(ValExpr, HelperValStmt, CaptureRegion,
18120 StartLoc, LParenLoc, EndLoc);
18121}
18122
18124 ArrayRef<Expr *> VarList,
18125 const OMPVarListLocTy &Locs,
18127 SourceLocation StartLoc = Locs.StartLoc;
18128 SourceLocation LParenLoc = Locs.LParenLoc;
18129 SourceLocation EndLoc = Locs.EndLoc;
18130 OMPClause *Res = nullptr;
18131 int ExtraModifier = Data.ExtraModifier;
18132 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
18133 SourceLocation ColonLoc = Data.ColonLoc;
18134 switch (Kind) {
18135 case OMPC_private:
18136 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18137 break;
18138 case OMPC_firstprivate:
18139 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18140 break;
18141 case OMPC_lastprivate:
18142 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
18143 "Unexpected lastprivate modifier.");
18145 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
18146 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
18147 break;
18148 case OMPC_shared:
18149 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
18150 break;
18151 case OMPC_reduction:
18152 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
18153 "Unexpected lastprivate modifier.");
18155 VarList, static_cast<OpenMPReductionClauseModifier>(ExtraModifier),
18156 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
18157 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18158 break;
18159 case OMPC_task_reduction:
18161 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18162 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18163 break;
18164 case OMPC_in_reduction:
18166 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18167 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18168 break;
18169 case OMPC_linear:
18170 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
18171 "Unexpected linear modifier.");
18173 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
18174 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
18175 ColonLoc, Data.StepModifierLoc, EndLoc);
18176 break;
18177 case OMPC_aligned:
18178 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
18179 LParenLoc, ColonLoc, EndLoc);
18180 break;
18181 case OMPC_copyin:
18182 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
18183 break;
18184 case OMPC_copyprivate:
18185 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18186 break;
18187 case OMPC_flush:
18188 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
18189 break;
18190 case OMPC_depend:
18191 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
18192 "Unexpected depend modifier.");
18194 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
18195 ColonLoc, Data.OmpAllMemoryLoc},
18196 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
18197 break;
18198 case OMPC_map:
18199 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
18200 "Unexpected map modifier.");
18202 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
18203 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
18204 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
18205 ExtraModifierLoc, ColonLoc, VarList, Locs);
18206 break;
18207 case OMPC_to:
18208 Res =
18209 ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc,
18210 Data.ReductionOrMapperIdScopeSpec,
18211 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
18212 break;
18213 case OMPC_from:
18214 Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc,
18215 Data.ReductionOrMapperIdScopeSpec,
18216 Data.ReductionOrMapperId, ColonLoc, VarList,
18217 Locs);
18218 break;
18219 case OMPC_use_device_ptr:
18220 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
18221 break;
18222 case OMPC_use_device_addr:
18223 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
18224 break;
18225 case OMPC_is_device_ptr:
18226 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
18227 break;
18228 case OMPC_has_device_addr:
18229 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
18230 break;
18231 case OMPC_allocate:
18232 Res = ActOnOpenMPAllocateClause(Data.DepModOrTailExpr, VarList, StartLoc,
18233 LParenLoc, ColonLoc, EndLoc);
18234 break;
18235 case OMPC_nontemporal:
18236 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
18237 break;
18238 case OMPC_inclusive:
18239 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18240 break;
18241 case OMPC_exclusive:
18242 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18243 break;
18244 case OMPC_affinity:
18245 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
18246 Data.DepModOrTailExpr, VarList);
18247 break;
18248 case OMPC_doacross:
18250 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
18251 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
18252 break;
18253 case OMPC_if:
18254 case OMPC_depobj:
18255 case OMPC_final:
18256 case OMPC_num_threads:
18257 case OMPC_safelen:
18258 case OMPC_simdlen:
18259 case OMPC_sizes:
18260 case OMPC_allocator:
18261 case OMPC_collapse:
18262 case OMPC_default:
18263 case OMPC_proc_bind:
18264 case OMPC_schedule:
18265 case OMPC_ordered:
18266 case OMPC_nowait:
18267 case OMPC_untied:
18268 case OMPC_mergeable:
18269 case OMPC_threadprivate:
18270 case OMPC_read:
18271 case OMPC_write:
18272 case OMPC_update:
18273 case OMPC_capture:
18274 case OMPC_compare:
18275 case OMPC_seq_cst:
18276 case OMPC_acq_rel:
18277 case OMPC_acquire:
18278 case OMPC_release:
18279 case OMPC_relaxed:
18280 case OMPC_device:
18281 case OMPC_threads:
18282 case OMPC_simd:
18283 case OMPC_num_teams:
18284 case OMPC_thread_limit:
18285 case OMPC_priority:
18286 case OMPC_grainsize:
18287 case OMPC_nogroup:
18288 case OMPC_num_tasks:
18289 case OMPC_hint:
18290 case OMPC_dist_schedule:
18291 case OMPC_defaultmap:
18292 case OMPC_unknown:
18293 case OMPC_uniform:
18294 case OMPC_unified_address:
18295 case OMPC_unified_shared_memory:
18296 case OMPC_reverse_offload:
18297 case OMPC_dynamic_allocators:
18298 case OMPC_atomic_default_mem_order:
18299 case OMPC_device_type:
18300 case OMPC_match:
18301 case OMPC_order:
18302 case OMPC_at:
18303 case OMPC_severity:
18304 case OMPC_message:
18305 case OMPC_destroy:
18306 case OMPC_novariants:
18307 case OMPC_nocontext:
18308 case OMPC_detach:
18309 case OMPC_uses_allocators:
18310 case OMPC_when:
18311 case OMPC_bind:
18312 default:
18313 llvm_unreachable("Clause is not allowed.");
18314 }
18315 return Res;
18316}
18317
18321 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
18322 if (!Res.isUsable())
18323 return ExprError();
18324 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
18325 Res = CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
18326 if (!Res.isUsable())
18327 return ExprError();
18328 }
18329 if (VK != VK_LValue && Res.get()->isGLValue()) {
18330 Res = DefaultLvalueConversion(Res.get());
18331 if (!Res.isUsable())
18332 return ExprError();
18333 }
18334 return Res;
18335}
18336
18338 SourceLocation StartLoc,
18339 SourceLocation LParenLoc,
18340 SourceLocation EndLoc) {
18342 SmallVector<Expr *, 8> PrivateCopies;
18343 bool IsImplicitClause =
18344 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18345 for (Expr *RefExpr : VarList) {
18346 assert(RefExpr && "NULL expr in OpenMP private clause.");
18347 SourceLocation ELoc;
18348 SourceRange ERange;
18349 Expr *SimpleRefExpr = RefExpr;
18350 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18351 if (Res.second) {
18352 // It will be analyzed later.
18353 Vars.push_back(RefExpr);
18354 PrivateCopies.push_back(nullptr);
18355 }
18356 ValueDecl *D = Res.first;
18357 if (!D)
18358 continue;
18359
18360 QualType Type = D->getType();
18361 auto *VD = dyn_cast<VarDecl>(D);
18362
18363 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18364 // A variable that appears in a private clause must not have an incomplete
18365 // type or a reference type.
18366 if (RequireCompleteType(ELoc, Type, diag::err_omp_private_incomplete_type))
18367 continue;
18368 Type = Type.getNonReferenceType();
18369
18370 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18371 // A variable that is privatized must not have a const-qualified type
18372 // unless it is of class type with a mutable member. This restriction does
18373 // not apply to the firstprivate clause.
18374 //
18375 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
18376 // A variable that appears in a private clause must not have a
18377 // const-qualified type unless it is of class type with a mutable member.
18378 if (rejectConstNotMutableType(*this, D, Type, OMPC_private, ELoc))
18379 continue;
18380
18381 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18382 // in a Construct]
18383 // Variables with the predetermined data-sharing attributes may not be
18384 // listed in data-sharing attributes clauses, except for the cases
18385 // listed below. For these exceptions only, listing a predetermined
18386 // variable in a data-sharing attribute clause is allowed and overrides
18387 // the variable's predetermined data-sharing attributes.
18388 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18389 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
18390 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
18391 << getOpenMPClauseName(OMPC_private);
18392 reportOriginalDsa(*this, DSAStack, D, DVar);
18393 continue;
18394 }
18395
18396 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18397 // Variably modified types are not supported for tasks.
18399 isOpenMPTaskingDirective(CurrDir)) {
18400 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18401 << getOpenMPClauseName(OMPC_private) << Type
18402 << getOpenMPDirectiveName(CurrDir);
18403 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18405 Diag(D->getLocation(),
18406 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18407 << D;
18408 continue;
18409 }
18410
18411 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18412 // A list item cannot appear in both a map clause and a data-sharing
18413 // attribute clause on the same construct
18414 //
18415 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18416 // A list item cannot appear in both a map clause and a data-sharing
18417 // attribute clause on the same construct unless the construct is a
18418 // combined construct.
18419 if ((LangOpts.OpenMP <= 45 && isOpenMPTargetExecutionDirective(CurrDir)) ||
18420 CurrDir == OMPD_target) {
18421 OpenMPClauseKind ConflictKind;
18422 if (DSAStack->checkMappableExprComponentListsForDecl(
18423 VD, /*CurrentRegionOnly=*/true,
18425 OpenMPClauseKind WhereFoundClauseKind) -> bool {
18426 ConflictKind = WhereFoundClauseKind;
18427 return true;
18428 })) {
18429 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18430 << getOpenMPClauseName(OMPC_private)
18431 << getOpenMPClauseName(ConflictKind)
18432 << getOpenMPDirectiveName(CurrDir);
18433 reportOriginalDsa(*this, DSAStack, D, DVar);
18434 continue;
18435 }
18436 }
18437
18438 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
18439 // A variable of class type (or array thereof) that appears in a private
18440 // clause requires an accessible, unambiguous default constructor for the
18441 // class type.
18442 // Generate helper private variable and initialize it with the default
18443 // value. The address of the original variable is replaced by the address of
18444 // the new private variable in CodeGen. This new variable is not added to
18445 // IdResolver, so the code in the OpenMP region uses original variable for
18446 // proper diagnostics.
18447 Type = Type.getUnqualifiedType();
18448 VarDecl *VDPrivate =
18449 buildVarDecl(*this, ELoc, Type, D->getName(),
18450 D->hasAttrs() ? &D->getAttrs() : nullptr,
18451 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18452 ActOnUninitializedDecl(VDPrivate);
18453 if (VDPrivate->isInvalidDecl())
18454 continue;
18455 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18456 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
18457
18458 DeclRefExpr *Ref = nullptr;
18459 if (!VD && !CurContext->isDependentContext()) {
18460 auto *FD = dyn_cast<FieldDecl>(D);
18461 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18462 if (VD)
18463 Ref = buildDeclRefExpr(*this, VD, VD->getType().getNonReferenceType(),
18464 RefExpr->getExprLoc());
18465 else
18466 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
18467 }
18468 if (!IsImplicitClause)
18469 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
18470 Vars.push_back((VD || CurContext->isDependentContext())
18471 ? RefExpr->IgnoreParens()
18472 : Ref);
18473 PrivateCopies.push_back(VDPrivateRefExpr);
18474 }
18475
18476 if (Vars.empty())
18477 return nullptr;
18478
18479 return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars,
18480 PrivateCopies);
18481}
18482
18484 SourceLocation StartLoc,
18485 SourceLocation LParenLoc,
18486 SourceLocation EndLoc) {
18488 SmallVector<Expr *, 8> PrivateCopies;
18490 SmallVector<Decl *, 4> ExprCaptures;
18491 bool IsImplicitClause =
18492 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18493 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
18494
18495 for (Expr *RefExpr : VarList) {
18496 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
18497 SourceLocation ELoc;
18498 SourceRange ERange;
18499 Expr *SimpleRefExpr = RefExpr;
18500 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18501 if (Res.second) {
18502 // It will be analyzed later.
18503 Vars.push_back(RefExpr);
18504 PrivateCopies.push_back(nullptr);
18505 Inits.push_back(nullptr);
18506 }
18507 ValueDecl *D = Res.first;
18508 if (!D)
18509 continue;
18510
18511 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
18512 QualType Type = D->getType();
18513 auto *VD = dyn_cast<VarDecl>(D);
18514
18515 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18516 // A variable that appears in a private clause must not have an incomplete
18517 // type or a reference type.
18518 if (RequireCompleteType(ELoc, Type,
18519 diag::err_omp_firstprivate_incomplete_type))
18520 continue;
18521 Type = Type.getNonReferenceType();
18522
18523 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
18524 // A variable of class type (or array thereof) that appears in a private
18525 // clause requires an accessible, unambiguous copy constructor for the
18526 // class type.
18528
18529 // If an implicit firstprivate variable found it was checked already.
18530 DSAStackTy::DSAVarData TopDVar;
18531 if (!IsImplicitClause) {
18532 DSAStackTy::DSAVarData DVar =
18533 DSAStack->getTopDSA(D, /*FromParent=*/false);
18534 TopDVar = DVar;
18535 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18536 bool IsConstant = ElemType.isConstant(Context);
18537 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
18538 // A list item that specifies a given variable may not appear in more
18539 // than one clause on the same directive, except that a variable may be
18540 // specified in both firstprivate and lastprivate clauses.
18541 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18542 // A list item may appear in a firstprivate or lastprivate clause but not
18543 // both.
18544 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
18545 (isOpenMPDistributeDirective(CurrDir) ||
18546 DVar.CKind != OMPC_lastprivate) &&
18547 DVar.RefExpr) {
18548 Diag(ELoc, diag::err_omp_wrong_dsa)
18549 << getOpenMPClauseName(DVar.CKind)
18550 << getOpenMPClauseName(OMPC_firstprivate);
18551 reportOriginalDsa(*this, DSAStack, D, DVar);
18552 continue;
18553 }
18554
18555 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18556 // in a Construct]
18557 // Variables with the predetermined data-sharing attributes may not be
18558 // listed in data-sharing attributes clauses, except for the cases
18559 // listed below. For these exceptions only, listing a predetermined
18560 // variable in a data-sharing attribute clause is allowed and overrides
18561 // the variable's predetermined data-sharing attributes.
18562 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18563 // in a Construct, C/C++, p.2]
18564 // Variables with const-qualified type having no mutable member may be
18565 // listed in a firstprivate clause, even if they are static data members.
18566 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
18567 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
18568 Diag(ELoc, diag::err_omp_wrong_dsa)
18569 << getOpenMPClauseName(DVar.CKind)
18570 << getOpenMPClauseName(OMPC_firstprivate);
18571 reportOriginalDsa(*this, DSAStack, D, DVar);
18572 continue;
18573 }
18574
18575 // OpenMP [2.9.3.4, Restrictions, p.2]
18576 // A list item that is private within a parallel region must not appear
18577 // in a firstprivate clause on a worksharing construct if any of the
18578 // worksharing regions arising from the worksharing construct ever bind
18579 // to any of the parallel regions arising from the parallel construct.
18580 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18581 // A list item that is private within a teams region must not appear in a
18582 // firstprivate clause on a distribute construct if any of the distribute
18583 // regions arising from the distribute construct ever bind to any of the
18584 // teams regions arising from the teams construct.
18585 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18586 // A list item that appears in a reduction clause of a teams construct
18587 // must not appear in a firstprivate clause on a distribute construct if
18588 // any of the distribute regions arising from the distribute construct
18589 // ever bind to any of the teams regions arising from the teams construct.
18590 if ((isOpenMPWorksharingDirective(CurrDir) ||
18591 isOpenMPDistributeDirective(CurrDir)) &&
18592 !isOpenMPParallelDirective(CurrDir) &&
18593 !isOpenMPTeamsDirective(CurrDir)) {
18594 DVar = DSAStack->getImplicitDSA(D, true);
18595 if (DVar.CKind != OMPC_shared &&
18596 (isOpenMPParallelDirective(DVar.DKind) ||
18597 isOpenMPTeamsDirective(DVar.DKind) ||
18598 DVar.DKind == OMPD_unknown)) {
18599 Diag(ELoc, diag::err_omp_required_access)
18600 << getOpenMPClauseName(OMPC_firstprivate)
18601 << getOpenMPClauseName(OMPC_shared);
18602 reportOriginalDsa(*this, DSAStack, D, DVar);
18603 continue;
18604 }
18605 }
18606 // OpenMP [2.9.3.4, Restrictions, p.3]
18607 // A list item that appears in a reduction clause of a parallel construct
18608 // must not appear in a firstprivate clause on a worksharing or task
18609 // construct if any of the worksharing or task regions arising from the
18610 // worksharing or task construct ever bind to any of the parallel regions
18611 // arising from the parallel construct.
18612 // OpenMP [2.9.3.4, Restrictions, p.4]
18613 // A list item that appears in a reduction clause in worksharing
18614 // construct must not appear in a firstprivate clause in a task construct
18615 // encountered during execution of any of the worksharing regions arising
18616 // from the worksharing construct.
18617 if (isOpenMPTaskingDirective(CurrDir)) {
18618 DVar = DSAStack->hasInnermostDSA(
18619 D,
18620 [](OpenMPClauseKind C, bool AppliedToPointee) {
18621 return C == OMPC_reduction && !AppliedToPointee;
18622 },
18623 [](OpenMPDirectiveKind K) {
18624 return isOpenMPParallelDirective(K) ||
18627 },
18628 /*FromParent=*/true);
18629 if (DVar.CKind == OMPC_reduction &&
18630 (isOpenMPParallelDirective(DVar.DKind) ||
18631 isOpenMPWorksharingDirective(DVar.DKind) ||
18632 isOpenMPTeamsDirective(DVar.DKind))) {
18633 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
18634 << getOpenMPDirectiveName(DVar.DKind);
18635 reportOriginalDsa(*this, DSAStack, D, DVar);
18636 continue;
18637 }
18638 }
18639
18640 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18641 // A list item cannot appear in both a map clause and a data-sharing
18642 // attribute clause on the same construct
18643 //
18644 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18645 // A list item cannot appear in both a map clause and a data-sharing
18646 // attribute clause on the same construct unless the construct is a
18647 // combined construct.
18648 if ((LangOpts.OpenMP <= 45 &&
18650 CurrDir == OMPD_target) {
18651 OpenMPClauseKind ConflictKind;
18652 if (DSAStack->checkMappableExprComponentListsForDecl(
18653 VD, /*CurrentRegionOnly=*/true,
18654 [&ConflictKind](
18656 OpenMPClauseKind WhereFoundClauseKind) {
18657 ConflictKind = WhereFoundClauseKind;
18658 return true;
18659 })) {
18660 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18661 << getOpenMPClauseName(OMPC_firstprivate)
18662 << getOpenMPClauseName(ConflictKind)
18663 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
18664 reportOriginalDsa(*this, DSAStack, D, DVar);
18665 continue;
18666 }
18667 }
18668 }
18669
18670 // Variably modified types are not supported for tasks.
18672 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
18673 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18674 << getOpenMPClauseName(OMPC_firstprivate) << Type
18675 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
18676 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18678 Diag(D->getLocation(),
18679 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18680 << D;
18681 continue;
18682 }
18683
18684 Type = Type.getUnqualifiedType();
18685 VarDecl *VDPrivate =
18686 buildVarDecl(*this, ELoc, Type, D->getName(),
18687 D->hasAttrs() ? &D->getAttrs() : nullptr,
18688 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18689 // Generate helper private variable and initialize it with the value of the
18690 // original variable. The address of the original variable is replaced by
18691 // the address of the new private variable in the CodeGen. This new variable
18692 // is not added to IdResolver, so the code in the OpenMP region uses
18693 // original variable for proper diagnostics and variable capturing.
18694 Expr *VDInitRefExpr = nullptr;
18695 // For arrays generate initializer for single element and replace it by the
18696 // original array element in CodeGen.
18697 if (Type->isArrayType()) {
18698 VarDecl *VDInit =
18699 buildVarDecl(*this, RefExpr->getExprLoc(), ElemType, D->getName());
18700 VDInitRefExpr = buildDeclRefExpr(*this, VDInit, ElemType, ELoc);
18701 Expr *Init = DefaultLvalueConversion(VDInitRefExpr).get();
18702 ElemType = ElemType.getUnqualifiedType();
18703 VarDecl *VDInitTemp = buildVarDecl(*this, RefExpr->getExprLoc(), ElemType,
18704 ".firstprivate.temp");
18705 InitializedEntity Entity =
18708
18709 InitializationSequence InitSeq(*this, Entity, Kind, Init);
18710 ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Init);
18711 if (Result.isInvalid())
18712 VDPrivate->setInvalidDecl();
18713 else
18714 VDPrivate->setInit(Result.getAs<Expr>());
18715 // Remove temp variable declaration.
18716 Context.Deallocate(VDInitTemp);
18717 } else {
18718 VarDecl *VDInit = buildVarDecl(*this, RefExpr->getExprLoc(), Type,
18719 ".firstprivate.temp");
18720 VDInitRefExpr = buildDeclRefExpr(*this, VDInit, RefExpr->getType(),
18721 RefExpr->getExprLoc());
18722 AddInitializerToDecl(VDPrivate,
18723 DefaultLvalueConversion(VDInitRefExpr).get(),
18724 /*DirectInit=*/false);
18725 }
18726 if (VDPrivate->isInvalidDecl()) {
18727 if (IsImplicitClause) {
18728 Diag(RefExpr->getExprLoc(),
18729 diag::note_omp_task_predetermined_firstprivate_here);
18730 }
18731 continue;
18732 }
18733 CurContext->addDecl(VDPrivate);
18734 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18735 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(),
18736 RefExpr->getExprLoc());
18737 DeclRefExpr *Ref = nullptr;
18738 if (!VD && !CurContext->isDependentContext()) {
18739 if (TopDVar.CKind == OMPC_lastprivate) {
18740 Ref = TopDVar.PrivateCopy;
18741 } else {
18742 auto *FD = dyn_cast<FieldDecl>(D);
18743 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18744 if (VD)
18745 Ref = buildDeclRefExpr(*this, VD, VD->getType().getNonReferenceType(),
18746 RefExpr->getExprLoc());
18747 else
18748 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
18749 if (VD || !isOpenMPCapturedDecl(D))
18750 ExprCaptures.push_back(Ref->getDecl());
18751 }
18752 }
18753 if (!IsImplicitClause)
18754 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
18755 Vars.push_back((VD || CurContext->isDependentContext())
18756 ? RefExpr->IgnoreParens()
18757 : Ref);
18758 PrivateCopies.push_back(VDPrivateRefExpr);
18759 Inits.push_back(VDInitRefExpr);
18760 }
18761
18762 if (Vars.empty())
18763 return nullptr;
18764
18765 return OMPFirstprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
18766 Vars, PrivateCopies, Inits,
18767 buildPreInits(Context, ExprCaptures));
18768}
18769
18772 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
18773 SourceLocation LParenLoc, SourceLocation EndLoc) {
18774 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
18775 assert(ColonLoc.isValid() && "Colon location must be valid.");
18776 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
18777 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
18778 /*Last=*/OMPC_LASTPRIVATE_unknown)
18779 << getOpenMPClauseName(OMPC_lastprivate);
18780 return nullptr;
18781 }
18782
18784 SmallVector<Expr *, 8> SrcExprs;
18785 SmallVector<Expr *, 8> DstExprs;
18786 SmallVector<Expr *, 8> AssignmentOps;
18787 SmallVector<Decl *, 4> ExprCaptures;
18788 SmallVector<Expr *, 4> ExprPostUpdates;
18789 for (Expr *RefExpr : VarList) {
18790 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18791 SourceLocation ELoc;
18792 SourceRange ERange;
18793 Expr *SimpleRefExpr = RefExpr;
18794 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18795 if (Res.second) {
18796 // It will be analyzed later.
18797 Vars.push_back(RefExpr);
18798 SrcExprs.push_back(nullptr);
18799 DstExprs.push_back(nullptr);
18800 AssignmentOps.push_back(nullptr);
18801 }
18802 ValueDecl *D = Res.first;
18803 if (!D)
18804 continue;
18805
18806 QualType Type = D->getType();
18807 auto *VD = dyn_cast<VarDecl>(D);
18808
18809 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
18810 // A variable that appears in a lastprivate clause must not have an
18811 // incomplete type or a reference type.
18812 if (RequireCompleteType(ELoc, Type,
18813 diag::err_omp_lastprivate_incomplete_type))
18814 continue;
18815 Type = Type.getNonReferenceType();
18816
18817 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18818 // A variable that is privatized must not have a const-qualified type
18819 // unless it is of class type with a mutable member. This restriction does
18820 // not apply to the firstprivate clause.
18821 //
18822 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
18823 // A variable that appears in a lastprivate clause must not have a
18824 // const-qualified type unless it is of class type with a mutable member.
18825 if (rejectConstNotMutableType(*this, D, Type, OMPC_lastprivate, ELoc))
18826 continue;
18827
18828 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
18829 // A list item that appears in a lastprivate clause with the conditional
18830 // modifier must be a scalar variable.
18831 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
18832 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
18833 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18835 Diag(D->getLocation(),
18836 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18837 << D;
18838 continue;
18839 }
18840
18841 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18842 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18843 // in a Construct]
18844 // Variables with the predetermined data-sharing attributes may not be
18845 // listed in data-sharing attributes clauses, except for the cases
18846 // listed below.
18847 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18848 // A list item may appear in a firstprivate or lastprivate clause but not
18849 // both.
18850 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18851 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
18852 (isOpenMPDistributeDirective(CurrDir) ||
18853 DVar.CKind != OMPC_firstprivate) &&
18854 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
18855 Diag(ELoc, diag::err_omp_wrong_dsa)
18856 << getOpenMPClauseName(DVar.CKind)
18857 << getOpenMPClauseName(OMPC_lastprivate);
18858 reportOriginalDsa(*this, DSAStack, D, DVar);
18859 continue;
18860 }
18861
18862 // OpenMP [2.14.3.5, Restrictions, p.2]
18863 // A list item that is private within a parallel region, or that appears in
18864 // the reduction clause of a parallel construct, must not appear in a
18865 // lastprivate clause on a worksharing construct if any of the corresponding
18866 // worksharing regions ever binds to any of the corresponding parallel
18867 // regions.
18868 DSAStackTy::DSAVarData TopDVar = DVar;
18869 if (isOpenMPWorksharingDirective(CurrDir) &&
18870 !isOpenMPParallelDirective(CurrDir) &&
18871 !isOpenMPTeamsDirective(CurrDir)) {
18872 DVar = DSAStack->getImplicitDSA(D, true);
18873 if (DVar.CKind != OMPC_shared) {
18874 Diag(ELoc, diag::err_omp_required_access)
18875 << getOpenMPClauseName(OMPC_lastprivate)
18876 << getOpenMPClauseName(OMPC_shared);
18877 reportOriginalDsa(*this, DSAStack, D, DVar);
18878 continue;
18879 }
18880 }
18881
18882 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
18883 // A variable of class type (or array thereof) that appears in a
18884 // lastprivate clause requires an accessible, unambiguous default
18885 // constructor for the class type, unless the list item is also specified
18886 // in a firstprivate clause.
18887 // A variable of class type (or array thereof) that appears in a
18888 // lastprivate clause requires an accessible, unambiguous copy assignment
18889 // operator for the class type.
18891 VarDecl *SrcVD = buildVarDecl(*this, ERange.getBegin(),
18892 Type.getUnqualifiedType(), ".lastprivate.src",
18893 D->hasAttrs() ? &D->getAttrs() : nullptr);
18894 DeclRefExpr *PseudoSrcExpr =
18895 buildDeclRefExpr(*this, SrcVD, Type.getUnqualifiedType(), ELoc);
18896 VarDecl *DstVD =
18897 buildVarDecl(*this, ERange.getBegin(), Type, ".lastprivate.dst",
18898 D->hasAttrs() ? &D->getAttrs() : nullptr);
18899 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
18900 // For arrays generate assignment operation for single element and replace
18901 // it by the original array element in CodeGen.
18902 ExprResult AssignmentOp = BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
18903 PseudoDstExpr, PseudoSrcExpr);
18904 if (AssignmentOp.isInvalid())
18905 continue;
18906 AssignmentOp =
18907 ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false);
18908 if (AssignmentOp.isInvalid())
18909 continue;
18910
18911 DeclRefExpr *Ref = nullptr;
18912 if (!VD && !CurContext->isDependentContext()) {
18913 if (TopDVar.CKind == OMPC_firstprivate) {
18914 Ref = TopDVar.PrivateCopy;
18915 } else {
18916 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
18917 if (!isOpenMPCapturedDecl(D))
18918 ExprCaptures.push_back(Ref->getDecl());
18919 }
18920 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
18921 (!isOpenMPCapturedDecl(D) &&
18922 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
18923 ExprResult RefRes = DefaultLvalueConversion(Ref);
18924 if (!RefRes.isUsable())
18925 continue;
18926 ExprResult PostUpdateRes =
18927 BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
18928 RefRes.get());
18929 if (!PostUpdateRes.isUsable())
18930 continue;
18931 ExprPostUpdates.push_back(
18932 IgnoredValueConversions(PostUpdateRes.get()).get());
18933 }
18934 }
18935 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
18936 Vars.push_back((VD || CurContext->isDependentContext())
18937 ? RefExpr->IgnoreParens()
18938 : Ref);
18939 SrcExprs.push_back(PseudoSrcExpr);
18940 DstExprs.push_back(PseudoDstExpr);
18941 AssignmentOps.push_back(AssignmentOp.get());
18942 }
18943
18944 if (Vars.empty())
18945 return nullptr;
18946
18947 return OMPLastprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
18948 Vars, SrcExprs, DstExprs, AssignmentOps,
18949 LPKind, LPKindLoc, ColonLoc,
18950 buildPreInits(Context, ExprCaptures),
18951 buildPostUpdate(*this, ExprPostUpdates));
18952}
18953
18955 SourceLocation StartLoc,
18956 SourceLocation LParenLoc,
18957 SourceLocation EndLoc) {
18959 for (Expr *RefExpr : VarList) {
18960 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18961 SourceLocation ELoc;
18962 SourceRange ERange;
18963 Expr *SimpleRefExpr = RefExpr;
18964 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18965 if (Res.second) {
18966 // It will be analyzed later.
18967 Vars.push_back(RefExpr);
18968 }
18969 ValueDecl *D = Res.first;
18970 if (!D)
18971 continue;
18972
18973 auto *VD = dyn_cast<VarDecl>(D);
18974 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18975 // in a Construct]
18976 // Variables with the predetermined data-sharing attributes may not be
18977 // listed in data-sharing attributes clauses, except for the cases
18978 // listed below. For these exceptions only, listing a predetermined
18979 // variable in a data-sharing attribute clause is allowed and overrides
18980 // the variable's predetermined data-sharing attributes.
18981 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18982 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
18983 DVar.RefExpr) {
18984 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
18985 << getOpenMPClauseName(OMPC_shared);
18986 reportOriginalDsa(*this, DSAStack, D, DVar);
18987 continue;
18988 }
18989
18990 DeclRefExpr *Ref = nullptr;
18992 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
18993 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
18994 Vars.push_back((VD || !Ref || CurContext->isDependentContext())
18995 ? RefExpr->IgnoreParens()
18996 : Ref);
18997 }
18998
18999 if (Vars.empty())
19000 return nullptr;
19001
19002 return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
19003}
19004
19005namespace {
19006class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
19007 DSAStackTy *Stack;
19008
19009public:
19010 bool VisitDeclRefExpr(DeclRefExpr *E) {
19011 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
19012 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
19013 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
19014 return false;
19015 if (DVar.CKind != OMPC_unknown)
19016 return true;
19017 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
19018 VD,
19019 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
19020 return isOpenMPPrivate(C) && !AppliedToPointee;
19021 },
19022 [](OpenMPDirectiveKind) { return true; },
19023 /*FromParent=*/true);
19024 return DVarPrivate.CKind != OMPC_unknown;
19025 }
19026 return false;
19027 }
19028 bool VisitStmt(Stmt *S) {
19029 for (Stmt *Child : S->children()) {
19030 if (Child && Visit(Child))
19031 return true;
19032 }
19033 return false;
19034 }
19035 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
19036};
19037} // namespace
19038
19039namespace {
19040// Transform MemberExpression for specified FieldDecl of current class to
19041// DeclRefExpr to specified OMPCapturedExprDecl.
19042class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
19043 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
19044 ValueDecl *Field = nullptr;
19045 DeclRefExpr *CapturedExpr = nullptr;
19046
19047public:
19048 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
19049 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
19050
19051 ExprResult TransformMemberExpr(MemberExpr *E) {
19052 if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
19053 E->getMemberDecl() == Field) {
19054 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
19055 return CapturedExpr;
19056 }
19057 return BaseTransform::TransformMemberExpr(E);
19058 }
19059 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
19060};
19061} // namespace
19062
19063template <typename T, typename U>
19065 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
19066 for (U &Set : Lookups) {
19067 for (auto *D : Set) {
19068 if (T Res = Gen(cast<ValueDecl>(D)))
19069 return Res;
19070 }
19071 }
19072 return T();
19073}
19074
19076 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
19077
19078 for (auto *RD : D->redecls()) {
19079 // Don't bother with extra checks if we already know this one isn't visible.
19080 if (RD == D)
19081 continue;
19082
19083 auto ND = cast<NamedDecl>(RD);
19084 if (LookupResult::isVisible(SemaRef, ND))
19085 return ND;
19086 }
19087
19088 return nullptr;
19089}
19090
19091static void
19093 SourceLocation Loc, QualType Ty,
19095 // Find all of the associated namespaces and classes based on the
19096 // arguments we have.
19097 Sema::AssociatedNamespaceSet AssociatedNamespaces;
19098 Sema::AssociatedClassSet AssociatedClasses;
19099 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
19100 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
19101 AssociatedClasses);
19102
19103 // C++ [basic.lookup.argdep]p3:
19104 // Let X be the lookup set produced by unqualified lookup (3.4.1)
19105 // and let Y be the lookup set produced by argument dependent
19106 // lookup (defined as follows). If X contains [...] then Y is
19107 // empty. Otherwise Y is the set of declarations found in the
19108 // namespaces associated with the argument types as described
19109 // below. The set of declarations found by the lookup of the name
19110 // is the union of X and Y.
19111 //
19112 // Here, we compute Y and add its members to the overloaded
19113 // candidate set.
19114 for (auto *NS : AssociatedNamespaces) {
19115 // When considering an associated namespace, the lookup is the
19116 // same as the lookup performed when the associated namespace is
19117 // used as a qualifier (3.4.3.2) except that:
19118 //
19119 // -- Any using-directives in the associated namespace are
19120 // ignored.
19121 //
19122 // -- Any namespace-scope friend functions declared in
19123 // associated classes are visible within their respective
19124 // namespaces even if they are not visible during an ordinary
19125 // lookup (11.4).
19126 DeclContext::lookup_result R = NS->lookup(Id.getName());
19127 for (auto *D : R) {
19128 auto *Underlying = D;
19129 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19130 Underlying = USD->getTargetDecl();
19131
19132 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
19133 !isa<OMPDeclareMapperDecl>(Underlying))
19134 continue;
19135
19136 if (!SemaRef.isVisible(D)) {
19137 D = findAcceptableDecl(SemaRef, D);
19138 if (!D)
19139 continue;
19140 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19141 Underlying = USD->getTargetDecl();
19142 }
19143 Lookups.emplace_back();
19144 Lookups.back().addDecl(Underlying);
19145 }
19146 }
19147}
19148
19149static ExprResult
19151 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
19152 const DeclarationNameInfo &ReductionId, QualType Ty,
19153 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
19154 if (ReductionIdScopeSpec.isInvalid())
19155 return ExprError();
19156 SmallVector<UnresolvedSet<8>, 4> Lookups;
19157 if (S) {
19158 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19159 Lookup.suppressDiagnostics();
19160 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec)) {
19161 NamedDecl *D = Lookup.getRepresentativeDecl();
19162 do {
19163 S = S->getParent();
19164 } while (S && !S->isDeclScope(D));
19165 if (S)
19166 S = S->getParent();
19167 Lookups.emplace_back();
19168 Lookups.back().append(Lookup.begin(), Lookup.end());
19169 Lookup.clear();
19170 }
19171 } else if (auto *ULE =
19172 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
19173 Lookups.push_back(UnresolvedSet<8>());
19174 Decl *PrevD = nullptr;
19175 for (NamedDecl *D : ULE->decls()) {
19176 if (D == PrevD)
19177 Lookups.push_back(UnresolvedSet<8>());
19178 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
19179 Lookups.back().addDecl(DRD);
19180 PrevD = D;
19181 }
19182 }
19183 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
19186 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
19187 return !D->isInvalidDecl() &&
19188 (D->getType()->isDependentType() ||
19189 D->getType()->isInstantiationDependentType() ||
19190 D->getType()->containsUnexpandedParameterPack());
19191 })) {
19192 UnresolvedSet<8> ResSet;
19193 for (const UnresolvedSet<8> &Set : Lookups) {
19194 if (Set.empty())
19195 continue;
19196 ResSet.append(Set.begin(), Set.end());
19197 // The last item marks the end of all declarations at the specified scope.
19198 ResSet.addDecl(Set[Set.size() - 1]);
19199 }
19201 SemaRef.Context, /*NamingClass=*/nullptr,
19202 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
19203 /*ADL=*/true, /*Overloaded=*/true, ResSet.begin(), ResSet.end());
19204 }
19205 // Lookup inside the classes.
19206 // C++ [over.match.oper]p3:
19207 // For a unary operator @ with an operand of a type whose
19208 // cv-unqualified version is T1, and for a binary operator @ with
19209 // a left operand of a type whose cv-unqualified version is T1 and
19210 // a right operand of a type whose cv-unqualified version is T2,
19211 // three sets of candidate functions, designated member
19212 // candidates, non-member candidates and built-in candidates, are
19213 // constructed as follows:
19214 // -- If T1 is a complete class type or a class currently being
19215 // defined, the set of member candidates is the result of the
19216 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
19217 // the set of member candidates is empty.
19218 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19219 Lookup.suppressDiagnostics();
19220 if (const auto *TyRec = Ty->getAs<RecordType>()) {
19221 // Complete the type if it can be completed.
19222 // If the type is neither complete nor being defined, bail out now.
19223 if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() ||
19224 TyRec->getDecl()->getDefinition()) {
19225 Lookup.clear();
19226 SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
19227 if (Lookup.empty()) {
19228 Lookups.emplace_back();
19229 Lookups.back().append(Lookup.begin(), Lookup.end());
19230 }
19231 }
19232 }
19233 // Perform ADL.
19234 if (SemaRef.getLangOpts().CPlusPlus)
19235 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
19236 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
19237 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
19238 if (!D->isInvalidDecl() &&
19239 SemaRef.Context.hasSameType(D->getType(), Ty))
19240 return D;
19241 return nullptr;
19242 }))
19243 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
19244 VK_LValue, Loc);
19245 if (SemaRef.getLangOpts().CPlusPlus) {
19246 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
19247 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
19248 if (!D->isInvalidDecl() &&
19249 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
19250 !Ty.isMoreQualifiedThan(D->getType()))
19251 return D;
19252 return nullptr;
19253 })) {
19254 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
19255 /*DetectVirtual=*/false);
19256 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
19257 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
19258 VD->getType().getUnqualifiedType()))) {
19259 if (SemaRef.CheckBaseClassAccess(
19260 Loc, VD->getType(), Ty, Paths.front(),
19261 /*DiagID=*/0) != Sema::AR_inaccessible) {
19262 SemaRef.BuildBasePathArray(Paths, BasePath);
19263 return SemaRef.BuildDeclRefExpr(
19264 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc);
19265 }
19266 }
19267 }
19268 }
19269 }
19270 if (ReductionIdScopeSpec.isSet()) {
19271 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
19272 << Ty << Range;
19273 return ExprError();
19274 }
19275 return ExprEmpty();
19276}
19277
19278namespace {
19279/// Data for the reduction-based clauses.
19280struct ReductionData {
19281 /// List of original reduction items.
19283 /// List of private copies of the reduction items.
19284 SmallVector<Expr *, 8> Privates;
19285 /// LHS expressions for the reduction_op expressions.
19287 /// RHS expressions for the reduction_op expressions.
19289 /// Reduction operation expression.
19290 SmallVector<Expr *, 8> ReductionOps;
19291 /// inscan copy operation expressions.
19292 SmallVector<Expr *, 8> InscanCopyOps;
19293 /// inscan copy temp array expressions for prefix sums.
19294 SmallVector<Expr *, 8> InscanCopyArrayTemps;
19295 /// inscan copy temp array element expressions for prefix sums.
19296 SmallVector<Expr *, 8> InscanCopyArrayElems;
19297 /// Taskgroup descriptors for the corresponding reduction items in
19298 /// in_reduction clauses.
19299 SmallVector<Expr *, 8> TaskgroupDescriptors;
19300 /// List of captures for clause.
19301 SmallVector<Decl *, 4> ExprCaptures;
19302 /// List of postupdate expressions.
19303 SmallVector<Expr *, 4> ExprPostUpdates;
19304 /// Reduction modifier.
19305 unsigned RedModifier = 0;
19306 ReductionData() = delete;
19307 /// Reserves required memory for the reduction data.
19308 ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
19309 Vars.reserve(Size);
19310 Privates.reserve(Size);
19311 LHSs.reserve(Size);
19312 RHSs.reserve(Size);
19313 ReductionOps.reserve(Size);
19314 if (RedModifier == OMPC_REDUCTION_inscan) {
19315 InscanCopyOps.reserve(Size);
19316 InscanCopyArrayTemps.reserve(Size);
19317 InscanCopyArrayElems.reserve(Size);
19318 }
19319 TaskgroupDescriptors.reserve(Size);
19320 ExprCaptures.reserve(Size);
19321 ExprPostUpdates.reserve(Size);
19322 }
19323 /// Stores reduction item and reduction operation only (required for dependent
19324 /// reduction item).
19325 void push(Expr *Item, Expr *ReductionOp) {
19326 Vars.emplace_back(Item);
19327 Privates.emplace_back(nullptr);
19328 LHSs.emplace_back(nullptr);
19329 RHSs.emplace_back(nullptr);
19330 ReductionOps.emplace_back(ReductionOp);
19331 TaskgroupDescriptors.emplace_back(nullptr);
19332 if (RedModifier == OMPC_REDUCTION_inscan) {
19333 InscanCopyOps.push_back(nullptr);
19334 InscanCopyArrayTemps.push_back(nullptr);
19335 InscanCopyArrayElems.push_back(nullptr);
19336 }
19337 }
19338 /// Stores reduction data.
19339 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
19340 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
19341 Expr *CopyArrayElem) {
19342 Vars.emplace_back(Item);
19343 Privates.emplace_back(Private);
19344 LHSs.emplace_back(LHS);
19345 RHSs.emplace_back(RHS);
19346 ReductionOps.emplace_back(ReductionOp);
19347 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
19348 if (RedModifier == OMPC_REDUCTION_inscan) {
19349 InscanCopyOps.push_back(CopyOp);
19350 InscanCopyArrayTemps.push_back(CopyArrayTemp);
19351 InscanCopyArrayElems.push_back(CopyArrayElem);
19352 } else {
19353 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
19354 CopyArrayElem == nullptr &&
19355 "Copy operation must be used for inscan reductions only.");
19356 }
19357 }
19358};
19359} // namespace
19360
19362 ASTContext &Context, const OMPArraySectionExpr *OASE, bool &SingleElement,
19363 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
19364 const Expr *Length = OASE->getLength();
19365 if (Length == nullptr) {
19366 // For array sections of the form [1:] or [:], we would need to analyze
19367 // the lower bound...
19368 if (OASE->getColonLocFirst().isValid())
19369 return false;
19370
19371 // This is an array subscript which has implicit length 1!
19372 SingleElement = true;
19373 ArraySizes.push_back(llvm::APSInt::get(1));
19374 } else {
19376 if (!Length->EvaluateAsInt(Result, Context))
19377 return false;
19378
19379 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19380 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
19381 ArraySizes.push_back(ConstantLengthValue);
19382 }
19383
19384 // Get the base of this array section and walk up from there.
19385 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
19386
19387 // We require length = 1 for all array sections except the right-most to
19388 // guarantee that the memory region is contiguous and has no holes in it.
19389 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) {
19390 Length = TempOASE->getLength();
19391 if (Length == nullptr) {
19392 // For array sections of the form [1:] or [:], we would need to analyze
19393 // the lower bound...
19394 if (OASE->getColonLocFirst().isValid())
19395 return false;
19396
19397 // This is an array subscript which has implicit length 1!
19398 ArraySizes.push_back(llvm::APSInt::get(1));
19399 } else {
19401 if (!Length->EvaluateAsInt(Result, Context))
19402 return false;
19403
19404 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19405 if (ConstantLengthValue.getSExtValue() != 1)
19406 return false;
19407
19408 ArraySizes.push_back(ConstantLengthValue);
19409 }
19410 Base = TempOASE->getBase()->IgnoreParenImpCasts();
19411 }
19412
19413 // If we have a single element, we don't need to add the implicit lengths.
19414 if (!SingleElement) {
19415 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
19416 // Has implicit length 1!
19417 ArraySizes.push_back(llvm::APSInt::get(1));
19418 Base = TempASE->getBase()->IgnoreParenImpCasts();
19419 }
19420 }
19421
19422 // This array section can be privatized as a single value or as a constant
19423 // sized array.
19424 return true;
19425}
19426
19427static BinaryOperatorKind
19429 if (BOK == BO_Add)
19430 return BO_AddAssign;
19431 if (BOK == BO_Mul)
19432 return BO_MulAssign;
19433 if (BOK == BO_And)
19434 return BO_AndAssign;
19435 if (BOK == BO_Or)
19436 return BO_OrAssign;
19437 if (BOK == BO_Xor)
19438 return BO_XorAssign;
19439 return BOK;
19440}
19441
19443 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
19444 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19445 SourceLocation ColonLoc, SourceLocation EndLoc,
19446 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19447 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
19448 DeclarationName DN = ReductionId.getName();
19450 BinaryOperatorKind BOK = BO_Comma;
19451
19452 ASTContext &Context = S.Context;
19453 // OpenMP [2.14.3.6, reduction clause]
19454 // C
19455 // reduction-identifier is either an identifier or one of the following
19456 // operators: +, -, *, &, |, ^, && and ||
19457 // C++
19458 // reduction-identifier is either an id-expression or one of the following
19459 // operators: +, -, *, &, |, ^, && and ||
19460 switch (OOK) {
19461 case OO_Plus:
19462 BOK = BO_Add;
19463 break;
19464 case OO_Minus:
19465 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
19466 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
19467 // reduction identifier.
19468 if (S.LangOpts.OpenMP > 52)
19469 BOK = BO_Comma;
19470 else
19471 BOK = BO_Add;
19472 break;
19473 case OO_Star:
19474 BOK = BO_Mul;
19475 break;
19476 case OO_Amp:
19477 BOK = BO_And;
19478 break;
19479 case OO_Pipe:
19480 BOK = BO_Or;
19481 break;
19482 case OO_Caret:
19483 BOK = BO_Xor;
19484 break;
19485 case OO_AmpAmp:
19486 BOK = BO_LAnd;
19487 break;
19488 case OO_PipePipe:
19489 BOK = BO_LOr;
19490 break;
19491 case OO_New:
19492 case OO_Delete:
19493 case OO_Array_New:
19494 case OO_Array_Delete:
19495 case OO_Slash:
19496 case OO_Percent:
19497 case OO_Tilde:
19498 case OO_Exclaim:
19499 case OO_Equal:
19500 case OO_Less:
19501 case OO_Greater:
19502 case OO_LessEqual:
19503 case OO_GreaterEqual:
19504 case OO_PlusEqual:
19505 case OO_MinusEqual:
19506 case OO_StarEqual:
19507 case OO_SlashEqual:
19508 case OO_PercentEqual:
19509 case OO_CaretEqual:
19510 case OO_AmpEqual:
19511 case OO_PipeEqual:
19512 case OO_LessLess:
19513 case OO_GreaterGreater:
19514 case OO_LessLessEqual:
19515 case OO_GreaterGreaterEqual:
19516 case OO_EqualEqual:
19517 case OO_ExclaimEqual:
19518 case OO_Spaceship:
19519 case OO_PlusPlus:
19520 case OO_MinusMinus:
19521 case OO_Comma:
19522 case OO_ArrowStar:
19523 case OO_Arrow:
19524 case OO_Call:
19525 case OO_Subscript:
19526 case OO_Conditional:
19527 case OO_Coawait:
19529 llvm_unreachable("Unexpected reduction identifier");
19530 case OO_None:
19531 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
19532 if (II->isStr("max"))
19533 BOK = BO_GT;
19534 else if (II->isStr("min"))
19535 BOK = BO_LT;
19536 }
19537 break;
19538 }
19539
19540 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
19541 // A reduction clause with the minus (-) operator was deprecated
19542 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
19543 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
19544
19545 SourceRange ReductionIdRange;
19546 if (ReductionIdScopeSpec.isValid())
19547 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
19548 else
19549 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
19550 ReductionIdRange.setEnd(ReductionId.getEndLoc());
19551
19552 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
19553 bool FirstIter = true;
19554 for (Expr *RefExpr : VarList) {
19555 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
19556 // OpenMP [2.1, C/C++]
19557 // A list item is a variable or array section, subject to the restrictions
19558 // specified in Section 2.4 on page 42 and in each of the sections
19559 // describing clauses and directives for which a list appears.
19560 // OpenMP [2.14.3.3, Restrictions, p.1]
19561 // A variable that is part of another variable (as an array or
19562 // structure element) cannot appear in a private clause.
19563 if (!FirstIter && IR != ER)
19564 ++IR;
19565 FirstIter = false;
19566 SourceLocation ELoc;
19567 SourceRange ERange;
19568 Expr *SimpleRefExpr = RefExpr;
19569 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
19570 /*AllowArraySection=*/true);
19571 if (Res.second) {
19572 // Try to find 'declare reduction' corresponding construct before using
19573 // builtin/overloaded operators.
19574 QualType Type = Context.DependentTy;
19575 CXXCastPath BasePath;
19576 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19577 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19578 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19579 Expr *ReductionOp = nullptr;
19580 if (S.CurContext->isDependentContext() &&
19581 (DeclareReductionRef.isUnset() ||
19582 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
19583 ReductionOp = DeclareReductionRef.get();
19584 // It will be analyzed later.
19585 RD.push(RefExpr, ReductionOp);
19586 }
19587 ValueDecl *D = Res.first;
19588 if (!D)
19589 continue;
19590
19591 Expr *TaskgroupDescriptor = nullptr;
19592 QualType Type;
19593 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
19594 auto *OASE = dyn_cast<OMPArraySectionExpr>(RefExpr->IgnoreParens());
19595 if (ASE) {
19596 Type = ASE->getType().getNonReferenceType();
19597 } else if (OASE) {
19598 QualType BaseType =
19600 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
19601 Type = ATy->getElementType();
19602 else
19603 Type = BaseType->getPointeeType();
19604 Type = Type.getNonReferenceType();
19605 } else {
19607 }
19608 auto *VD = dyn_cast<VarDecl>(D);
19609
19610 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19611 // A variable that appears in a private clause must not have an incomplete
19612 // type or a reference type.
19613 if (S.RequireCompleteType(ELoc, D->getType(),
19614 diag::err_omp_reduction_incomplete_type))
19615 continue;
19616 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19617 // A list item that appears in a reduction clause must not be
19618 // const-qualified.
19619 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
19620 /*AcceptIfMutable*/ false, ASE || OASE))
19621 continue;
19622
19623 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
19624 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
19625 // If a list-item is a reference type then it must bind to the same object
19626 // for all threads of the team.
19627 if (!ASE && !OASE) {
19628 if (VD) {
19629 VarDecl *VDDef = VD->getDefinition();
19630 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
19631 DSARefChecker Check(Stack);
19632 if (Check.Visit(VDDef->getInit())) {
19633 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
19634 << getOpenMPClauseName(ClauseKind) << ERange;
19635 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
19636 continue;
19637 }
19638 }
19639 }
19640
19641 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19642 // in a Construct]
19643 // Variables with the predetermined data-sharing attributes may not be
19644 // listed in data-sharing attributes clauses, except for the cases
19645 // listed below. For these exceptions only, listing a predetermined
19646 // variable in a data-sharing attribute clause is allowed and overrides
19647 // the variable's predetermined data-sharing attributes.
19648 // OpenMP [2.14.3.6, Restrictions, p.3]
19649 // Any number of reduction clauses can be specified on the directive,
19650 // but a list item can appear only once in the reduction clauses for that
19651 // directive.
19652 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19653 if (DVar.CKind == OMPC_reduction) {
19654 S.Diag(ELoc, diag::err_omp_once_referenced)
19655 << getOpenMPClauseName(ClauseKind);
19656 if (DVar.RefExpr)
19657 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
19658 continue;
19659 }
19660 if (DVar.CKind != OMPC_unknown) {
19661 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19662 << getOpenMPClauseName(DVar.CKind)
19663 << getOpenMPClauseName(OMPC_reduction);
19664 reportOriginalDsa(S, Stack, D, DVar);
19665 continue;
19666 }
19667
19668 // OpenMP [2.14.3.6, Restrictions, p.1]
19669 // A list item that appears in a reduction clause of a worksharing
19670 // construct must be shared in the parallel regions to which any of the
19671 // worksharing regions arising from the worksharing construct bind.
19672 if (isOpenMPWorksharingDirective(CurrDir) &&
19673 !isOpenMPParallelDirective(CurrDir) &&
19674 !isOpenMPTeamsDirective(CurrDir)) {
19675 DVar = Stack->getImplicitDSA(D, true);
19676 if (DVar.CKind != OMPC_shared) {
19677 S.Diag(ELoc, diag::err_omp_required_access)
19678 << getOpenMPClauseName(OMPC_reduction)
19679 << getOpenMPClauseName(OMPC_shared);
19680 reportOriginalDsa(S, Stack, D, DVar);
19681 continue;
19682 }
19683 }
19684 } else {
19685 // Threadprivates cannot be shared between threads, so dignose if the base
19686 // is a threadprivate variable.
19687 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19688 if (DVar.CKind == OMPC_threadprivate) {
19689 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19690 << getOpenMPClauseName(DVar.CKind)
19691 << getOpenMPClauseName(OMPC_reduction);
19692 reportOriginalDsa(S, Stack, D, DVar);
19693 continue;
19694 }
19695 }
19696
19697 // Try to find 'declare reduction' corresponding construct before using
19698 // builtin/overloaded operators.
19699 CXXCastPath BasePath;
19700 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19701 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19702 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19703 if (DeclareReductionRef.isInvalid())
19704 continue;
19705 if (S.CurContext->isDependentContext() &&
19706 (DeclareReductionRef.isUnset() ||
19707 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
19708 RD.push(RefExpr, DeclareReductionRef.get());
19709 continue;
19710 }
19711 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
19712 // Not allowed reduction identifier is found.
19713 if (S.LangOpts.OpenMP > 52)
19714 S.Diag(ReductionId.getBeginLoc(),
19715 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
19716 << Type << ReductionIdRange;
19717 else
19718 S.Diag(ReductionId.getBeginLoc(),
19719 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
19720 << Type << ReductionIdRange;
19721 continue;
19722 }
19723
19724 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19725 // The type of a list item that appears in a reduction clause must be valid
19726 // for the reduction-identifier. For a max or min reduction in C, the type
19727 // of the list item must be an allowed arithmetic data type: char, int,
19728 // float, double, or _Bool, possibly modified with long, short, signed, or
19729 // unsigned. For a max or min reduction in C++, the type of the list item
19730 // must be an allowed arithmetic data type: char, wchar_t, int, float,
19731 // double, or bool, possibly modified with long, short, signed, or unsigned.
19732 if (DeclareReductionRef.isUnset()) {
19733 if ((BOK == BO_GT || BOK == BO_LT) &&
19734 !(Type->isScalarType() ||
19735 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
19736 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
19737 << getOpenMPClauseName(ClauseKind) << S.getLangOpts().CPlusPlus;
19738 if (!ASE && !OASE) {
19739 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19741 S.Diag(D->getLocation(),
19742 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19743 << D;
19744 }
19745 continue;
19746 }
19747 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
19748 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
19749 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
19750 << getOpenMPClauseName(ClauseKind);
19751 if (!ASE && !OASE) {
19752 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19754 S.Diag(D->getLocation(),
19755 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19756 << D;
19757 }
19758 continue;
19759 }
19760 }
19761
19762 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
19763 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
19764 D->hasAttrs() ? &D->getAttrs() : nullptr);
19765 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
19766 D->hasAttrs() ? &D->getAttrs() : nullptr);
19767 QualType PrivateTy = Type;
19768
19769 // Try if we can determine constant lengths for all array sections and avoid
19770 // the VLA.
19771 bool ConstantLengthOASE = false;
19772 if (OASE) {
19773 bool SingleElement;
19775 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
19776 Context, OASE, SingleElement, ArraySizes);
19777
19778 // If we don't have a single element, we must emit a constant array type.
19779 if (ConstantLengthOASE && !SingleElement) {
19780 for (llvm::APSInt &Size : ArraySizes)
19781 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
19783 /*IndexTypeQuals=*/0);
19784 }
19785 }
19786
19787 if ((OASE && !ConstantLengthOASE) ||
19788 (!OASE && !ASE &&
19790 if (!Context.getTargetInfo().isVLASupported()) {
19791 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
19792 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19793 S.Diag(ELoc, diag::note_vla_unsupported);
19794 continue;
19795 } else {
19796 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19797 S.targetDiag(ELoc, diag::note_vla_unsupported);
19798 }
19799 }
19800 // For arrays/array sections only:
19801 // Create pseudo array type for private copy. The size for this array will
19802 // be generated during codegen.
19803 // For array subscripts or single variables Private Ty is the same as Type
19804 // (type of the variable or single array element).
19805 PrivateTy = Context.getVariableArrayType(
19806 Type,
19807 new (Context)
19808 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
19809 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0, SourceRange());
19810 } else if (!ASE && !OASE &&
19811 Context.getAsArrayType(D->getType().getNonReferenceType())) {
19812 PrivateTy = D->getType().getNonReferenceType();
19813 }
19814 // Private copy.
19815 VarDecl *PrivateVD =
19816 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19817 D->hasAttrs() ? &D->getAttrs() : nullptr,
19818 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19819 // Add initializer for private variable.
19820 Expr *Init = nullptr;
19821 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
19822 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
19823 if (DeclareReductionRef.isUsable()) {
19824 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
19825 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
19826 if (DRD->getInitializer()) {
19827 Init = DRDRef;
19828 RHSVD->setInit(DRDRef);
19830 }
19831 } else {
19832 switch (BOK) {
19833 case BO_Add:
19834 case BO_Xor:
19835 case BO_Or:
19836 case BO_LOr:
19837 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
19839 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
19840 break;
19841 case BO_Mul:
19842 case BO_LAnd:
19843 if (Type->isScalarType() || Type->isAnyComplexType()) {
19844 // '*' and '&&' reduction ops - initializer is '1'.
19845 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
19846 }
19847 break;
19848 case BO_And: {
19849 // '&' reduction op - initializer is '~0'.
19850 QualType OrigType = Type;
19851 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
19852 Type = ComplexTy->getElementType();
19853 if (Type->isRealFloatingType()) {
19854 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
19855 Context.getFloatTypeSemantics(Type));
19856 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19857 Type, ELoc);
19858 } else if (Type->isScalarType()) {
19859 uint64_t Size = Context.getTypeSize(Type);
19860 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
19861 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
19862 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19863 }
19864 if (Init && OrigType->isAnyComplexType()) {
19865 // Init = 0xFFFF + 0xFFFFi;
19866 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
19867 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
19868 }
19869 Type = OrigType;
19870 break;
19871 }
19872 case BO_LT:
19873 case BO_GT: {
19874 // 'min' reduction op - initializer is 'Largest representable number in
19875 // the reduction list item type'.
19876 // 'max' reduction op - initializer is 'Least representable number in
19877 // the reduction list item type'.
19878 if (Type->isIntegerType() || Type->isPointerType()) {
19879 bool IsSigned = Type->hasSignedIntegerRepresentation();
19880 uint64_t Size = Context.getTypeSize(Type);
19881 QualType IntTy =
19882 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
19883 llvm::APInt InitValue =
19884 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
19885 : llvm::APInt::getMinValue(Size)
19886 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
19887 : llvm::APInt::getMaxValue(Size);
19888 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19889 if (Type->isPointerType()) {
19890 // Cast to pointer type.
19892 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
19893 if (CastExpr.isInvalid())
19894 continue;
19895 Init = CastExpr.get();
19896 }
19897 } else if (Type->isRealFloatingType()) {
19898 llvm::APFloat InitValue = llvm::APFloat::getLargest(
19899 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
19900 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19901 Type, ELoc);
19902 }
19903 break;
19904 }
19905 case BO_PtrMemD:
19906 case BO_PtrMemI:
19907 case BO_MulAssign:
19908 case BO_Div:
19909 case BO_Rem:
19910 case BO_Sub:
19911 case BO_Shl:
19912 case BO_Shr:
19913 case BO_LE:
19914 case BO_GE:
19915 case BO_EQ:
19916 case BO_NE:
19917 case BO_Cmp:
19918 case BO_AndAssign:
19919 case BO_XorAssign:
19920 case BO_OrAssign:
19921 case BO_Assign:
19922 case BO_AddAssign:
19923 case BO_SubAssign:
19924 case BO_DivAssign:
19925 case BO_RemAssign:
19926 case BO_ShlAssign:
19927 case BO_ShrAssign:
19928 case BO_Comma:
19929 llvm_unreachable("Unexpected reduction operation");
19930 }
19931 }
19932 if (Init && DeclareReductionRef.isUnset()) {
19933 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
19934 // Store initializer for single element in private copy. Will be used
19935 // during codegen.
19936 PrivateVD->setInit(RHSVD->getInit());
19937 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19938 } else if (!Init) {
19939 S.ActOnUninitializedDecl(RHSVD);
19940 // Store initializer for single element in private copy. Will be used
19941 // during codegen.
19942 PrivateVD->setInit(RHSVD->getInit());
19943 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19944 }
19945 if (RHSVD->isInvalidDecl())
19946 continue;
19947 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
19948 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
19949 << Type << ReductionIdRange;
19950 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19952 S.Diag(D->getLocation(),
19953 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19954 << D;
19955 continue;
19956 }
19957 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
19958 ExprResult ReductionOp;
19959 if (DeclareReductionRef.isUsable()) {
19960 QualType RedTy = DeclareReductionRef.get()->getType();
19961 QualType PtrRedTy = Context.getPointerType(RedTy);
19962 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
19963 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
19964 if (!BasePath.empty()) {
19965 LHS = S.DefaultLvalueConversion(LHS.get());
19966 RHS = S.DefaultLvalueConversion(RHS.get());
19968 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
19969 LHS.get()->getValueKind(), FPOptionsOverride());
19971 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
19972 RHS.get()->getValueKind(), FPOptionsOverride());
19973 }
19975 QualType Params[] = {PtrRedTy, PtrRedTy};
19976 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
19977 auto *OVE = new (Context) OpaqueValueExpr(
19978 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
19979 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
19980 Expr *Args[] = {LHS.get(), RHS.get()};
19981 ReductionOp =
19982 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
19984 } else {
19986 if (Type->isRecordType() && CombBOK != BOK) {
19988 ReductionOp =
19989 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19990 CombBOK, LHSDRE, RHSDRE);
19991 }
19992 if (!ReductionOp.isUsable()) {
19993 ReductionOp =
19994 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
19995 LHSDRE, RHSDRE);
19996 if (ReductionOp.isUsable()) {
19997 if (BOK != BO_LT && BOK != BO_GT) {
19998 ReductionOp =
19999 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20000 BO_Assign, LHSDRE, ReductionOp.get());
20001 } else {
20002 auto *ConditionalOp = new (Context)
20003 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
20004 RHSDRE, Type, VK_LValue, OK_Ordinary);
20005 ReductionOp =
20006 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20007 BO_Assign, LHSDRE, ConditionalOp);
20008 }
20009 }
20010 }
20011 if (ReductionOp.isUsable())
20012 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
20013 /*DiscardedValue*/ false);
20014 if (!ReductionOp.isUsable())
20015 continue;
20016 }
20017
20018 // Add copy operations for inscan reductions.
20019 // LHS = RHS;
20020 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
20021 if (ClauseKind == OMPC_reduction &&
20022 RD.RedModifier == OMPC_REDUCTION_inscan) {
20023 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
20024 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
20025 RHS.get());
20026 if (!CopyOpRes.isUsable())
20027 continue;
20028 CopyOpRes =
20029 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
20030 if (!CopyOpRes.isUsable())
20031 continue;
20032 // For simd directive and simd-based directives in simd mode no need to
20033 // construct temp array, need just a single temp element.
20034 if (Stack->getCurrentDirective() == OMPD_simd ||
20035 (S.getLangOpts().OpenMPSimd &&
20036 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
20037 VarDecl *TempArrayVD =
20038 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
20039 D->hasAttrs() ? &D->getAttrs() : nullptr);
20040 // Add a constructor to the temp decl.
20041 S.ActOnUninitializedDecl(TempArrayVD);
20042 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
20043 } else {
20044 // Build temp array for prefix sum.
20045 auto *Dim = new (S.Context)
20048 PrivateTy, Dim, ArraySizeModifier::Normal,
20049 /*IndexTypeQuals=*/0, {ELoc, ELoc});
20050 VarDecl *TempArrayVD =
20051 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
20052 D->hasAttrs() ? &D->getAttrs() : nullptr);
20053 // Add a constructor to the temp decl.
20054 S.ActOnUninitializedDecl(TempArrayVD);
20055 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
20056 TempArrayElem =
20057 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
20058 auto *Idx = new (S.Context)
20060 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
20061 ELoc, Idx, ELoc);
20062 }
20063 }
20064
20065 // OpenMP [2.15.4.6, Restrictions, p.2]
20066 // A list item that appears in an in_reduction clause of a task construct
20067 // must appear in a task_reduction clause of a construct associated with a
20068 // taskgroup region that includes the participating task in its taskgroup
20069 // set. The construct associated with the innermost region that meets this
20070 // condition must specify the same reduction-identifier as the in_reduction
20071 // clause.
20072 if (ClauseKind == OMPC_in_reduction) {
20073 SourceRange ParentSR;
20074 BinaryOperatorKind ParentBOK;
20075 const Expr *ParentReductionOp = nullptr;
20076 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
20077 DSAStackTy::DSAVarData ParentBOKDSA =
20078 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
20079 ParentBOKTD);
20080 DSAStackTy::DSAVarData ParentReductionOpDSA =
20081 Stack->getTopMostTaskgroupReductionData(
20082 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
20083 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
20084 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
20085 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
20086 (DeclareReductionRef.isUsable() && IsParentBOK) ||
20087 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
20088 bool EmitError = true;
20089 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
20090 llvm::FoldingSetNodeID RedId, ParentRedId;
20091 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
20092 DeclareReductionRef.get()->Profile(RedId, Context,
20093 /*Canonical=*/true);
20094 EmitError = RedId != ParentRedId;
20095 }
20096 if (EmitError) {
20097 S.Diag(ReductionId.getBeginLoc(),
20098 diag::err_omp_reduction_identifier_mismatch)
20099 << ReductionIdRange << RefExpr->getSourceRange();
20100 S.Diag(ParentSR.getBegin(),
20101 diag::note_omp_previous_reduction_identifier)
20102 << ParentSR
20103 << (IsParentBOK ? ParentBOKDSA.RefExpr
20104 : ParentReductionOpDSA.RefExpr)
20105 ->getSourceRange();
20106 continue;
20107 }
20108 }
20109 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
20110 }
20111
20112 DeclRefExpr *Ref = nullptr;
20113 Expr *VarsExpr = RefExpr->IgnoreParens();
20114 if (!VD && !S.CurContext->isDependentContext()) {
20115 if (ASE || OASE) {
20116 TransformExprToCaptures RebuildToCapture(S, D);
20117 VarsExpr =
20118 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
20119 Ref = RebuildToCapture.getCapturedExpr();
20120 } else {
20121 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
20122 }
20123 if (!S.isOpenMPCapturedDecl(D)) {
20124 RD.ExprCaptures.emplace_back(Ref->getDecl());
20125 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20126 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
20127 if (!RefRes.isUsable())
20128 continue;
20129 ExprResult PostUpdateRes =
20130 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
20131 RefRes.get());
20132 if (!PostUpdateRes.isUsable())
20133 continue;
20134 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
20135 Stack->getCurrentDirective() == OMPD_taskgroup) {
20136 S.Diag(RefExpr->getExprLoc(),
20137 diag::err_omp_reduction_non_addressable_expression)
20138 << RefExpr->getSourceRange();
20139 continue;
20140 }
20141 RD.ExprPostUpdates.emplace_back(
20142 S.IgnoredValueConversions(PostUpdateRes.get()).get());
20143 }
20144 }
20145 }
20146 // All reduction items are still marked as reduction (to do not increase
20147 // code base size).
20148 unsigned Modifier = RD.RedModifier;
20149 // Consider task_reductions as reductions with task modifier. Required for
20150 // correct analysis of in_reduction clauses.
20151 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
20152 Modifier = OMPC_REDUCTION_task;
20153 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
20154 ASE || OASE);
20155 if (Modifier == OMPC_REDUCTION_task &&
20156 (CurrDir == OMPD_taskgroup ||
20157 ((isOpenMPParallelDirective(CurrDir) ||
20158 isOpenMPWorksharingDirective(CurrDir)) &&
20159 !isOpenMPSimdDirective(CurrDir)))) {
20160 if (DeclareReductionRef.isUsable())
20161 Stack->addTaskgroupReductionData(D, ReductionIdRange,
20162 DeclareReductionRef.get());
20163 else
20164 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
20165 }
20166 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
20167 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
20168 TempArrayElem.get());
20169 }
20170 return RD.Vars.empty();
20171}
20172
20175 SourceLocation StartLoc, SourceLocation LParenLoc,
20176 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
20177 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20178 ArrayRef<Expr *> UnresolvedReductions) {
20179 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
20180 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
20181 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
20182 /*Last=*/OMPC_REDUCTION_unknown)
20183 << getOpenMPClauseName(OMPC_reduction);
20184 return nullptr;
20185 }
20186 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
20187 // A reduction clause with the inscan reduction-modifier may only appear on a
20188 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
20189 // construct, a parallel worksharing-loop construct or a parallel
20190 // worksharing-loop SIMD construct.
20191 if (Modifier == OMPC_REDUCTION_inscan &&
20192 (DSAStack->getCurrentDirective() != OMPD_for &&
20193 DSAStack->getCurrentDirective() != OMPD_for_simd &&
20194 DSAStack->getCurrentDirective() != OMPD_simd &&
20195 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
20196 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
20197 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
20198 return nullptr;
20199 }
20200
20201 ReductionData RD(VarList.size(), Modifier);
20202 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_reduction, VarList,
20203 StartLoc, LParenLoc, ColonLoc, EndLoc,
20204 ReductionIdScopeSpec, ReductionId,
20205 UnresolvedReductions, RD))
20206 return nullptr;
20207
20209 Context, StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc, Modifier,
20210 RD.Vars, ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
20211 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
20212 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
20213 buildPreInits(Context, RD.ExprCaptures),
20214 buildPostUpdate(*this, RD.ExprPostUpdates));
20215}
20216
20218 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20219 SourceLocation ColonLoc, SourceLocation EndLoc,
20220 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20221 ArrayRef<Expr *> UnresolvedReductions) {
20222 ReductionData RD(VarList.size());
20223 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_task_reduction, VarList,
20224 StartLoc, LParenLoc, ColonLoc, EndLoc,
20225 ReductionIdScopeSpec, ReductionId,
20226 UnresolvedReductions, RD))
20227 return nullptr;
20228
20230 Context, StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20231 ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
20232 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
20233 buildPreInits(Context, RD.ExprCaptures),
20234 buildPostUpdate(*this, RD.ExprPostUpdates));
20235}
20236
20238 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20239 SourceLocation ColonLoc, SourceLocation EndLoc,
20240 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20241 ArrayRef<Expr *> UnresolvedReductions) {
20242 ReductionData RD(VarList.size());
20243 if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_in_reduction, VarList,
20244 StartLoc, LParenLoc, ColonLoc, EndLoc,
20245 ReductionIdScopeSpec, ReductionId,
20246 UnresolvedReductions, RD))
20247 return nullptr;
20248
20250 Context, StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20251 ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
20252 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
20253 buildPreInits(Context, RD.ExprCaptures),
20254 buildPostUpdate(*this, RD.ExprPostUpdates));
20255}
20256
20258 SourceLocation LinLoc) {
20259 if ((!LangOpts.CPlusPlus && LinKind != OMPC_LINEAR_val) ||
20260 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
20261 Diag(LinLoc, diag::err_omp_wrong_linear_modifier) << LangOpts.CPlusPlus;
20262 return true;
20263 }
20264 return false;
20265}
20266
20269 bool IsDeclareSimd) {
20270 const auto *VD = dyn_cast_or_null<VarDecl>(D);
20271 // A variable must not have an incomplete type or a reference type.
20272 if (RequireCompleteType(ELoc, Type, diag::err_omp_linear_incomplete_type))
20273 return true;
20274 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
20275 !Type->isReferenceType()) {
20276 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
20277 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
20278 return true;
20279 }
20280 Type = Type.getNonReferenceType();
20281
20282 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
20283 // A variable that is privatized must not have a const-qualified type
20284 // unless it is of class type with a mutable member. This restriction does
20285 // not apply to the firstprivate clause, nor to the linear clause on
20286 // declarative directives (like declare simd).
20287 if (!IsDeclareSimd &&
20288 rejectConstNotMutableType(*this, D, Type, OMPC_linear, ELoc))
20289 return true;
20290
20291 // A list item must be of integral or pointer type.
20292 Type = Type.getUnqualifiedType().getCanonicalType();
20293 const auto *Ty = Type.getTypePtrOrNull();
20294 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
20295 !Ty->isIntegralType(Context) && !Ty->isPointerType())) {
20296 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
20297 if (D) {
20298 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20300 Diag(D->getLocation(),
20301 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20302 << D;
20303 }
20304 return true;
20305 }
20306 return false;
20307}
20308
20310 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
20311 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
20312 SourceLocation LinLoc, SourceLocation ColonLoc,
20313 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
20315 SmallVector<Expr *, 8> Privates;
20317 SmallVector<Decl *, 4> ExprCaptures;
20318 SmallVector<Expr *, 4> ExprPostUpdates;
20319 // OpenMP 5.2 [Section 5.4.6, linear clause]
20320 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
20321 // 'ref'
20322 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
20323 getLangOpts().OpenMP >= 52)
20324 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
20325 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
20326 LinKind = OMPC_LINEAR_val;
20327 for (Expr *RefExpr : VarList) {
20328 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20329 SourceLocation ELoc;
20330 SourceRange ERange;
20331 Expr *SimpleRefExpr = RefExpr;
20332 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
20333 if (Res.second) {
20334 // It will be analyzed later.
20335 Vars.push_back(RefExpr);
20336 Privates.push_back(nullptr);
20337 Inits.push_back(nullptr);
20338 }
20339 ValueDecl *D = Res.first;
20340 if (!D)
20341 continue;
20342
20343 QualType Type = D->getType();
20344 auto *VD = dyn_cast<VarDecl>(D);
20345
20346 // OpenMP [2.14.3.7, linear clause]
20347 // A list-item cannot appear in more than one linear clause.
20348 // A list-item that appears in a linear clause cannot appear in any
20349 // other data-sharing attribute clause.
20350 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
20351 if (DVar.RefExpr) {
20352 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
20353 << getOpenMPClauseName(OMPC_linear);
20354 reportOriginalDsa(*this, DSAStack, D, DVar);
20355 continue;
20356 }
20357
20358 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
20359 continue;
20360 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20361
20362 // Build private copy of original var.
20363 VarDecl *Private =
20364 buildVarDecl(*this, ELoc, Type, D->getName(),
20365 D->hasAttrs() ? &D->getAttrs() : nullptr,
20366 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
20367 DeclRefExpr *PrivateRef = buildDeclRefExpr(*this, Private, Type, ELoc);
20368 // Build var to save initial value.
20369 VarDecl *Init = buildVarDecl(*this, ELoc, Type, ".linear.start");
20370 Expr *InitExpr;
20371 DeclRefExpr *Ref = nullptr;
20372 if (!VD && !CurContext->isDependentContext()) {
20373 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
20374 if (!isOpenMPCapturedDecl(D)) {
20375 ExprCaptures.push_back(Ref->getDecl());
20376 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20377 ExprResult RefRes = DefaultLvalueConversion(Ref);
20378 if (!RefRes.isUsable())
20379 continue;
20380 ExprResult PostUpdateRes =
20381 BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
20382 SimpleRefExpr, RefRes.get());
20383 if (!PostUpdateRes.isUsable())
20384 continue;
20385 ExprPostUpdates.push_back(
20386 IgnoredValueConversions(PostUpdateRes.get()).get());
20387 }
20388 }
20389 }
20390 if (LinKind == OMPC_LINEAR_uval)
20391 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
20392 else
20393 InitExpr = VD ? SimpleRefExpr : Ref;
20395 /*DirectInit=*/false);
20396 DeclRefExpr *InitRef = buildDeclRefExpr(*this, Init, Type, ELoc);
20397
20398 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
20399 Vars.push_back((VD || CurContext->isDependentContext())
20400 ? RefExpr->IgnoreParens()
20401 : Ref);
20402 Privates.push_back(PrivateRef);
20403 Inits.push_back(InitRef);
20404 }
20405
20406 if (Vars.empty())
20407 return nullptr;
20408
20409 Expr *StepExpr = Step;
20410 Expr *CalcStepExpr = nullptr;
20411 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
20412 !Step->isInstantiationDependent() &&
20414 SourceLocation StepLoc = Step->getBeginLoc();
20416 if (Val.isInvalid())
20417 return nullptr;
20418 StepExpr = Val.get();
20419
20420 // Build var to save the step value.
20421 VarDecl *SaveVar =
20422 buildVarDecl(*this, StepLoc, StepExpr->getType(), ".linear.step");
20423 ExprResult SaveRef =
20424 buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc);
20425 ExprResult CalcStep =
20426 BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr);
20427 CalcStep = ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false);
20428
20429 // Warn about zero linear step (it would be probably better specified as
20430 // making corresponding variables 'const').
20431 if (std::optional<llvm::APSInt> Result =
20432 StepExpr->getIntegerConstantExpr(Context)) {
20433 if (!Result->isNegative() && !Result->isStrictlyPositive())
20434 Diag(StepLoc, diag::warn_omp_linear_step_zero)
20435 << Vars[0] << (Vars.size() > 1);
20436 } else if (CalcStep.isUsable()) {
20437 // Calculate the step beforehand instead of doing this on each iteration.
20438 // (This is not used if the number of iterations may be kfold-ed).
20439 CalcStepExpr = CalcStep.get();
20440 }
20441 }
20442
20443 return OMPLinearClause::Create(Context, StartLoc, LParenLoc, LinKind, LinLoc,
20444 ColonLoc, StepModifierLoc, EndLoc, Vars,
20445 Privates, Inits, StepExpr, CalcStepExpr,
20446 buildPreInits(Context, ExprCaptures),
20447 buildPostUpdate(*this, ExprPostUpdates));
20448}
20449
20451 Expr *NumIterations, Sema &SemaRef,
20452 Scope *S, DSAStackTy *Stack) {
20453 // Walk the vars and build update/final expressions for the CodeGen.
20454 SmallVector<Expr *, 8> Updates;
20456 SmallVector<Expr *, 8> UsedExprs;
20457 Expr *Step = Clause.getStep();
20458 Expr *CalcStep = Clause.getCalcStep();
20459 // OpenMP [2.14.3.7, linear clause]
20460 // If linear-step is not specified it is assumed to be 1.
20461 if (!Step)
20462 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
20463 else if (CalcStep)
20464 Step = cast<BinaryOperator>(CalcStep)->getLHS();
20465 bool HasErrors = false;
20466 auto CurInit = Clause.inits().begin();
20467 auto CurPrivate = Clause.privates().begin();
20468 OpenMPLinearClauseKind LinKind = Clause.getModifier();
20469 for (Expr *RefExpr : Clause.varlists()) {
20470 SourceLocation ELoc;
20471 SourceRange ERange;
20472 Expr *SimpleRefExpr = RefExpr;
20473 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20474 ValueDecl *D = Res.first;
20475 if (Res.second || !D) {
20476 Updates.push_back(nullptr);
20477 Finals.push_back(nullptr);
20478 HasErrors = true;
20479 continue;
20480 }
20481 auto &&Info = Stack->isLoopControlVariable(D);
20482 // OpenMP [2.15.11, distribute simd Construct]
20483 // A list item may not appear in a linear clause, unless it is the loop
20484 // iteration variable.
20485 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
20486 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
20487 SemaRef.Diag(ELoc,
20488 diag::err_omp_linear_distribute_var_non_loop_iteration);
20489 Updates.push_back(nullptr);
20490 Finals.push_back(nullptr);
20491 HasErrors = true;
20492 continue;
20493 }
20494 Expr *InitExpr = *CurInit;
20495
20496 // Build privatized reference to the current linear var.
20497 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
20498 Expr *CapturedRef;
20499 if (LinKind == OMPC_LINEAR_uval)
20500 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
20501 else
20502 CapturedRef =
20503 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
20504 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
20505 /*RefersToCapture=*/true);
20506
20507 // Build update: Var = InitExpr + IV * Step
20509 if (!Info.first)
20511 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
20512 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
20513 else
20514 Update = *CurPrivate;
20515 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
20516 /*DiscardedValue*/ false);
20517
20518 // Build final: Var = PrivCopy;
20519 ExprResult Final;
20520 if (!Info.first)
20521 Final = SemaRef.BuildBinOp(
20522 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
20523 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
20524 else
20525 Final = *CurPrivate;
20526 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
20527 /*DiscardedValue*/ false);
20528
20529 if (!Update.isUsable() || !Final.isUsable()) {
20530 Updates.push_back(nullptr);
20531 Finals.push_back(nullptr);
20532 UsedExprs.push_back(nullptr);
20533 HasErrors = true;
20534 } else {
20535 Updates.push_back(Update.get());
20536 Finals.push_back(Final.get());
20537 if (!Info.first)
20538 UsedExprs.push_back(SimpleRefExpr);
20539 }
20540 ++CurInit;
20541 ++CurPrivate;
20542 }
20543 if (Expr *S = Clause.getStep())
20544 UsedExprs.push_back(S);
20545 // Fill the remaining part with the nullptr.
20546 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
20547 Clause.setUpdates(Updates);
20548 Clause.setFinals(Finals);
20549 Clause.setUsedExprs(UsedExprs);
20550 return HasErrors;
20551}
20552
20554 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
20555 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
20557 for (Expr *RefExpr : VarList) {
20558 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20559 SourceLocation ELoc;
20560 SourceRange ERange;
20561 Expr *SimpleRefExpr = RefExpr;
20562 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
20563 if (Res.second) {
20564 // It will be analyzed later.
20565 Vars.push_back(RefExpr);
20566 }
20567 ValueDecl *D = Res.first;
20568 if (!D)
20569 continue;
20570
20571 QualType QType = D->getType();
20572 auto *VD = dyn_cast<VarDecl>(D);
20573
20574 // OpenMP [2.8.1, simd construct, Restrictions]
20575 // The type of list items appearing in the aligned clause must be
20576 // array, pointer, reference to array, or reference to pointer.
20578 const Type *Ty = QType.getTypePtrOrNull();
20579 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
20580 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
20581 << QType << getLangOpts().CPlusPlus << ERange;
20582 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20584 Diag(D->getLocation(),
20585 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20586 << D;
20587 continue;
20588 }
20589
20590 // OpenMP [2.8.1, simd construct, Restrictions]
20591 // A list-item cannot appear in more than one aligned clause.
20592 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
20593 Diag(ELoc, diag::err_omp_used_in_clause_twice)
20594 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
20595 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
20596 << getOpenMPClauseName(OMPC_aligned);
20597 continue;
20598 }
20599
20600 DeclRefExpr *Ref = nullptr;
20601 if (!VD && isOpenMPCapturedDecl(D))
20602 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
20603 Vars.push_back(DefaultFunctionArrayConversion(
20604 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
20605 .get());
20606 }
20607
20608 // OpenMP [2.8.1, simd construct, Description]
20609 // The parameter of the aligned clause, alignment, must be a constant
20610 // positive integer expression.
20611 // If no optional parameter is specified, implementation-defined default
20612 // alignments for SIMD instructions on the target platforms are assumed.
20613 if (Alignment != nullptr) {
20614 ExprResult AlignResult =
20615 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
20616 if (AlignResult.isInvalid())
20617 return nullptr;
20618 Alignment = AlignResult.get();
20619 }
20620 if (Vars.empty())
20621 return nullptr;
20622
20623 return OMPAlignedClause::Create(Context, StartLoc, LParenLoc, ColonLoc,
20624 EndLoc, Vars, Alignment);
20625}
20626
20628 SourceLocation StartLoc,
20629 SourceLocation LParenLoc,
20630 SourceLocation EndLoc) {
20632 SmallVector<Expr *, 8> SrcExprs;
20633 SmallVector<Expr *, 8> DstExprs;
20634 SmallVector<Expr *, 8> AssignmentOps;
20635 for (Expr *RefExpr : VarList) {
20636 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
20637 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20638 // It will be analyzed later.
20639 Vars.push_back(RefExpr);
20640 SrcExprs.push_back(nullptr);
20641 DstExprs.push_back(nullptr);
20642 AssignmentOps.push_back(nullptr);
20643 continue;
20644 }
20645
20646 SourceLocation ELoc = RefExpr->getExprLoc();
20647 // OpenMP [2.1, C/C++]
20648 // A list item is a variable name.
20649 // OpenMP [2.14.4.1, Restrictions, p.1]
20650 // A list item that appears in a copyin clause must be threadprivate.
20651 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
20652 if (!DE || !isa<VarDecl>(DE->getDecl())) {
20653 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
20654 << 0 << RefExpr->getSourceRange();
20655 continue;
20656 }
20657
20658 Decl *D = DE->getDecl();
20659 auto *VD = cast<VarDecl>(D);
20660
20661 QualType Type = VD->getType();
20663 // It will be analyzed later.
20664 Vars.push_back(DE);
20665 SrcExprs.push_back(nullptr);
20666 DstExprs.push_back(nullptr);
20667 AssignmentOps.push_back(nullptr);
20668 continue;
20669 }
20670
20671 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
20672 // A list item that appears in a copyin clause must be threadprivate.
20673 if (!DSAStack->isThreadPrivate(VD)) {
20674 Diag(ELoc, diag::err_omp_required_access)
20675 << getOpenMPClauseName(OMPC_copyin)
20676 << getOpenMPDirectiveName(OMPD_threadprivate);
20677 continue;
20678 }
20679
20680 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20681 // A variable of class type (or array thereof) that appears in a
20682 // copyin clause requires an accessible, unambiguous copy assignment
20683 // operator for the class type.
20685 VarDecl *SrcVD =
20686 buildVarDecl(*this, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
20687 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20688 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
20689 *this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
20690 VarDecl *DstVD =
20691 buildVarDecl(*this, DE->getBeginLoc(), ElemType, ".copyin.dst",
20692 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20693 DeclRefExpr *PseudoDstExpr =
20694 buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc());
20695 // For arrays generate assignment operation for single element and replace
20696 // it by the original array element in CodeGen.
20697 ExprResult AssignmentOp =
20698 BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, PseudoDstExpr,
20699 PseudoSrcExpr);
20700 if (AssignmentOp.isInvalid())
20701 continue;
20702 AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
20703 /*DiscardedValue*/ false);
20704 if (AssignmentOp.isInvalid())
20705 continue;
20706
20707 DSAStack->addDSA(VD, DE, OMPC_copyin);
20708 Vars.push_back(DE);
20709 SrcExprs.push_back(PseudoSrcExpr);
20710 DstExprs.push_back(PseudoDstExpr);
20711 AssignmentOps.push_back(AssignmentOp.get());
20712 }
20713
20714 if (Vars.empty())
20715 return nullptr;
20716
20717 return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars,
20718 SrcExprs, DstExprs, AssignmentOps);
20719}
20720
20722 SourceLocation StartLoc,
20723 SourceLocation LParenLoc,
20724 SourceLocation EndLoc) {
20726 SmallVector<Expr *, 8> SrcExprs;
20727 SmallVector<Expr *, 8> DstExprs;
20728 SmallVector<Expr *, 8> AssignmentOps;
20729 for (Expr *RefExpr : VarList) {
20730 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20731 SourceLocation ELoc;
20732 SourceRange ERange;
20733 Expr *SimpleRefExpr = RefExpr;
20734 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
20735 if (Res.second) {
20736 // It will be analyzed later.
20737 Vars.push_back(RefExpr);
20738 SrcExprs.push_back(nullptr);
20739 DstExprs.push_back(nullptr);
20740 AssignmentOps.push_back(nullptr);
20741 }
20742 ValueDecl *D = Res.first;
20743 if (!D)
20744 continue;
20745
20746 QualType Type = D->getType();
20747 auto *VD = dyn_cast<VarDecl>(D);
20748
20749 // OpenMP [2.14.4.2, Restrictions, p.2]
20750 // A list item that appears in a copyprivate clause may not appear in a
20751 // private or firstprivate clause on the single construct.
20752 if (!VD || !DSAStack->isThreadPrivate(VD)) {
20753 DSAStackTy::DSAVarData DVar =
20754 DSAStack->getTopDSA(D, /*FromParent=*/false);
20755 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
20756 DVar.RefExpr) {
20757 Diag(ELoc, diag::err_omp_wrong_dsa)
20758 << getOpenMPClauseName(DVar.CKind)
20759 << getOpenMPClauseName(OMPC_copyprivate);
20760 reportOriginalDsa(*this, DSAStack, D, DVar);
20761 continue;
20762 }
20763
20764 // OpenMP [2.11.4.2, Restrictions, p.1]
20765 // All list items that appear in a copyprivate clause must be either
20766 // threadprivate or private in the enclosing context.
20767 if (DVar.CKind == OMPC_unknown) {
20768 DVar = DSAStack->getImplicitDSA(D, false);
20769 if (DVar.CKind == OMPC_shared) {
20770 Diag(ELoc, diag::err_omp_required_access)
20771 << getOpenMPClauseName(OMPC_copyprivate)
20772 << "threadprivate or private in the enclosing context";
20773 reportOriginalDsa(*this, DSAStack, D, DVar);
20774 continue;
20775 }
20776 }
20777 }
20778
20779 // Variably modified types are not supported.
20781 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
20782 << getOpenMPClauseName(OMPC_copyprivate) << Type
20783 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
20784 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20786 Diag(D->getLocation(),
20787 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20788 << D;
20789 continue;
20790 }
20791
20792 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20793 // A variable of class type (or array thereof) that appears in a
20794 // copyin clause requires an accessible, unambiguous copy assignment
20795 // operator for the class type.
20796 Type = Context.getBaseElementType(Type.getNonReferenceType())
20798 VarDecl *SrcVD =
20799 buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
20800 D->hasAttrs() ? &D->getAttrs() : nullptr);
20801 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(*this, SrcVD, Type, ELoc);
20802 VarDecl *DstVD =
20803 buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
20804 D->hasAttrs() ? &D->getAttrs() : nullptr);
20805 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
20806 ExprResult AssignmentOp = BuildBinOp(
20807 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
20808 if (AssignmentOp.isInvalid())
20809 continue;
20810 AssignmentOp =
20811 ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false);
20812 if (AssignmentOp.isInvalid())
20813 continue;
20814
20815 // No need to mark vars as copyprivate, they are already threadprivate or
20816 // implicitly private.
20817 assert(VD || isOpenMPCapturedDecl(D));
20818 Vars.push_back(
20819 VD ? RefExpr->IgnoreParens()
20820 : buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false));
20821 SrcExprs.push_back(PseudoSrcExpr);
20822 DstExprs.push_back(PseudoDstExpr);
20823 AssignmentOps.push_back(AssignmentOp.get());
20824 }
20825
20826 if (Vars.empty())
20827 return nullptr;
20828
20829 return OMPCopyprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
20830 Vars, SrcExprs, DstExprs, AssignmentOps);
20831}
20832
20834 SourceLocation StartLoc,
20835 SourceLocation LParenLoc,
20836 SourceLocation EndLoc) {
20837 if (VarList.empty())
20838 return nullptr;
20839
20840 return OMPFlushClause::Create(Context, StartLoc, LParenLoc, EndLoc, VarList);
20841}
20842
20843/// Tries to find omp_depend_t. type.
20844static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
20845 bool Diagnose = true) {
20846 QualType OMPDependT = Stack->getOMPDependT();
20847 if (!OMPDependT.isNull())
20848 return true;
20849 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
20850 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
20851 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
20852 if (Diagnose)
20853 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
20854 return false;
20855 }
20856 Stack->setOMPDependT(PT.get());
20857 return true;
20858}
20859
20861 SourceLocation LParenLoc,
20862 SourceLocation EndLoc) {
20863 if (!Depobj)
20864 return nullptr;
20865
20866 bool OMPDependTFound = findOMPDependT(*this, StartLoc, DSAStack);
20867
20868 // OpenMP 5.0, 2.17.10.1 depobj Construct
20869 // depobj is an lvalue expression of type omp_depend_t.
20870 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
20871 !Depobj->isInstantiationDependent() &&
20873 (OMPDependTFound &&
20874 !Context.typesAreCompatible(DSAStack->getOMPDependT(), Depobj->getType(),
20875 /*CompareUnqualified=*/true))) {
20876 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20877 << 0 << Depobj->getType() << Depobj->getSourceRange();
20878 }
20879
20880 if (!Depobj->isLValue()) {
20881 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20882 << 1 << Depobj->getSourceRange();
20883 }
20884
20885 return OMPDepobjClause::Create(Context, StartLoc, LParenLoc, EndLoc, Depobj);
20886}
20887
20888namespace {
20889// Utility struct that gathers the related info for doacross clause.
20890struct DoacrossDataInfoTy {
20891 // The list of expressions.
20893 // The OperatorOffset for doacross loop.
20895 // The depended loop count.
20896 llvm::APSInt TotalDepCount;
20897};
20898} // namespace
20899static DoacrossDataInfoTy
20901 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
20902 SourceLocation EndLoc) {
20903
20906 llvm::APSInt DepCounter(/*BitWidth=*/32);
20907 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20908
20909 if (const Expr *OrderedCountExpr =
20910 Stack->getParentOrderedRegionParam().first) {
20911 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
20912 TotalDepCount.setIsUnsigned(/*Val=*/true);
20913 }
20914
20915 for (Expr *RefExpr : VarList) {
20916 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
20917 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20918 // It will be analyzed later.
20919 Vars.push_back(RefExpr);
20920 continue;
20921 }
20922
20923 SourceLocation ELoc = RefExpr->getExprLoc();
20924 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20925 if (!IsSource) {
20926 if (Stack->getParentOrderedRegionParam().first &&
20927 DepCounter >= TotalDepCount) {
20928 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
20929 continue;
20930 }
20931 ++DepCounter;
20932 // OpenMP [2.13.9, Summary]
20933 // depend(dependence-type : vec), where dependence-type is:
20934 // 'sink' and where vec is the iteration vector, which has the form:
20935 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
20936 // where n is the value specified by the ordered clause in the loop
20937 // directive, xi denotes the loop iteration variable of the i-th nested
20938 // loop associated with the loop directive, and di is a constant
20939 // non-negative integer.
20940 if (SemaRef.CurContext->isDependentContext()) {
20941 // It will be analyzed later.
20942 Vars.push_back(RefExpr);
20943 continue;
20944 }
20945 SimpleExpr = SimpleExpr->IgnoreImplicit();
20947 SourceLocation OOLoc;
20948 Expr *LHS = SimpleExpr;
20949 Expr *RHS = nullptr;
20950 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
20951 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
20952 OOLoc = BO->getOperatorLoc();
20953 LHS = BO->getLHS()->IgnoreParenImpCasts();
20954 RHS = BO->getRHS()->IgnoreParenImpCasts();
20955 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
20956 OOK = OCE->getOperator();
20957 OOLoc = OCE->getOperatorLoc();
20958 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20959 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
20960 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
20961 OOK = MCE->getMethodDecl()
20962 ->getNameInfo()
20963 .getName()
20964 .getCXXOverloadedOperator();
20965 OOLoc = MCE->getCallee()->getExprLoc();
20966 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
20967 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20968 }
20969 SourceLocation ELoc;
20970 SourceRange ERange;
20971 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
20972 if (Res.second) {
20973 // It will be analyzed later.
20974 Vars.push_back(RefExpr);
20975 }
20976 ValueDecl *D = Res.first;
20977 if (!D)
20978 continue;
20979
20980 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
20981 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
20982 continue;
20983 }
20984 if (RHS) {
20986 RHS, OMPC_depend, /*StrictlyPositive=*/false);
20987 if (RHSRes.isInvalid())
20988 continue;
20989 }
20990 if (!SemaRef.CurContext->isDependentContext() &&
20991 Stack->getParentOrderedRegionParam().first &&
20992 DepCounter != Stack->isParentLoopControlVariable(D).first) {
20993 const ValueDecl *VD =
20994 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
20995 if (VD)
20996 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20997 << 1 << VD;
20998 else
20999 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21000 << 0;
21001 continue;
21002 }
21003 OpsOffs.emplace_back(RHS, OOK);
21004 }
21005 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21006 }
21007 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
21008 TotalDepCount > VarList.size() &&
21009 Stack->getParentOrderedRegionParam().first &&
21010 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
21011 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
21012 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
21013 }
21014 return {Vars, OpsOffs, TotalDepCount};
21015}
21016
21017OMPClause *
21019 Expr *DepModifier, ArrayRef<Expr *> VarList,
21020 SourceLocation StartLoc, SourceLocation LParenLoc,
21021 SourceLocation EndLoc) {
21022 OpenMPDependClauseKind DepKind = Data.DepKind;
21023 SourceLocation DepLoc = Data.DepLoc;
21024 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
21025 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
21026 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21027 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
21028 return nullptr;
21029 }
21030 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
21031 DepKind == OMPC_DEPEND_mutexinoutset) {
21032 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
21033 return nullptr;
21034 }
21035 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
21036 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21037 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
21038 DepKind == OMPC_DEPEND_sink ||
21039 ((LangOpts.OpenMP < 50 ||
21040 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21041 DepKind == OMPC_DEPEND_depobj))) {
21042 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
21043 OMPC_DEPEND_outallmemory,
21044 OMPC_DEPEND_inoutallmemory};
21045 if (LangOpts.OpenMP < 50 || DSAStack->getCurrentDirective() == OMPD_depobj)
21046 Except.push_back(OMPC_DEPEND_depobj);
21047 if (LangOpts.OpenMP < 51)
21048 Except.push_back(OMPC_DEPEND_inoutset);
21049 std::string Expected = (LangOpts.OpenMP >= 50 && !DepModifier)
21050 ? "depend modifier(iterator) or "
21051 : "";
21052 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21053 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
21054 /*Last=*/OMPC_DEPEND_unknown,
21055 Except)
21056 << getOpenMPClauseName(OMPC_depend);
21057 return nullptr;
21058 }
21059 if (DepModifier &&
21060 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
21061 Diag(DepModifier->getExprLoc(),
21062 diag::err_omp_depend_sink_source_with_modifier);
21063 return nullptr;
21064 }
21065 if (DepModifier &&
21066 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
21067 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
21068
21071 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
21072
21073 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
21074 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
21075 *this, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
21076 Vars = VarOffset.Vars;
21077 OpsOffs = VarOffset.OpsOffs;
21078 TotalDepCount = VarOffset.TotalDepCount;
21079 } else {
21080 for (Expr *RefExpr : VarList) {
21081 assert(RefExpr && "NULL expr in OpenMP shared clause.");
21082 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21083 // It will be analyzed later.
21084 Vars.push_back(RefExpr);
21085 continue;
21086 }
21087
21088 SourceLocation ELoc = RefExpr->getExprLoc();
21089 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
21090 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
21091 bool OMPDependTFound = LangOpts.OpenMP >= 50;
21092 if (OMPDependTFound)
21093 OMPDependTFound = findOMPDependT(*this, StartLoc, DSAStack,
21094 DepKind == OMPC_DEPEND_depobj);
21095 if (DepKind == OMPC_DEPEND_depobj) {
21096 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21097 // List items used in depend clauses with the depobj dependence type
21098 // must be expressions of the omp_depend_t type.
21099 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21100 !RefExpr->isInstantiationDependent() &&
21101 !RefExpr->containsUnexpandedParameterPack() &&
21102 (OMPDependTFound &&
21103 !Context.hasSameUnqualifiedType(DSAStack->getOMPDependT(),
21104 RefExpr->getType()))) {
21105 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21106 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
21107 continue;
21108 }
21109 if (!RefExpr->isLValue()) {
21110 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21111 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
21112 continue;
21113 }
21114 } else {
21115 // OpenMP 5.0 [2.17.11, Restrictions]
21116 // List items used in depend clauses cannot be zero-length array
21117 // sections.
21118 QualType ExprTy = RefExpr->getType().getNonReferenceType();
21119 const auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr);
21120 if (OASE) {
21121 QualType BaseType =
21123 if (BaseType.isNull())
21124 return nullptr;
21125 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21126 ExprTy = ATy->getElementType();
21127 else
21128 ExprTy = BaseType->getPointeeType();
21129 if (BaseType.isNull() || ExprTy.isNull())
21130 return nullptr;
21131 ExprTy = ExprTy.getNonReferenceType();
21132 const Expr *Length = OASE->getLength();
21134 if (Length && !Length->isValueDependent() &&
21135 Length->EvaluateAsInt(Result, Context) &&
21136 Result.Val.getInt().isZero()) {
21137 Diag(ELoc,
21138 diag::err_omp_depend_zero_length_array_section_not_allowed)
21139 << SimpleExpr->getSourceRange();
21140 continue;
21141 }
21142 }
21143
21144 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21145 // List items used in depend clauses with the in, out, inout,
21146 // inoutset, or mutexinoutset dependence types cannot be
21147 // expressions of the omp_depend_t type.
21148 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21149 !RefExpr->isInstantiationDependent() &&
21150 !RefExpr->containsUnexpandedParameterPack() &&
21151 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
21152 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
21153 ExprTy.getTypePtr()))) {
21154 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21155 << (LangOpts.OpenMP >= 50 ? 1 : 0)
21156 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
21157 continue;
21158 }
21159
21160 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
21161 if (ASE && !ASE->getBase()->isTypeDependent() &&
21162 !ASE->getBase()
21163 ->getType()
21164 .getNonReferenceType()
21165 ->isPointerType() &&
21166 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
21167 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21168 << (LangOpts.OpenMP >= 50 ? 1 : 0)
21169 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
21170 continue;
21171 }
21172
21173 ExprResult Res;
21174 {
21175 Sema::TentativeAnalysisScope Trap(*this);
21176 Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
21177 RefExpr->IgnoreParenImpCasts());
21178 }
21179 if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr) &&
21180 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
21181 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21182 << (LangOpts.OpenMP >= 50 ? 1 : 0)
21183 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
21184 continue;
21185 }
21186 }
21187 }
21188 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21189 }
21190 }
21191
21192 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
21193 DepKind != OMPC_DEPEND_outallmemory &&
21194 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
21195 return nullptr;
21196
21197 auto *C = OMPDependClause::Create(
21198 Context, StartLoc, LParenLoc, EndLoc,
21199 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
21200 TotalDepCount.getZExtValue());
21201 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
21202 DSAStack->isParentOrderedRegion())
21203 DSAStack->addDoacrossDependClause(C, OpsOffs);
21204 return C;
21205}
21206
21208 Expr *Device, SourceLocation StartLoc,
21209 SourceLocation LParenLoc,
21210 SourceLocation ModifierLoc,
21211 SourceLocation EndLoc) {
21212 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 50) &&
21213 "Unexpected device modifier in OpenMP < 50.");
21214
21215 bool ErrorFound = false;
21216 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
21217 std::string Values =
21218 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
21219 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21220 << Values << getOpenMPClauseName(OMPC_device);
21221 ErrorFound = true;
21222 }
21223
21224 Expr *ValExpr = Device;
21225 Stmt *HelperValStmt = nullptr;
21226
21227 // OpenMP [2.9.1, Restrictions]
21228 // The device expression must evaluate to a non-negative integer value.
21229 ErrorFound = !isNonNegativeIntegerValue(ValExpr, *this, OMPC_device,
21230 /*StrictlyPositive=*/false) ||
21231 ErrorFound;
21232 if (ErrorFound)
21233 return nullptr;
21234
21235 // OpenMP 5.0 [2.12.5, Restrictions]
21236 // In case of ancestor device-modifier, a requires directive with
21237 // the reverse_offload clause must be specified.
21238 if (Modifier == OMPC_DEVICE_ancestor) {
21239 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
21240 targetDiag(
21241 StartLoc,
21242 diag::err_omp_device_ancestor_without_requires_reverse_offload);
21243 ErrorFound = true;
21244 }
21245 }
21246
21247 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
21248 OpenMPDirectiveKind CaptureRegion =
21249 getOpenMPCaptureRegionForClause(DKind, OMPC_device, LangOpts.OpenMP);
21250 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
21251 ValExpr = MakeFullExpr(ValExpr).get();
21252 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21253 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
21254 HelperValStmt = buildPreInits(Context, Captures);
21255 }
21256
21257 return new (Context)
21258 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
21259 LParenLoc, ModifierLoc, EndLoc);
21260}
21261
21263 DSAStackTy *Stack, QualType QTy,
21264 bool FullCheck = true) {
21265 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
21266 return false;
21267 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
21268 !QTy.isTriviallyCopyableType(SemaRef.Context))
21269 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
21270 return true;
21271}
21272
21273/// Return true if it can be proven that the provided array expression
21274/// (array section or array subscript) does NOT specify the whole size of the
21275/// array whose base type is \a BaseQTy.
21277 const Expr *E,
21278 QualType BaseQTy) {
21279 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
21280
21281 // If this is an array subscript, it refers to the whole size if the size of
21282 // the dimension is constant and equals 1. Also, an array section assumes the
21283 // format of an array subscript if no colon is used.
21284 if (isa<ArraySubscriptExpr>(E) ||
21285 (OASE && OASE->getColonLocFirst().isInvalid())) {
21286 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21287 return ATy->getSize().getSExtValue() != 1;
21288 // Size can't be evaluated statically.
21289 return false;
21290 }
21291
21292 assert(OASE && "Expecting array section if not an array subscript.");
21293 const Expr *LowerBound = OASE->getLowerBound();
21294 const Expr *Length = OASE->getLength();
21295
21296 // If there is a lower bound that does not evaluates to zero, we are not
21297 // covering the whole dimension.
21298 if (LowerBound) {
21300 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
21301 return false; // Can't get the integer value as a constant.
21302
21303 llvm::APSInt ConstLowerBound = Result.Val.getInt();
21304 if (ConstLowerBound.getSExtValue())
21305 return true;
21306 }
21307
21308 // If we don't have a length we covering the whole dimension.
21309 if (!Length)
21310 return false;
21311
21312 // If the base is a pointer, we don't have a way to get the size of the
21313 // pointee.
21314 if (BaseQTy->isPointerType())
21315 return false;
21316
21317 // We can only check if the length is the same as the size of the dimension
21318 // if we have a constant array.
21319 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
21320 if (!CATy)
21321 return false;
21322
21324 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21325 return false; // Can't get the integer value as a constant.
21326
21327 llvm::APSInt ConstLength = Result.Val.getInt();
21328 return CATy->getSize().getSExtValue() != ConstLength.getSExtValue();
21329}
21330
21331// Return true if it can be proven that the provided array expression (array
21332// section or array subscript) does NOT specify a single element of the array
21333// whose base type is \a BaseQTy.
21335 const Expr *E,
21336 QualType BaseQTy) {
21337 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
21338
21339 // An array subscript always refer to a single element. Also, an array section
21340 // assumes the format of an array subscript if no colon is used.
21341 if (isa<ArraySubscriptExpr>(E) ||
21342 (OASE && OASE->getColonLocFirst().isInvalid()))
21343 return false;
21344
21345 assert(OASE && "Expecting array section if not an array subscript.");
21346 const Expr *Length = OASE->getLength();
21347
21348 // If we don't have a length we have to check if the array has unitary size
21349 // for this dimension. Also, we should always expect a length if the base type
21350 // is pointer.
21351 if (!Length) {
21352 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21353 return ATy->getSize().getSExtValue() != 1;
21354 // We cannot assume anything.
21355 return false;
21356 }
21357
21358 // Check if the length evaluates to 1.
21360 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21361 return false; // Can't get the integer value as a constant.
21362
21363 llvm::APSInt ConstLength = Result.Val.getInt();
21364 return ConstLength.getSExtValue() != 1;
21365}
21366
21367// The base of elements of list in a map clause have to be either:
21368// - a reference to variable or field.
21369// - a member expression.
21370// - an array expression.
21371//
21372// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
21373// reference to 'r'.
21374//
21375// If we have:
21376//
21377// struct SS {
21378// Bla S;
21379// foo() {
21380// #pragma omp target map (S.Arr[:12]);
21381// }
21382// }
21383//
21384// We want to retrieve the member expression 'this->S';
21385
21386// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
21387// If a list item is an array section, it must specify contiguous storage.
21388//
21389// For this restriction it is sufficient that we make sure only references
21390// to variables or fields and array expressions, and that no array sections
21391// exist except in the rightmost expression (unless they cover the whole
21392// dimension of the array). E.g. these would be invalid:
21393//
21394// r.ArrS[3:5].Arr[6:7]
21395//
21396// r.ArrS[3:5].x
21397//
21398// but these would be valid:
21399// r.ArrS[3].Arr[6:7]
21400//
21401// r.ArrS[3].x
21402namespace {
21403class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
21404 Sema &SemaRef;
21405 OpenMPClauseKind CKind = OMPC_unknown;
21406 OpenMPDirectiveKind DKind = OMPD_unknown;
21408 bool IsNonContiguous = false;
21409 bool NoDiagnose = false;
21410 const Expr *RelevantExpr = nullptr;
21411 bool AllowUnitySizeArraySection = true;
21412 bool AllowWholeSizeArraySection = true;
21413 bool AllowAnotherPtr = true;
21414 SourceLocation ELoc;
21415 SourceRange ERange;
21416
21417 void emitErrorMsg() {
21418 // If nothing else worked, this is not a valid map clause expression.
21419 if (SemaRef.getLangOpts().OpenMP < 50) {
21420 SemaRef.Diag(ELoc,
21421 diag::err_omp_expected_named_var_member_or_array_expression)
21422 << ERange;
21423 } else {
21424 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21425 << getOpenMPClauseName(CKind) << ERange;
21426 }
21427 }
21428
21429public:
21430 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
21431 if (!isa<VarDecl>(DRE->getDecl())) {
21432 emitErrorMsg();
21433 return false;
21434 }
21435 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21436 RelevantExpr = DRE;
21437 // Record the component.
21438 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
21439 return true;
21440 }
21441
21442 bool VisitMemberExpr(MemberExpr *ME) {
21443 Expr *E = ME;
21444 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
21445
21446 if (isa<CXXThisExpr>(BaseE)) {
21447 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21448 // We found a base expression: this->Val.
21449 RelevantExpr = ME;
21450 } else {
21451 E = BaseE;
21452 }
21453
21454 if (!isa<FieldDecl>(ME->getMemberDecl())) {
21455 if (!NoDiagnose) {
21456 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
21457 << ME->getSourceRange();
21458 return false;
21459 }
21460 if (RelevantExpr)
21461 return false;
21462 return Visit(E);
21463 }
21464
21465 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
21466
21467 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
21468 // A bit-field cannot appear in a map clause.
21469 //
21470 if (FD->isBitField()) {
21471 if (!NoDiagnose) {
21472 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
21473 << ME->getSourceRange() << getOpenMPClauseName(CKind);
21474 return false;
21475 }
21476 if (RelevantExpr)
21477 return false;
21478 return Visit(E);
21479 }
21480
21481 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21482 // If the type of a list item is a reference to a type T then the type
21483 // will be considered to be T for all purposes of this clause.
21484 QualType CurType = BaseE->getType().getNonReferenceType();
21485
21486 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
21487 // A list item cannot be a variable that is a member of a structure with
21488 // a union type.
21489 //
21490 if (CurType->isUnionType()) {
21491 if (!NoDiagnose) {
21492 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
21493 << ME->getSourceRange();
21494 return false;
21495 }
21496 return RelevantExpr || Visit(E);
21497 }
21498
21499 // If we got a member expression, we should not expect any array section
21500 // before that:
21501 //
21502 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
21503 // If a list item is an element of a structure, only the rightmost symbol
21504 // of the variable reference can be an array section.
21505 //
21506 AllowUnitySizeArraySection = false;
21507 AllowWholeSizeArraySection = false;
21508
21509 // Record the component.
21510 Components.emplace_back(ME, FD, IsNonContiguous);
21511 return RelevantExpr || Visit(E);
21512 }
21513
21514 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
21515 Expr *E = AE->getBase()->IgnoreParenImpCasts();
21516
21517 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
21518 if (!NoDiagnose) {
21519 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21520 << 0 << AE->getSourceRange();
21521 return false;
21522 }
21523 return RelevantExpr || Visit(E);
21524 }
21525
21526 // If we got an array subscript that express the whole dimension we
21527 // can have any array expressions before. If it only expressing part of
21528 // the dimension, we can only have unitary-size array expressions.
21530 AllowWholeSizeArraySection = false;
21531
21532 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
21533 Expr::EvalResult Result;
21534 if (!AE->getIdx()->isValueDependent() &&
21535 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
21536 !Result.Val.getInt().isZero()) {
21537 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21538 diag::err_omp_invalid_map_this_expr);
21539 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21540 diag::note_omp_invalid_subscript_on_this_ptr_map);
21541 }
21542 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21543 RelevantExpr = TE;
21544 }
21545
21546 // Record the component - we don't have any declaration associated.
21547 Components.emplace_back(AE, nullptr, IsNonContiguous);
21548
21549 return RelevantExpr || Visit(E);
21550 }
21551
21552 bool VisitOMPArraySectionExpr(OMPArraySectionExpr *OASE) {
21553 // After OMP 5.0 Array section in reduction clause will be implicitly
21554 // mapped
21555 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
21556 "Array sections cannot be implicitly mapped.");
21557 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21558 QualType CurType =
21560
21561 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21562 // If the type of a list item is a reference to a type T then the type
21563 // will be considered to be T for all purposes of this clause.
21564 if (CurType->isReferenceType())
21565 CurType = CurType->getPointeeType();
21566
21567 bool IsPointer = CurType->isAnyPointerType();
21568
21569 if (!IsPointer && !CurType->isArrayType()) {
21570 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21571 << 0 << OASE->getSourceRange();
21572 return false;
21573 }
21574
21575 bool NotWhole =
21576 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
21577 bool NotUnity =
21578 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
21579
21580 if (AllowWholeSizeArraySection) {
21581 // Any array section is currently allowed. Allowing a whole size array
21582 // section implies allowing a unity array section as well.
21583 //
21584 // If this array section refers to the whole dimension we can still
21585 // accept other array sections before this one, except if the base is a
21586 // pointer. Otherwise, only unitary sections are accepted.
21587 if (NotWhole || IsPointer)
21588 AllowWholeSizeArraySection = false;
21589 } else if (DKind == OMPD_target_update &&
21590 SemaRef.getLangOpts().OpenMP >= 50) {
21591 if (IsPointer && !AllowAnotherPtr)
21592 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
21593 << /*array of unknown bound */ 1;
21594 else
21595 IsNonContiguous = true;
21596 } else if (AllowUnitySizeArraySection && NotUnity) {
21597 // A unity or whole array section is not allowed and that is not
21598 // compatible with the properties of the current array section.
21599 if (NoDiagnose)
21600 return false;
21601 SemaRef.Diag(ELoc,
21602 diag::err_array_section_does_not_specify_contiguous_storage)
21603 << OASE->getSourceRange();
21604 return false;
21605 }
21606
21607 if (IsPointer)
21608 AllowAnotherPtr = false;
21609
21610 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
21611 Expr::EvalResult ResultR;
21612 Expr::EvalResult ResultL;
21613 if (!OASE->getLength()->isValueDependent() &&
21614 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
21615 !ResultR.Val.getInt().isOne()) {
21616 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21617 diag::err_omp_invalid_map_this_expr);
21618 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21619 diag::note_omp_invalid_length_on_this_ptr_mapping);
21620 }
21621 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
21622 OASE->getLowerBound()->EvaluateAsInt(ResultL,
21623 SemaRef.getASTContext()) &&
21624 !ResultL.Val.getInt().isZero()) {
21625 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21626 diag::err_omp_invalid_map_this_expr);
21627 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21628 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
21629 }
21630 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21631 RelevantExpr = TE;
21632 }
21633
21634 // Record the component - we don't have any declaration associated.
21635 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
21636 return RelevantExpr || Visit(E);
21637 }
21638 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
21639 Expr *Base = E->getBase();
21640
21641 // Record the component - we don't have any declaration associated.
21642 Components.emplace_back(E, nullptr, IsNonContiguous);
21643
21644 return Visit(Base->IgnoreParenImpCasts());
21645 }
21646
21647 bool VisitUnaryOperator(UnaryOperator *UO) {
21648 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
21649 UO->getOpcode() != UO_Deref) {
21650 emitErrorMsg();
21651 return false;
21652 }
21653 if (!RelevantExpr) {
21654 // Record the component if haven't found base decl.
21655 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
21656 }
21657 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
21658 }
21659 bool VisitBinaryOperator(BinaryOperator *BO) {
21660 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
21661 emitErrorMsg();
21662 return false;
21663 }
21664
21665 // Pointer arithmetic is the only thing we expect to happen here so after we
21666 // make sure the binary operator is a pointer type, the only thing we need
21667 // to do is to visit the subtree that has the same type as root (so that we
21668 // know the other subtree is just an offset)
21669 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
21670 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
21671 Components.emplace_back(BO, nullptr, false);
21672 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
21673 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
21674 "Either LHS or RHS have base decl inside");
21675 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
21676 return RelevantExpr || Visit(LE);
21677 return RelevantExpr || Visit(RE);
21678 }
21679 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
21680 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21681 RelevantExpr = CTE;
21682 Components.emplace_back(CTE, nullptr, IsNonContiguous);
21683 return true;
21684 }
21685 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
21686 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21687 Components.emplace_back(COCE, nullptr, IsNonContiguous);
21688 return true;
21689 }
21690 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
21691 Expr *Source = E->getSourceExpr();
21692 if (!Source) {
21693 emitErrorMsg();
21694 return false;
21695 }
21696 return Visit(Source);
21697 }
21698 bool VisitStmt(Stmt *) {
21699 emitErrorMsg();
21700 return false;
21701 }
21702 const Expr *getFoundBase() const { return RelevantExpr; }
21703 explicit MapBaseChecker(
21704 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
21706 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
21707 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
21708 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
21709};
21710} // namespace
21711
21712/// Return the expression of the base of the mappable expression or null if it
21713/// cannot be determined and do all the necessary checks to see if the
21714/// expression is valid as a standalone mappable expression. In the process,
21715/// record all the components of the expression.
21717 Sema &SemaRef, Expr *E,
21719 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
21720 SourceLocation ELoc = E->getExprLoc();
21721 SourceRange ERange = E->getSourceRange();
21722 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
21723 ERange);
21724 if (Checker.Visit(E->IgnoreParens())) {
21725 // Check if the highest dimension array section has length specified
21726 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
21727 (CKind == OMPC_to || CKind == OMPC_from)) {
21728 auto CI = CurComponents.rbegin();
21729 auto CE = CurComponents.rend();
21730 for (; CI != CE; ++CI) {
21731 const auto *OASE =
21732 dyn_cast<OMPArraySectionExpr>(CI->getAssociatedExpression());
21733 if (!OASE)
21734 continue;
21735 if (OASE && OASE->getLength())
21736 break;
21737 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
21738 << ERange;
21739 }
21740 }
21741 return Checker.getFoundBase();
21742 }
21743 return nullptr;
21744}
21745
21746// Return true if expression E associated with value VD has conflicts with other
21747// map information.
21749 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
21750 bool CurrentRegionOnly,
21752 OpenMPClauseKind CKind) {
21753 assert(VD && E);
21754 SourceLocation ELoc = E->getExprLoc();
21755 SourceRange ERange = E->getSourceRange();
21756
21757 // In order to easily check the conflicts we need to match each component of
21758 // the expression under test with the components of the expressions that are
21759 // already in the stack.
21760
21761 assert(!CurComponents.empty() && "Map clause expression with no components!");
21762 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
21763 "Map clause expression with unexpected base!");
21764
21765 // Variables to help detecting enclosing problems in data environment nests.
21766 bool IsEnclosedByDataEnvironmentExpr = false;
21767 const Expr *EnclosingExpr = nullptr;
21768
21769 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
21770 VD, CurrentRegionOnly,
21771 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
21772 ERange, CKind, &EnclosingExpr,
21774 StackComponents,
21775 OpenMPClauseKind Kind) {
21776 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
21777 return false;
21778 assert(!StackComponents.empty() &&
21779 "Map clause expression with no components!");
21780 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
21781 "Map clause expression with unexpected base!");
21782 (void)VD;
21783
21784 // The whole expression in the stack.
21785 const Expr *RE = StackComponents.front().getAssociatedExpression();
21786
21787 // Expressions must start from the same base. Here we detect at which
21788 // point both expressions diverge from each other and see if we can
21789 // detect if the memory referred to both expressions is contiguous and
21790 // do not overlap.
21791 auto CI = CurComponents.rbegin();
21792 auto CE = CurComponents.rend();
21793 auto SI = StackComponents.rbegin();
21794 auto SE = StackComponents.rend();
21795 for (; CI != CE && SI != SE; ++CI, ++SI) {
21796
21797 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
21798 // At most one list item can be an array item derived from a given
21799 // variable in map clauses of the same construct.
21800 if (CurrentRegionOnly &&
21801 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
21802 isa<OMPArraySectionExpr>(CI->getAssociatedExpression()) ||
21803 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
21804 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
21805 isa<OMPArraySectionExpr>(SI->getAssociatedExpression()) ||
21806 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
21807 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
21808 diag::err_omp_multiple_array_items_in_map_clause)
21809 << CI->getAssociatedExpression()->getSourceRange();
21810 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
21811 diag::note_used_here)
21812 << SI->getAssociatedExpression()->getSourceRange();
21813 return true;
21814 }
21815
21816 // Do both expressions have the same kind?
21817 if (CI->getAssociatedExpression()->getStmtClass() !=
21818 SI->getAssociatedExpression()->getStmtClass())
21819 break;
21820
21821 // Are we dealing with different variables/fields?
21822 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
21823 break;
21824 }
21825 // Check if the extra components of the expressions in the enclosing
21826 // data environment are redundant for the current base declaration.
21827 // If they are, the maps completely overlap, which is legal.
21828 for (; SI != SE; ++SI) {
21829 QualType Type;
21830 if (const auto *ASE =
21831 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
21832 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
21833 } else if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(
21834 SI->getAssociatedExpression())) {
21835 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21836 Type =
21837 OMPArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
21838 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
21839 SI->getAssociatedExpression())) {
21840 Type = OASE->getBase()->getType()->getPointeeType();
21841 }
21842 if (Type.isNull() || Type->isAnyPointerType() ||
21844 SemaRef, SI->getAssociatedExpression(), Type))
21845 break;
21846 }
21847
21848 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21849 // List items of map clauses in the same construct must not share
21850 // original storage.
21851 //
21852 // If the expressions are exactly the same or one is a subset of the
21853 // other, it means they are sharing storage.
21854 if (CI == CE && SI == SE) {
21855 if (CurrentRegionOnly) {
21856 if (CKind == OMPC_map) {
21857 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21858 } else {
21859 assert(CKind == OMPC_to || CKind == OMPC_from);
21860 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21861 << ERange;
21862 }
21863 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21864 << RE->getSourceRange();
21865 return true;
21866 }
21867 // If we find the same expression in the enclosing data environment,
21868 // that is legal.
21869 IsEnclosedByDataEnvironmentExpr = true;
21870 return false;
21871 }
21872
21873 QualType DerivedType =
21874 std::prev(CI)->getAssociatedDeclaration()->getType();
21875 SourceLocation DerivedLoc =
21876 std::prev(CI)->getAssociatedExpression()->getExprLoc();
21877
21878 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21879 // If the type of a list item is a reference to a type T then the type
21880 // will be considered to be T for all purposes of this clause.
21881 DerivedType = DerivedType.getNonReferenceType();
21882
21883 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
21884 // A variable for which the type is pointer and an array section
21885 // derived from that variable must not appear as list items of map
21886 // clauses of the same construct.
21887 //
21888 // Also, cover one of the cases in:
21889 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21890 // If any part of the original storage of a list item has corresponding
21891 // storage in the device data environment, all of the original storage
21892 // must have corresponding storage in the device data environment.
21893 //
21894 if (DerivedType->isAnyPointerType()) {
21895 if (CI == CE || SI == SE) {
21896 SemaRef.Diag(
21897 DerivedLoc,
21898 diag::err_omp_pointer_mapped_along_with_derived_section)
21899 << DerivedLoc;
21900 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21901 << RE->getSourceRange();
21902 return true;
21903 }
21904 if (CI->getAssociatedExpression()->getStmtClass() !=
21905 SI->getAssociatedExpression()->getStmtClass() ||
21906 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
21907 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
21908 assert(CI != CE && SI != SE);
21909 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
21910 << DerivedLoc;
21911 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21912 << RE->getSourceRange();
21913 return true;
21914 }
21915 }
21916
21917 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21918 // List items of map clauses in the same construct must not share
21919 // original storage.
21920 //
21921 // An expression is a subset of the other.
21922 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
21923 if (CKind == OMPC_map) {
21924 if (CI != CE || SI != SE) {
21925 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
21926 // a pointer.
21927 auto Begin =
21928 CI != CE ? CurComponents.begin() : StackComponents.begin();
21929 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
21930 auto It = Begin;
21931 while (It != End && !It->getAssociatedDeclaration())
21932 std::advance(It, 1);
21933 assert(It != End &&
21934 "Expected at least one component with the declaration.");
21935 if (It != Begin && It->getAssociatedDeclaration()
21936 ->getType()
21937 .getCanonicalType()
21938 ->isAnyPointerType()) {
21939 IsEnclosedByDataEnvironmentExpr = false;
21940 EnclosingExpr = nullptr;
21941 return false;
21942 }
21943 }
21944 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21945 } else {
21946 assert(CKind == OMPC_to || CKind == OMPC_from);
21947 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21948 << ERange;
21949 }
21950 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21951 << RE->getSourceRange();
21952 return true;
21953 }
21954
21955 // The current expression uses the same base as other expression in the
21956 // data environment but does not contain it completely.
21957 if (!CurrentRegionOnly && SI != SE)
21958 EnclosingExpr = RE;
21959
21960 // The current expression is a subset of the expression in the data
21961 // environment.
21962 IsEnclosedByDataEnvironmentExpr |=
21963 (!CurrentRegionOnly && CI != CE && SI == SE);
21964
21965 return false;
21966 });
21967
21968 if (CurrentRegionOnly)
21969 return FoundError;
21970
21971 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21972 // If any part of the original storage of a list item has corresponding
21973 // storage in the device data environment, all of the original storage must
21974 // have corresponding storage in the device data environment.
21975 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
21976 // If a list item is an element of a structure, and a different element of
21977 // the structure has a corresponding list item in the device data environment
21978 // prior to a task encountering the construct associated with the map clause,
21979 // then the list item must also have a corresponding list item in the device
21980 // data environment prior to the task encountering the construct.
21981 //
21982 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
21983 SemaRef.Diag(ELoc,
21984 diag::err_omp_original_storage_is_shared_and_does_not_contain)
21985 << ERange;
21986 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
21987 << EnclosingExpr->getSourceRange();
21988 return true;
21989 }
21990
21991 return FoundError;
21992}
21993
21994// Look up the user-defined mapper given the mapper name and mapped type, and
21995// build a reference to it.
21997 CXXScopeSpec &MapperIdScopeSpec,
21998 const DeclarationNameInfo &MapperId,
21999 QualType Type,
22000 Expr *UnresolvedMapper) {
22001 if (MapperIdScopeSpec.isInvalid())
22002 return ExprError();
22003 // Get the actual type for the array type.
22004 if (Type->isArrayType()) {
22005 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
22007 }
22008 // Find all user-defined mappers with the given MapperId.
22009 SmallVector<UnresolvedSet<8>, 4> Lookups;
22010 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
22011 Lookup.suppressDiagnostics();
22012 if (S) {
22013 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec)) {
22014 NamedDecl *D = Lookup.getRepresentativeDecl();
22015 while (S && !S->isDeclScope(D))
22016 S = S->getParent();
22017 if (S)
22018 S = S->getParent();
22019 Lookups.emplace_back();
22020 Lookups.back().append(Lookup.begin(), Lookup.end());
22021 Lookup.clear();
22022 }
22023 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
22024 // Extract the user-defined mappers with the given MapperId.
22025 Lookups.push_back(UnresolvedSet<8>());
22026 for (NamedDecl *D : ULE->decls()) {
22027 auto *DMD = cast<OMPDeclareMapperDecl>(D);
22028 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
22029 Lookups.back().addDecl(DMD);
22030 }
22031 }
22032 // Defer the lookup for dependent types. The results will be passed through
22033 // UnresolvedMapper on instantiation.
22034 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
22037 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
22038 return !D->isInvalidDecl() &&
22039 (D->getType()->isDependentType() ||
22040 D->getType()->isInstantiationDependentType() ||
22041 D->getType()->containsUnexpandedParameterPack());
22042 })) {
22043 UnresolvedSet<8> URS;
22044 for (const UnresolvedSet<8> &Set : Lookups) {
22045 if (Set.empty())
22046 continue;
22047 URS.append(Set.begin(), Set.end());
22048 }
22050 SemaRef.Context, /*NamingClass=*/nullptr,
22051 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
22052 /*ADL=*/false, /*Overloaded=*/true, URS.begin(), URS.end());
22053 }
22054 SourceLocation Loc = MapperId.getLoc();
22055 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22056 // The type must be of struct, union or class type in C and C++
22058 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
22059 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
22060 return ExprError();
22061 }
22062 // Perform argument dependent lookup.
22063 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
22064 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
22065 // Return the first user-defined mapper with the desired type.
22066 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
22067 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
22068 if (!D->isInvalidDecl() &&
22069 SemaRef.Context.hasSameType(D->getType(), Type))
22070 return D;
22071 return nullptr;
22072 }))
22073 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
22074 // Find the first user-defined mapper with a type derived from the desired
22075 // type.
22076 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
22077 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
22078 if (!D->isInvalidDecl() &&
22079 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
22080 !Type.isMoreQualifiedThan(D->getType()))
22081 return D;
22082 return nullptr;
22083 })) {
22084 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
22085 /*DetectVirtual=*/false);
22086 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
22087 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
22088 VD->getType().getUnqualifiedType()))) {
22089 if (SemaRef.CheckBaseClassAccess(
22090 Loc, VD->getType(), Type, Paths.front(),
22091 /*DiagID=*/0) != Sema::AR_inaccessible) {
22092 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
22093 }
22094 }
22095 }
22096 }
22097 // Report error if a mapper is specified, but cannot be found.
22098 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
22099 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
22100 << Type << MapperId.getName();
22101 return ExprError();
22102 }
22103 return ExprEmpty();
22104}
22105
22106namespace {
22107// Utility struct that gathers all the related lists associated with a mappable
22108// expression.
22109struct MappableVarListInfo {
22110 // The list of expressions.
22111 ArrayRef<Expr *> VarList;
22112 // The list of processed expressions.
22113 SmallVector<Expr *, 16> ProcessedVarList;
22114 // The mappble components for each expression.
22116 // The base declaration of the variable.
22117 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
22118 // The reference to the user-defined mapper associated with every expression.
22119 SmallVector<Expr *, 16> UDMapperList;
22120
22121 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
22122 // We have a list of components and base declarations for each entry in the
22123 // variable list.
22124 VarComponents.reserve(VarList.size());
22125 VarBaseDeclarations.reserve(VarList.size());
22126 }
22127};
22128} // namespace
22129
22130// Check the validity of the provided variable list for the provided clause kind
22131// \a CKind. In the check process the valid expressions, mappable expression
22132// components, variables, and user-defined mappers are extracted and used to
22133// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
22134// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
22135// and \a MapperId are expected to be valid if the clause kind is 'map'.
22137 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
22138 MappableVarListInfo &MVLI, SourceLocation StartLoc,
22139 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
22140 ArrayRef<Expr *> UnresolvedMappers,
22142 ArrayRef<OpenMPMapModifierKind> Modifiers = std::nullopt,
22143 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
22144 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
22145 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
22146 "Unexpected clause kind with mappable expressions!");
22147
22148 // If the identifier of user-defined mapper is not specified, it is "default".
22149 // We do not change the actual name in this clause to distinguish whether a
22150 // mapper is specified explicitly, i.e., it is not explicitly specified when
22151 // MapperId.getName() is empty.
22152 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
22153 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
22154 MapperId.setName(DeclNames.getIdentifier(
22155 &SemaRef.getASTContext().Idents.get("default")));
22156 MapperId.setLoc(StartLoc);
22157 }
22158
22159 // Iterators to find the current unresolved mapper expression.
22160 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
22161 bool UpdateUMIt = false;
22162 Expr *UnresolvedMapper = nullptr;
22163
22164 bool HasHoldModifier =
22165 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
22166
22167 // Keep track of the mappable components and base declarations in this clause.
22168 // Each entry in the list is going to have a list of components associated. We
22169 // record each set of the components so that we can build the clause later on.
22170 // In the end we should have the same amount of declarations and component
22171 // lists.
22172
22173 for (Expr *RE : MVLI.VarList) {
22174 assert(RE && "Null expr in omp to/from/map clause");
22175 SourceLocation ELoc = RE->getExprLoc();
22176
22177 // Find the current unresolved mapper expression.
22178 if (UpdateUMIt && UMIt != UMEnd) {
22179 UMIt++;
22180 assert(
22181 UMIt != UMEnd &&
22182 "Expect the size of UnresolvedMappers to match with that of VarList");
22183 }
22184 UpdateUMIt = true;
22185 if (UMIt != UMEnd)
22186 UnresolvedMapper = *UMIt;
22187
22188 const Expr *VE = RE->IgnoreParenLValueCasts();
22189
22190 if (VE->isValueDependent() || VE->isTypeDependent() ||
22193 // Try to find the associated user-defined mapper.
22195 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22196 VE->getType().getCanonicalType(), UnresolvedMapper);
22197 if (ER.isInvalid())
22198 continue;
22199 MVLI.UDMapperList.push_back(ER.get());
22200 // We can only analyze this information once the missing information is
22201 // resolved.
22202 MVLI.ProcessedVarList.push_back(RE);
22203 continue;
22204 }
22205
22206 Expr *SimpleExpr = RE->IgnoreParenCasts();
22207
22208 if (!RE->isLValue()) {
22209 if (SemaRef.getLangOpts().OpenMP < 50) {
22210 SemaRef.Diag(
22211 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
22212 << RE->getSourceRange();
22213 } else {
22214 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22215 << getOpenMPClauseName(CKind) << RE->getSourceRange();
22216 }
22217 continue;
22218 }
22219
22221 ValueDecl *CurDeclaration = nullptr;
22222
22223 // Obtain the array or member expression bases if required. Also, fill the
22224 // components array with all the components identified in the process.
22225 const Expr *BE =
22226 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
22227 DSAS->getCurrentDirective(), NoDiagnose);
22228 if (!BE)
22229 continue;
22230
22231 assert(!CurComponents.empty() &&
22232 "Invalid mappable expression information.");
22233
22234 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
22235 // Add store "this" pointer to class in DSAStackTy for future checking
22236 DSAS->addMappedClassesQualTypes(TE->getType());
22237 // Try to find the associated user-defined mapper.
22239 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22240 VE->getType().getCanonicalType(), UnresolvedMapper);
22241 if (ER.isInvalid())
22242 continue;
22243 MVLI.UDMapperList.push_back(ER.get());
22244 // Skip restriction checking for variable or field declarations
22245 MVLI.ProcessedVarList.push_back(RE);
22246 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22247 MVLI.VarComponents.back().append(CurComponents.begin(),
22248 CurComponents.end());
22249 MVLI.VarBaseDeclarations.push_back(nullptr);
22250 continue;
22251 }
22252
22253 // For the following checks, we rely on the base declaration which is
22254 // expected to be associated with the last component. The declaration is
22255 // expected to be a variable or a field (if 'this' is being mapped).
22256 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
22257 assert(CurDeclaration && "Null decl on map clause.");
22258 assert(
22259 CurDeclaration->isCanonicalDecl() &&
22260 "Expecting components to have associated only canonical declarations.");
22261
22262 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
22263 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
22264
22265 assert((VD || FD) && "Only variables or fields are expected here!");
22266 (void)FD;
22267
22268 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
22269 // threadprivate variables cannot appear in a map clause.
22270 // OpenMP 4.5 [2.10.5, target update Construct]
22271 // threadprivate variables cannot appear in a from clause.
22272 if (VD && DSAS->isThreadPrivate(VD)) {
22273 if (NoDiagnose)
22274 continue;
22275 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
22276 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
22277 << getOpenMPClauseName(CKind);
22278 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
22279 continue;
22280 }
22281
22282 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22283 // A list item cannot appear in both a map clause and a data-sharing
22284 // attribute clause on the same construct.
22285
22286 // Check conflicts with other map clause expressions. We check the conflicts
22287 // with the current construct separately from the enclosing data
22288 // environment, because the restrictions are different. We only have to
22289 // check conflicts across regions for the map clauses.
22290 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
22291 /*CurrentRegionOnly=*/true, CurComponents, CKind))
22292 break;
22293 if (CKind == OMPC_map &&
22294 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
22295 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
22296 /*CurrentRegionOnly=*/false, CurComponents, CKind))
22297 break;
22298
22299 // OpenMP 4.5 [2.10.5, target update Construct]
22300 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22301 // If the type of a list item is a reference to a type T then the type will
22302 // be considered to be T for all purposes of this clause.
22303 auto I = llvm::find_if(
22304 CurComponents,
22306 return MC.getAssociatedDeclaration();
22307 });
22308 assert(I != CurComponents.end() && "Null decl on map clause.");
22309 (void)I;
22310 QualType Type;
22311 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
22312 auto *OASE = dyn_cast<OMPArraySectionExpr>(VE->IgnoreParens());
22313 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
22314 if (ASE) {
22315 Type = ASE->getType().getNonReferenceType();
22316 } else if (OASE) {
22317 QualType BaseType =
22319 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
22320 Type = ATy->getElementType();
22321 else
22322 Type = BaseType->getPointeeType();
22323 Type = Type.getNonReferenceType();
22324 } else if (OAShE) {
22325 Type = OAShE->getBase()->getType()->getPointeeType();
22326 } else {
22327 Type = VE->getType();
22328 }
22329
22330 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
22331 // A list item in a to or from clause must have a mappable type.
22332 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22333 // A list item must have a mappable type.
22334 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
22335 DSAS, Type, /*FullCheck=*/true))
22336 continue;
22337
22338 if (CKind == OMPC_map) {
22339 // target enter data
22340 // OpenMP [2.10.2, Restrictions, p. 99]
22341 // A map-type must be specified in all map clauses and must be either
22342 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
22343 // no map type is present.
22344 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
22345 if (DKind == OMPD_target_enter_data &&
22346 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
22347 SemaRef.getLangOpts().OpenMP >= 52)) {
22348 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22349 << (IsMapTypeImplicit ? 1 : 0)
22350 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22351 << getOpenMPDirectiveName(DKind);
22352 continue;
22353 }
22354
22355 // target exit_data
22356 // OpenMP [2.10.3, Restrictions, p. 102]
22357 // A map-type must be specified in all map clauses and must be either
22358 // from, release, or delete. Starting with OpenMP 5.2 the default map
22359 // type is `from` if no map type is present.
22360 if (DKind == OMPD_target_exit_data &&
22361 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
22362 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
22363 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22364 << (IsMapTypeImplicit ? 1 : 0)
22365 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22366 << getOpenMPDirectiveName(DKind);
22367 continue;
22368 }
22369
22370 // The 'ompx_hold' modifier is specifically intended to be used on a
22371 // 'target' or 'target data' directive to prevent data from being unmapped
22372 // during the associated statement. It is not permitted on a 'target
22373 // enter data' or 'target exit data' directive, which have no associated
22374 // statement.
22375 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
22376 HasHoldModifier) {
22377 SemaRef.Diag(StartLoc,
22378 diag::err_omp_invalid_map_type_modifier_for_directive)
22380 OMPC_MAP_MODIFIER_ompx_hold)
22381 << getOpenMPDirectiveName(DKind);
22382 continue;
22383 }
22384
22385 // target, target data
22386 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
22387 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
22388 // A map-type in a map clause must be to, from, tofrom or alloc
22389 if ((DKind == OMPD_target_data ||
22391 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
22392 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
22393 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22394 << (IsMapTypeImplicit ? 1 : 0)
22395 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22396 << getOpenMPDirectiveName(DKind);
22397 continue;
22398 }
22399
22400 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
22401 // A list item cannot appear in both a map clause and a data-sharing
22402 // attribute clause on the same construct
22403 //
22404 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
22405 // A list item cannot appear in both a map clause and a data-sharing
22406 // attribute clause on the same construct unless the construct is a
22407 // combined construct.
22408 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
22410 DKind == OMPD_target)) {
22411 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
22412 if (isOpenMPPrivate(DVar.CKind)) {
22413 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22414 << getOpenMPClauseName(DVar.CKind)
22415 << getOpenMPClauseName(OMPC_map)
22416 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
22417 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
22418 continue;
22419 }
22420 }
22421 }
22422
22423 // Try to find the associated user-defined mapper.
22425 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22426 Type.getCanonicalType(), UnresolvedMapper);
22427 if (ER.isInvalid())
22428 continue;
22429 MVLI.UDMapperList.push_back(ER.get());
22430
22431 // Save the current expression.
22432 MVLI.ProcessedVarList.push_back(RE);
22433
22434 // Store the components in the stack so that they can be used to check
22435 // against other clauses later on.
22436 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
22437 /*WhereFoundClauseKind=*/OMPC_map);
22438
22439 // Save the components and declaration to create the clause. For purposes of
22440 // the clause creation, any component list that has base 'this' uses
22441 // null as base declaration.
22442 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22443 MVLI.VarComponents.back().append(CurComponents.begin(),
22444 CurComponents.end());
22445 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
22446 : CurDeclaration);
22447 }
22448}
22449
22451 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
22452 ArrayRef<SourceLocation> MapTypeModifiersLoc,
22453 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22454 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
22455 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22456 const OMPVarListLocTy &Locs, bool NoDiagnose,
22457 ArrayRef<Expr *> UnresolvedMappers) {
22458 OpenMPMapModifierKind Modifiers[] = {
22463
22464 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
22465 BuiltinType::OMPIterator))
22466 Diag(IteratorModifier->getExprLoc(),
22467 diag::err_omp_map_modifier_not_iterator);
22468
22469 // Process map-type-modifiers, flag errors for duplicate modifiers.
22470 unsigned Count = 0;
22471 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
22472 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
22473 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
22474 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
22475 continue;
22476 }
22477 assert(Count < NumberOfOMPMapClauseModifiers &&
22478 "Modifiers exceed the allowed number of map type modifiers");
22479 Modifiers[Count] = MapTypeModifiers[I];
22480 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
22481 ++Count;
22482 }
22483
22484 MappableVarListInfo MVLI(VarList);
22485 checkMappableExpressionList(*this, DSAStack, OMPC_map, MVLI, Locs.StartLoc,
22486 MapperIdScopeSpec, MapperId, UnresolvedMappers,
22487 MapType, Modifiers, IsMapTypeImplicit,
22488 NoDiagnose);
22489
22490 // We need to produce a map clause even if we don't have variables so that
22491 // other diagnostics related with non-existing map clauses are accurate.
22492 return OMPMapClause::Create(
22493 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22494 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
22495 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(Context), MapperId,
22496 MapType, IsMapTypeImplicit, MapLoc);
22497}
22498
22501 assert(ParsedType.isUsable());
22502
22503 QualType ReductionType = GetTypeFromParser(ParsedType.get());
22504 if (ReductionType.isNull())
22505 return QualType();
22506
22507 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
22508 // A type name in a declare reduction directive cannot be a function type, an
22509 // array type, a reference type, or a type qualified with const, volatile or
22510 // restrict.
22511 if (ReductionType.hasQualifiers()) {
22512 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
22513 return QualType();
22514 }
22515
22516 if (ReductionType->isFunctionType()) {
22517 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
22518 return QualType();
22519 }
22520 if (ReductionType->isReferenceType()) {
22521 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
22522 return QualType();
22523 }
22524 if (ReductionType->isArrayType()) {
22525 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
22526 return QualType();
22527 }
22528 return ReductionType;
22529}
22530
22532 Scope *S, DeclContext *DC, DeclarationName Name,
22533 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
22534 AccessSpecifier AS, Decl *PrevDeclInScope) {
22536 Decls.reserve(ReductionTypes.size());
22537
22538 LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPReductionName,
22540 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
22541 // A reduction-identifier may not be re-declared in the current scope for the
22542 // same type or for a type that is compatible according to the base language
22543 // rules.
22544 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22545 OMPDeclareReductionDecl *PrevDRD = nullptr;
22546 bool InCompoundScope = true;
22547 if (S != nullptr) {
22548 // Find previous declaration with the same name not referenced in other
22549 // declarations.
22551 InCompoundScope =
22552 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22553 LookupName(Lookup, S);
22554 FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22555 /*AllowInlineNamespace=*/false);
22556 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
22557 LookupResult::Filter Filter = Lookup.makeFilter();
22558 while (Filter.hasNext()) {
22559 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
22560 if (InCompoundScope) {
22561 auto I = UsedAsPrevious.find(PrevDecl);
22562 if (I == UsedAsPrevious.end())
22563 UsedAsPrevious[PrevDecl] = false;
22564 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
22565 UsedAsPrevious[D] = true;
22566 }
22567 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22568 PrevDecl->getLocation();
22569 }
22570 Filter.done();
22571 if (InCompoundScope) {
22572 for (const auto &PrevData : UsedAsPrevious) {
22573 if (!PrevData.second) {
22574 PrevDRD = PrevData.first;
22575 break;
22576 }
22577 }
22578 }
22579 } else if (PrevDeclInScope != nullptr) {
22580 auto *PrevDRDInScope = PrevDRD =
22581 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
22582 do {
22583 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
22584 PrevDRDInScope->getLocation();
22585 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
22586 } while (PrevDRDInScope != nullptr);
22587 }
22588 for (const auto &TyData : ReductionTypes) {
22589 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
22590 bool Invalid = false;
22591 if (I != PreviousRedeclTypes.end()) {
22592 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
22593 << TyData.first;
22594 Diag(I->second, diag::note_previous_definition);
22595 Invalid = true;
22596 }
22597 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
22598 auto *DRD = OMPDeclareReductionDecl::Create(Context, DC, TyData.second,
22599 Name, TyData.first, PrevDRD);
22600 DC->addDecl(DRD);
22601 DRD->setAccess(AS);
22602 Decls.push_back(DRD);
22603 if (Invalid)
22604 DRD->setInvalidDecl();
22605 else
22606 PrevDRD = DRD;
22607 }
22608
22609 return DeclGroupPtrTy::make(
22610 DeclGroupRef::Create(Context, Decls.begin(), Decls.size()));
22611}
22612
22614 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22615
22616 // Enter new function scope.
22620
22621 if (S != nullptr)
22622 PushDeclContext(S, DRD);
22623 else
22624 CurContext = DRD;
22625
22628
22629 QualType ReductionType = DRD->getType();
22630 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
22631 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
22632 // uses semantics of argument handles by value, but it should be passed by
22633 // reference. C lang does not support references, so pass all parameters as
22634 // pointers.
22635 // Create 'T omp_in;' variable.
22636 VarDecl *OmpInParm =
22637 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_in");
22638 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
22639 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
22640 // uses semantics of argument handles by value, but it should be passed by
22641 // reference. C lang does not support references, so pass all parameters as
22642 // pointers.
22643 // Create 'T omp_out;' variable.
22644 VarDecl *OmpOutParm =
22645 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_out");
22646 if (S != nullptr) {
22647 PushOnScopeChains(OmpInParm, S);
22648 PushOnScopeChains(OmpOutParm, S);
22649 } else {
22650 DRD->addDecl(OmpInParm);
22651 DRD->addDecl(OmpOutParm);
22652 }
22653 Expr *InE =
22654 ::buildDeclRefExpr(*this, OmpInParm, ReductionType, D->getLocation());
22655 Expr *OutE =
22656 ::buildDeclRefExpr(*this, OmpOutParm, ReductionType, D->getLocation());
22657 DRD->setCombinerData(InE, OutE);
22658}
22659
22661 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22664
22667
22668 if (Combiner != nullptr)
22669 DRD->setCombiner(Combiner);
22670 else
22671 DRD->setInvalidDecl();
22672}
22673
22675 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22676
22677 // Enter new function scope.
22680
22681 if (S != nullptr)
22682 PushDeclContext(S, DRD);
22683 else
22684 CurContext = DRD;
22685
22688
22689 QualType ReductionType = DRD->getType();
22690 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
22691 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
22692 // uses semantics of argument handles by value, but it should be passed by
22693 // reference. C lang does not support references, so pass all parameters as
22694 // pointers.
22695 // Create 'T omp_priv;' variable.
22696 VarDecl *OmpPrivParm =
22697 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_priv");
22698 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
22699 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
22700 // uses semantics of argument handles by value, but it should be passed by
22701 // reference. C lang does not support references, so pass all parameters as
22702 // pointers.
22703 // Create 'T omp_orig;' variable.
22704 VarDecl *OmpOrigParm =
22705 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_orig");
22706 if (S != nullptr) {
22707 PushOnScopeChains(OmpPrivParm, S);
22708 PushOnScopeChains(OmpOrigParm, S);
22709 } else {
22710 DRD->addDecl(OmpPrivParm);
22711 DRD->addDecl(OmpOrigParm);
22712 }
22713 Expr *OrigE =
22714 ::buildDeclRefExpr(*this, OmpOrigParm, ReductionType, D->getLocation());
22715 Expr *PrivE =
22716 ::buildDeclRefExpr(*this, OmpPrivParm, ReductionType, D->getLocation());
22717 DRD->setInitializerData(OrigE, PrivE);
22718 return OmpPrivParm;
22719}
22720
22722 VarDecl *OmpPrivParm) {
22723 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22726
22729
22730 if (Initializer != nullptr) {
22731 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
22732 } else if (OmpPrivParm->hasInit()) {
22733 DRD->setInitializer(OmpPrivParm->getInit(),
22734 OmpPrivParm->isDirectInit()
22737 } else {
22738 DRD->setInvalidDecl();
22739 }
22740}
22741
22743 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
22744 for (Decl *D : DeclReductions.get()) {
22745 if (IsValid) {
22746 if (S)
22747 PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
22748 /*AddToContext=*/false);
22749 } else {
22750 D->setInvalidDecl();
22751 }
22752 }
22753 return DeclReductions;
22754}
22755
22758 QualType T = TInfo->getType();
22759 if (D.isInvalidType())
22760 return true;
22761
22762 if (getLangOpts().CPlusPlus) {
22763 // Check that there are no default arguments (C++ only).
22765 }
22766
22767 return CreateParsedType(T, TInfo);
22768}
22769
22772 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
22773
22774 QualType MapperType = GetTypeFromParser(ParsedType.get());
22775 assert(!MapperType.isNull() && "Expect valid mapper type");
22776
22777 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22778 // The type must be of struct, union or class type in C and C++
22779 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
22780 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
22781 return QualType();
22782 }
22783 return MapperType;
22784}
22785
22787 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
22789 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
22790 LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPMapperName,
22792 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22793 // A mapper-identifier may not be redeclared in the current scope for the
22794 // same type or for a type that is compatible according to the base language
22795 // rules.
22796 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22797 OMPDeclareMapperDecl *PrevDMD = nullptr;
22798 bool InCompoundScope = true;
22799 if (S != nullptr) {
22800 // Find previous declaration with the same name not referenced in other
22801 // declarations.
22803 InCompoundScope =
22804 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22805 LookupName(Lookup, S);
22806 FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22807 /*AllowInlineNamespace=*/false);
22808 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
22809 LookupResult::Filter Filter = Lookup.makeFilter();
22810 while (Filter.hasNext()) {
22811 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
22812 if (InCompoundScope) {
22813 auto I = UsedAsPrevious.find(PrevDecl);
22814 if (I == UsedAsPrevious.end())
22815 UsedAsPrevious[PrevDecl] = false;
22816 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
22817 UsedAsPrevious[D] = true;
22818 }
22819 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22820 PrevDecl->getLocation();
22821 }
22822 Filter.done();
22823 if (InCompoundScope) {
22824 for (const auto &PrevData : UsedAsPrevious) {
22825 if (!PrevData.second) {
22826 PrevDMD = PrevData.first;
22827 break;
22828 }
22829 }
22830 }
22831 } else if (PrevDeclInScope) {
22832 auto *PrevDMDInScope = PrevDMD =
22833 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
22834 do {
22835 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
22836 PrevDMDInScope->getLocation();
22837 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
22838 } while (PrevDMDInScope != nullptr);
22839 }
22840 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
22841 bool Invalid = false;
22842 if (I != PreviousRedeclTypes.end()) {
22843 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
22844 << MapperType << Name;
22845 Diag(I->second, diag::note_previous_definition);
22846 Invalid = true;
22847 }
22848 // Build expressions for implicit maps of data members with 'default'
22849 // mappers.
22850 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses.begin(),
22851 Clauses.end());
22852 if (LangOpts.OpenMP >= 50)
22853 processImplicitMapsWithDefaultMappers(*this, DSAStack, ClausesWithImplicit);
22854 auto *DMD =
22855 OMPDeclareMapperDecl::Create(Context, DC, StartLoc, Name, MapperType, VN,
22856 ClausesWithImplicit, PrevDMD);
22857 if (S)
22858 PushOnScopeChains(DMD, S);
22859 else
22860 DC->addDecl(DMD);
22861 DMD->setAccess(AS);
22862 if (Invalid)
22863 DMD->setInvalidDecl();
22864
22865 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22866 VD->setDeclContext(DMD);
22867 VD->setLexicalDeclContext(DMD);
22868 DMD->addDecl(VD);
22869 DMD->setMapperVarRef(MapperVarRef);
22870
22872}
22873
22876 SourceLocation StartLoc,
22877 DeclarationName VN) {
22878 TypeSourceInfo *TInfo =
22879 Context.getTrivialTypeSourceInfo(MapperType, StartLoc);
22881 StartLoc, StartLoc, VN.getAsIdentifierInfo(),
22882 MapperType, TInfo, SC_None);
22883 if (S)
22884 PushOnScopeChains(VD, S, /*AddToContext=*/false);
22885 Expr *E = buildDeclRefExpr(*this, VD, MapperType, StartLoc);
22886 DSAStack->addDeclareMapperVarRef(E);
22887 return E;
22888}
22889
22891 if (DSAStack->getDeclareMapperVarRef())
22892 DSAStack->addIteratorVarDecl(VD);
22893}
22894
22896 assert(LangOpts.OpenMP && "Expected OpenMP mode.");
22897 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
22898 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
22899 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
22900 return true;
22902 return true;
22903 if (LangOpts.OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
22904 return true;
22905 return false;
22906 }
22907 return true;
22908}
22909
22911 assert(LangOpts.OpenMP && "Expected OpenMP mode.");
22912 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
22913}
22914
22916 SourceLocation StartLoc,
22917 SourceLocation LParenLoc,
22918 SourceLocation EndLoc) {
22919 Expr *ValExpr = NumTeams;
22920 Stmt *HelperValStmt = nullptr;
22921
22922 // OpenMP [teams Constrcut, Restrictions]
22923 // The num_teams expression must evaluate to a positive integer value.
22924 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_teams,
22925 /*StrictlyPositive=*/true))
22926 return nullptr;
22927
22928 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22929 OpenMPDirectiveKind CaptureRegion =
22930 getOpenMPCaptureRegionForClause(DKind, OMPC_num_teams, LangOpts.OpenMP);
22931 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
22932 ValExpr = MakeFullExpr(ValExpr).get();
22933 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22934 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
22935 HelperValStmt = buildPreInits(Context, Captures);
22936 }
22937
22938 return new (Context) OMPNumTeamsClause(ValExpr, HelperValStmt, CaptureRegion,
22939 StartLoc, LParenLoc, EndLoc);
22940}
22941
22943 SourceLocation StartLoc,
22944 SourceLocation LParenLoc,
22945 SourceLocation EndLoc) {
22946 Expr *ValExpr = ThreadLimit;
22947 Stmt *HelperValStmt = nullptr;
22948
22949 // OpenMP [teams Constrcut, Restrictions]
22950 // The thread_limit expression must evaluate to a positive integer value.
22951 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_thread_limit,
22952 /*StrictlyPositive=*/true))
22953 return nullptr;
22954
22955 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22957 DKind, OMPC_thread_limit, LangOpts.OpenMP);
22958 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
22959 ValExpr = MakeFullExpr(ValExpr).get();
22960 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22961 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
22962 HelperValStmt = buildPreInits(Context, Captures);
22963 }
22964
22965 return new (Context) OMPThreadLimitClause(
22966 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22967}
22968
22970 SourceLocation StartLoc,
22971 SourceLocation LParenLoc,
22972 SourceLocation EndLoc) {
22973 Expr *ValExpr = Priority;
22974 Stmt *HelperValStmt = nullptr;
22975 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22976
22977 // OpenMP [2.9.1, task Constrcut]
22978 // The priority-value is a non-negative numerical scalar expression.
22980 ValExpr, *this, OMPC_priority,
22981 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
22982 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22983 return nullptr;
22984
22985 return new (Context) OMPPriorityClause(ValExpr, HelperValStmt, CaptureRegion,
22986 StartLoc, LParenLoc, EndLoc);
22987}
22988
22990 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
22991 SourceLocation StartLoc, SourceLocation LParenLoc,
22992 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22993 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 51) &&
22994 "Unexpected grainsize modifier in OpenMP < 51.");
22995
22996 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
22997 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
22999 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23000 << Values << getOpenMPClauseName(OMPC_grainsize);
23001 return nullptr;
23002 }
23003
23004 Expr *ValExpr = Grainsize;
23005 Stmt *HelperValStmt = nullptr;
23006 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23007
23008 // OpenMP [2.9.2, taskloop Constrcut]
23009 // The parameter of the grainsize clause must be a positive integer
23010 // expression.
23011 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_grainsize,
23012 /*StrictlyPositive=*/true,
23013 /*BuildCapture=*/true,
23014 DSAStack->getCurrentDirective(),
23015 &CaptureRegion, &HelperValStmt))
23016 return nullptr;
23017
23018 return new (Context)
23019 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
23020 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23021}
23022
23024 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
23025 SourceLocation StartLoc, SourceLocation LParenLoc,
23026 SourceLocation ModifierLoc, SourceLocation EndLoc) {
23027 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 51) &&
23028 "Unexpected num_tasks modifier in OpenMP < 51.");
23029
23030 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
23031 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
23033 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23034 << Values << getOpenMPClauseName(OMPC_num_tasks);
23035 return nullptr;
23036 }
23037
23038 Expr *ValExpr = NumTasks;
23039 Stmt *HelperValStmt = nullptr;
23040 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23041
23042 // OpenMP [2.9.2, taskloop Constrcut]
23043 // The parameter of the num_tasks clause must be a positive integer
23044 // expression.
23046 ValExpr, *this, OMPC_num_tasks,
23047 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
23048 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23049 return nullptr;
23050
23051 return new (Context)
23052 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
23053 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23054}
23055
23057 SourceLocation LParenLoc,
23058 SourceLocation EndLoc) {
23059 // OpenMP [2.13.2, critical construct, Description]
23060 // ... where hint-expression is an integer constant expression that evaluates
23061 // to a valid lock hint.
23062 ExprResult HintExpr =
23063 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
23064 if (HintExpr.isInvalid())
23065 return nullptr;
23066 return new (Context)
23067 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
23068}
23069
23070/// Tries to find omp_event_handle_t type.
23072 DSAStackTy *Stack) {
23073 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
23074 if (!OMPEventHandleT.isNull())
23075 return true;
23076 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
23077 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
23078 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23079 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
23080 return false;
23081 }
23082 Stack->setOMPEventHandleT(PT.get());
23083 return true;
23084}
23085
23087 SourceLocation LParenLoc,
23088 SourceLocation EndLoc) {
23089 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
23090 !Evt->isInstantiationDependent() &&
23092 if (!findOMPEventHandleT(*this, Evt->getExprLoc(), DSAStack))
23093 return nullptr;
23094 // OpenMP 5.0, 2.10.1 task Construct.
23095 // event-handle is a variable of the omp_event_handle_t type.
23096 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
23097 if (!Ref) {
23098 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23099 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
23100 return nullptr;
23101 }
23102 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
23103 if (!VD) {
23104 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23105 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
23106 return nullptr;
23107 }
23108 if (!Context.hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
23109 VD->getType()) ||
23110 VD->getType().isConstant(Context)) {
23111 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23112 << "omp_event_handle_t" << 1 << VD->getType()
23113 << Evt->getSourceRange();
23114 return nullptr;
23115 }
23116 // OpenMP 5.0, 2.10.1 task Construct
23117 // [detach clause]... The event-handle will be considered as if it was
23118 // specified on a firstprivate clause.
23119 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
23120 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
23121 DVar.RefExpr) {
23122 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
23123 << getOpenMPClauseName(DVar.CKind)
23124 << getOpenMPClauseName(OMPC_firstprivate);
23125 reportOriginalDsa(*this, DSAStack, VD, DVar);
23126 return nullptr;
23127 }
23128 }
23129
23130 return new (Context) OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
23131}
23132
23134 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
23135 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
23136 SourceLocation EndLoc) {
23137 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
23138 std::string Values;
23139 Values += "'";
23140 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
23141 Values += "'";
23142 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23143 << Values << getOpenMPClauseName(OMPC_dist_schedule);
23144 return nullptr;
23145 }
23146 Expr *ValExpr = ChunkSize;
23147 Stmt *HelperValStmt = nullptr;
23148 if (ChunkSize) {
23149 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
23150 !ChunkSize->isInstantiationDependent() &&
23151 !ChunkSize->containsUnexpandedParameterPack()) {
23152 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
23153 ExprResult Val =
23154 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
23155 if (Val.isInvalid())
23156 return nullptr;
23157
23158 ValExpr = Val.get();
23159
23160 // OpenMP [2.7.1, Restrictions]
23161 // chunk_size must be a loop invariant integer expression with a positive
23162 // value.
23163 if (std::optional<llvm::APSInt> Result =
23164 ValExpr->getIntegerConstantExpr(Context)) {
23165 if (Result->isSigned() && !Result->isStrictlyPositive()) {
23166 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
23167 << "dist_schedule" << ChunkSize->getSourceRange();
23168 return nullptr;
23169 }
23171 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
23172 LangOpts.OpenMP) != OMPD_unknown &&
23174 ValExpr = MakeFullExpr(ValExpr).get();
23175 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23176 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
23177 HelperValStmt = buildPreInits(Context, Captures);
23178 }
23179 }
23180 }
23181
23182 return new (Context)
23183 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
23184 Kind, ValExpr, HelperValStmt);
23185}
23186
23189 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
23190 SourceLocation KindLoc, SourceLocation EndLoc) {
23191 if (getLangOpts().OpenMP < 50) {
23192 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
23193 Kind != OMPC_DEFAULTMAP_scalar) {
23194 std::string Value;
23195 SourceLocation Loc;
23196 Value += "'";
23197 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
23198 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
23199 OMPC_DEFAULTMAP_MODIFIER_tofrom);
23200 Loc = MLoc;
23201 } else {
23202 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
23203 OMPC_DEFAULTMAP_scalar);
23204 Loc = KindLoc;
23205 }
23206 Value += "'";
23207 Diag(Loc, diag::err_omp_unexpected_clause_value)
23208 << Value << getOpenMPClauseName(OMPC_defaultmap);
23209 return nullptr;
23210 }
23211 } else {
23212 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
23213 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
23214 (LangOpts.OpenMP >= 50 && KindLoc.isInvalid());
23215 if (!isDefaultmapKind || !isDefaultmapModifier) {
23216 StringRef KindValue = "'scalar', 'aggregate', 'pointer'";
23217 if (LangOpts.OpenMP == 50) {
23218 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
23219 "'firstprivate', 'none', 'default'";
23220 if (!isDefaultmapKind && isDefaultmapModifier) {
23221 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23222 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23223 } else if (isDefaultmapKind && !isDefaultmapModifier) {
23224 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23225 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23226 } else {
23227 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23228 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23229 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23230 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23231 }
23232 } else {
23233 StringRef ModifierValue =
23234 "'alloc', 'from', 'to', 'tofrom', "
23235 "'firstprivate', 'none', 'default', 'present'";
23236 if (!isDefaultmapKind && isDefaultmapModifier) {
23237 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23238 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23239 } else if (isDefaultmapKind && !isDefaultmapModifier) {
23240 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23241 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23242 } else {
23243 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23244 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23245 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23246 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23247 }
23248 }
23249 return nullptr;
23250 }
23251
23252 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
23253 // At most one defaultmap clause for each category can appear on the
23254 // directive.
23255 if (DSAStack->checkDefaultmapCategory(Kind)) {
23256 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
23257 return nullptr;
23258 }
23259 }
23260 if (Kind == OMPC_DEFAULTMAP_unknown) {
23261 // Variable category is not specified - mark all categories.
23262 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
23263 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
23264 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
23265 } else {
23266 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
23267 }
23268
23269 return new (Context)
23270 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
23271}
23272
23275 DeclContext *CurLexicalContext = getCurLexicalContext();
23276 if (!CurLexicalContext->isFileContext() &&
23277 !CurLexicalContext->isExternCContext() &&
23278 !CurLexicalContext->isExternCXXContext() &&
23279 !isa<CXXRecordDecl>(CurLexicalContext) &&
23280 !isa<ClassTemplateDecl>(CurLexicalContext) &&
23281 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
23282 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
23283 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
23284 return false;
23285 }
23286
23287 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23288 if (getLangOpts().HIP)
23289 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
23290
23291 DeclareTargetNesting.push_back(DTCI);
23292 return true;
23293}
23294
23297 assert(!DeclareTargetNesting.empty() &&
23298 "check isInOpenMPDeclareTargetContext() first!");
23299 return DeclareTargetNesting.pop_back_val();
23300}
23301
23304 for (auto &It : DTCI.ExplicitlyMapped)
23305 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
23306}
23307
23309 if (DeclareTargetNesting.empty())
23310 return;
23311 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23312 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
23313 << getOpenMPDirectiveName(DTCI.Kind);
23314}
23315
23317 CXXScopeSpec &ScopeSpec,
23318 const DeclarationNameInfo &Id) {
23319 LookupResult Lookup(*this, Id, LookupOrdinaryName);
23320 LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
23321
23322 if (Lookup.isAmbiguous())
23323 return nullptr;
23324 Lookup.suppressDiagnostics();
23325
23326 if (!Lookup.isSingleResult()) {
23327 VarOrFuncDeclFilterCCC CCC(*this);
23328 if (TypoCorrection Corrected =
23329 CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, CCC,
23331 diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest)
23332 << Id.getName());
23333 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
23334 return nullptr;
23335 }
23336
23337 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
23338 return nullptr;
23339 }
23340
23341 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
23342 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
23343 !isa<FunctionTemplateDecl>(ND)) {
23344 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
23345 return nullptr;
23346 }
23347 return ND;
23348}
23349
23351 OMPDeclareTargetDeclAttr::MapTypeTy MT,
23353 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
23354 isa<FunctionTemplateDecl>(ND)) &&
23355 "Expected variable, function or function template.");
23356
23357 if (auto *VD = dyn_cast<VarDecl>(ND)) {
23358 // Only global variables can be marked as declare target.
23359 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23360 !VD->isStaticDataMember()) {
23361 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
23362 << VD->getNameAsString();
23363 return;
23364 }
23365 }
23366 // Diagnose marking after use as it may lead to incorrect diagnosis and
23367 // codegen.
23368 if (LangOpts.OpenMP >= 50 &&
23369 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
23370 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
23371
23372 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23373 if (getLangOpts().HIP)
23374 Diag(Loc, diag::warn_hip_omp_target_directives);
23375
23376 // Explicit declare target lists have precedence.
23377 const unsigned Level = -1;
23378
23379 auto *VD = cast<ValueDecl>(ND);
23380 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23381 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23382 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
23383 (*ActiveAttr)->getLevel() == Level) {
23384 Diag(Loc, diag::err_omp_device_type_mismatch)
23385 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
23386 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
23387 (*ActiveAttr)->getDevType());
23388 return;
23389 }
23390 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
23391 (*ActiveAttr)->getLevel() == Level) {
23392 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
23393 return;
23394 }
23395
23396 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
23397 return;
23398
23399 Expr *IndirectE = nullptr;
23400 bool IsIndirect = false;
23401 if (DTCI.Indirect) {
23402 IndirectE = *DTCI.Indirect;
23403 if (!IndirectE)
23404 IsIndirect = true;
23405 }
23406 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23407 Context, MT, DTCI.DT, IndirectE, IsIndirect, Level,
23408 SourceRange(Loc, Loc));
23409 ND->addAttr(A);
23411 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
23412 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
23413 if (auto *VD = dyn_cast<VarDecl>(ND);
23414 LangOpts.OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
23415 VD->hasGlobalStorage())
23417}
23418
23420 Sema &SemaRef, Decl *D) {
23421 if (!D || !isa<VarDecl>(D))
23422 return;
23423 auto *VD = cast<VarDecl>(D);
23424 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
23425 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
23426 if (SemaRef.LangOpts.OpenMP >= 50 &&
23427 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
23428 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
23429 VD->hasGlobalStorage()) {
23430 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
23431 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
23432 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
23433 // If a lambda declaration and definition appears between a
23434 // declare target directive and the matching end declare target
23435 // directive, all variables that are captured by the lambda
23436 // expression must also appear in a to clause.
23437 SemaRef.Diag(VD->getLocation(),
23438 diag::err_omp_lambda_capture_in_declare_target_not_to);
23439 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
23440 << VD << 0 << SR;
23441 return;
23442 }
23443 }
23444 if (MapTy)
23445 return;
23446 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
23447 SemaRef.Diag(SL, diag::note_used_here) << SR;
23448}
23449
23451 Sema &SemaRef, DSAStackTy *Stack,
23452 ValueDecl *VD) {
23453 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
23454 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
23455 /*FullCheck=*/false);
23456}
23457
23459 SourceLocation IdLoc) {
23460 if (!D || D->isInvalidDecl())
23461 return;
23462 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
23463 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
23464 if (auto *VD = dyn_cast<VarDecl>(D)) {
23465 // Only global variables can be marked as declare target.
23466 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23467 !VD->isStaticDataMember())
23468 return;
23469 // 2.10.6: threadprivate variable cannot appear in a declare target
23470 // directive.
23471 if (DSAStack->isThreadPrivate(VD)) {
23472 Diag(SL, diag::err_omp_threadprivate_in_target);
23473 reportOriginalDsa(*this, DSAStack, VD, DSAStack->getTopDSA(VD, false));
23474 return;
23475 }
23476 }
23477 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
23478 D = FTD->getTemplatedDecl();
23479 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
23480 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
23481 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
23482 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
23483 Diag(IdLoc, diag::err_omp_function_in_link_clause);
23484 Diag(FD->getLocation(), diag::note_defined_here) << FD;
23485 return;
23486 }
23487 }
23488 if (auto *VD = dyn_cast<ValueDecl>(D)) {
23489 // Problem if any with var declared with incomplete type will be reported
23490 // as normal, so no need to check it here.
23491 if ((E || !VD->getType()->isIncompleteType()) &&
23492 !checkValueDeclInTarget(SL, SR, *this, DSAStack, VD))
23493 return;
23494 if (!E && isInOpenMPDeclareTargetContext()) {
23495 // Checking declaration inside declare target region.
23496 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
23497 isa<FunctionTemplateDecl>(D)) {
23498 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23499 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23500 unsigned Level = DeclareTargetNesting.size();
23501 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
23502 return;
23503 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23504 Expr *IndirectE = nullptr;
23505 bool IsIndirect = false;
23506 if (DTCI.Indirect) {
23507 IndirectE = *DTCI.Indirect;
23508 if (!IndirectE)
23509 IsIndirect = true;
23510 }
23511 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23512 Context,
23513 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
23514 : OMPDeclareTargetDeclAttr::MT_To,
23515 DTCI.DT, IndirectE, IsIndirect, Level,
23516 SourceRange(DTCI.Loc, DTCI.Loc));
23517 D->addAttr(A);
23519 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
23520 }
23521 return;
23522 }
23523 }
23524 if (!E)
23525 return;
23527}
23528
23529/// This class visits every VarDecl that the initializer references and adds
23530/// OMPDeclareTargetDeclAttr to each of them.
23532 : public StmtVisitor<GlobalDeclRefChecker> {
23533 SmallVector<VarDecl *> DeclVector;
23534 Attr *A;
23535
23536public:
23537 /// A StmtVisitor class function that visits all DeclRefExpr and adds
23538 /// OMPDeclareTargetDeclAttr to them.
23540 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
23541 VD->addAttr(A);
23542 DeclVector.push_back(VD);
23543 }
23544 }
23545 /// A function that iterates across each of the Expr's children.
23546 void VisitExpr(Expr *Ex) {
23547 for (auto *Child : Ex->children()) {
23548 Visit(Child);
23549 }
23550 }
23551 /// A function that keeps a record of all the Decls that are variables, has
23552 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
23553 /// each Decl one at a time and use the inherited 'visit' functions to look
23554 /// for DeclRefExpr.
23556 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
23557 DeclVector.push_back(cast<VarDecl>(TD));
23558 while (!DeclVector.empty()) {
23559 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
23560 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
23561 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
23562 if (Expr *Ex = TargetVarDecl->getInit())
23563 Visit(Ex);
23564 }
23565 }
23566 }
23567};
23568
23569/// Adding OMPDeclareTargetDeclAttr to variables with static storage
23570/// duration that are referenced in the initializer expression list of
23571/// variables with static storage duration in declare target directive.
23573 GlobalDeclRefChecker Checker;
23574 if (isa<VarDecl>(TargetDecl))
23575 Checker.declareTargetInitializer(TargetDecl);
23576}
23577
23579 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23580 ArrayRef<SourceLocation> MotionModifiersLoc,
23581 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23582 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23583 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23587
23588 // Process motion-modifiers, flag errors for duplicate modifiers.
23589 unsigned Count = 0;
23590 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23591 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23592 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23593 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23594 continue;
23595 }
23596 assert(Count < NumberOfOMPMotionModifiers &&
23597 "Modifiers exceed the allowed number of motion modifiers");
23598 Modifiers[Count] = MotionModifiers[I];
23599 ModifiersLoc[Count] = MotionModifiersLoc[I];
23600 ++Count;
23601 }
23602
23603 MappableVarListInfo MVLI(VarList);
23604 checkMappableExpressionList(*this, DSAStack, OMPC_to, MVLI, Locs.StartLoc,
23605 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23606 if (MVLI.ProcessedVarList.empty())
23607 return nullptr;
23608
23609 return OMPToClause::Create(
23610 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23611 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23612 MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
23613}
23614
23616 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23617 ArrayRef<SourceLocation> MotionModifiersLoc,
23618 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23619 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23620 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23624
23625 // Process motion-modifiers, flag errors for duplicate modifiers.
23626 unsigned Count = 0;
23627 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23628 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23629 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23630 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23631 continue;
23632 }
23633 assert(Count < NumberOfOMPMotionModifiers &&
23634 "Modifiers exceed the allowed number of motion modifiers");
23635 Modifiers[Count] = MotionModifiers[I];
23636 ModifiersLoc[Count] = MotionModifiersLoc[I];
23637 ++Count;
23638 }
23639
23640 MappableVarListInfo MVLI(VarList);
23641 checkMappableExpressionList(*this, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
23642 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23643 if (MVLI.ProcessedVarList.empty())
23644 return nullptr;
23645
23646 return OMPFromClause::Create(
23647 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23648 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23649 MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
23650}
23651
23653 const OMPVarListLocTy &Locs) {
23654 MappableVarListInfo MVLI(VarList);
23655 SmallVector<Expr *, 8> PrivateCopies;
23657
23658 for (Expr *RefExpr : VarList) {
23659 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
23660 SourceLocation ELoc;
23661 SourceRange ERange;
23662 Expr *SimpleRefExpr = RefExpr;
23663 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23664 if (Res.second) {
23665 // It will be analyzed later.
23666 MVLI.ProcessedVarList.push_back(RefExpr);
23667 PrivateCopies.push_back(nullptr);
23668 Inits.push_back(nullptr);
23669 }
23670 ValueDecl *D = Res.first;
23671 if (!D)
23672 continue;
23673
23674 QualType Type = D->getType();
23675 Type = Type.getNonReferenceType().getUnqualifiedType();
23676
23677 auto *VD = dyn_cast<VarDecl>(D);
23678
23679 // Item should be a pointer or reference to pointer.
23680 if (!Type->isPointerType()) {
23681 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
23682 << 0 << RefExpr->getSourceRange();
23683 continue;
23684 }
23685
23686 // Build the private variable and the expression that refers to it.
23687 auto VDPrivate =
23688 buildVarDecl(*this, ELoc, Type, D->getName(),
23689 D->hasAttrs() ? &D->getAttrs() : nullptr,
23690 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
23691 if (VDPrivate->isInvalidDecl())
23692 continue;
23693
23694 CurContext->addDecl(VDPrivate);
23695 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
23696 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
23697
23698 // Add temporary variable to initialize the private copy of the pointer.
23699 VarDecl *VDInit =
23700 buildVarDecl(*this, RefExpr->getExprLoc(), Type, ".devptr.temp");
23701 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
23702 *this, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
23703 AddInitializerToDecl(VDPrivate,
23704 DefaultLvalueConversion(VDInitRefExpr).get(),
23705 /*DirectInit=*/false);
23706
23707 // If required, build a capture to implement the privatization initialized
23708 // with the current list item value.
23709 DeclRefExpr *Ref = nullptr;
23710 if (!VD)
23711 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
23712 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23713 PrivateCopies.push_back(VDPrivateRefExpr);
23714 Inits.push_back(VDInitRefExpr);
23715
23716 // We need to add a data sharing attribute for this variable to make sure it
23717 // is correctly captured. A variable that shows up in a use_device_ptr has
23718 // similar properties of a first private variable.
23719 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23720
23721 // Create a mappable component for the list item. List items in this clause
23722 // only need a component.
23723 MVLI.VarBaseDeclarations.push_back(D);
23724 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23725 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
23726 /*IsNonContiguous=*/false);
23727 }
23728
23729 if (MVLI.ProcessedVarList.empty())
23730 return nullptr;
23731
23733 Context, Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
23734 MVLI.VarBaseDeclarations, MVLI.VarComponents);
23735}
23736
23738 const OMPVarListLocTy &Locs) {
23739 MappableVarListInfo MVLI(VarList);
23740
23741 for (Expr *RefExpr : VarList) {
23742 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
23743 SourceLocation ELoc;
23744 SourceRange ERange;
23745 Expr *SimpleRefExpr = RefExpr;
23746 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23747 /*AllowArraySection=*/true);
23748 if (Res.second) {
23749 // It will be analyzed later.
23750 MVLI.ProcessedVarList.push_back(RefExpr);
23751 }
23752 ValueDecl *D = Res.first;
23753 if (!D)
23754 continue;
23755 auto *VD = dyn_cast<VarDecl>(D);
23756
23757 // If required, build a capture to implement the privatization initialized
23758 // with the current list item value.
23759 DeclRefExpr *Ref = nullptr;
23760 if (!VD)
23761 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
23762 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23763
23764 // We need to add a data sharing attribute for this variable to make sure it
23765 // is correctly captured. A variable that shows up in a use_device_addr has
23766 // similar properties of a first private variable.
23767 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23768
23769 // Create a mappable component for the list item. List items in this clause
23770 // only need a component.
23771 MVLI.VarBaseDeclarations.push_back(D);
23772 MVLI.VarComponents.emplace_back();
23773 Expr *Component = SimpleRefExpr;
23774 if (VD && (isa<OMPArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23775 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23776 Component = DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
23777 MVLI.VarComponents.back().emplace_back(Component, D,
23778 /*IsNonContiguous=*/false);
23779 }
23780
23781 if (MVLI.ProcessedVarList.empty())
23782 return nullptr;
23783
23784 return OMPUseDeviceAddrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23785 MVLI.VarBaseDeclarations,
23786 MVLI.VarComponents);
23787}
23788
23790 const OMPVarListLocTy &Locs) {
23791 MappableVarListInfo MVLI(VarList);
23792 for (Expr *RefExpr : VarList) {
23793 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
23794 SourceLocation ELoc;
23795 SourceRange ERange;
23796 Expr *SimpleRefExpr = RefExpr;
23797 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23798 if (Res.second) {
23799 // It will be analyzed later.
23800 MVLI.ProcessedVarList.push_back(RefExpr);
23801 }
23802 ValueDecl *D = Res.first;
23803 if (!D)
23804 continue;
23805
23806 QualType Type = D->getType();
23807 // item should be a pointer or array or reference to pointer or array
23808 if (!Type.getNonReferenceType()->isPointerType() &&
23809 !Type.getNonReferenceType()->isArrayType()) {
23810 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
23811 << 0 << RefExpr->getSourceRange();
23812 continue;
23813 }
23814
23815 // Check if the declaration in the clause does not show up in any data
23816 // sharing attribute.
23817 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23818 if (isOpenMPPrivate(DVar.CKind)) {
23819 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23820 << getOpenMPClauseName(DVar.CKind)
23821 << getOpenMPClauseName(OMPC_is_device_ptr)
23822 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
23823 reportOriginalDsa(*this, DSAStack, D, DVar);
23824 continue;
23825 }
23826
23827 const Expr *ConflictExpr;
23828 if (DSAStack->checkMappableExprComponentListsForDecl(
23829 D, /*CurrentRegionOnly=*/true,
23830 [&ConflictExpr](
23832 OpenMPClauseKind) -> bool {
23833 ConflictExpr = R.front().getAssociatedExpression();
23834 return true;
23835 })) {
23836 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23837 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23838 << ConflictExpr->getSourceRange();
23839 continue;
23840 }
23841
23842 // Store the components in the stack so that they can be used to check
23843 // against other clauses later on.
23845 SimpleRefExpr, D, /*IsNonContiguous=*/false);
23846 DSAStack->addMappableExpressionComponents(
23847 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
23848
23849 // Record the expression we've just processed.
23850 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
23851
23852 // Create a mappable component for the list item. List items in this clause
23853 // only need a component. We use a null declaration to signal fields in
23854 // 'this'.
23855 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23856 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23857 "Unexpected device pointer expression!");
23858 MVLI.VarBaseDeclarations.push_back(
23859 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23860 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23861 MVLI.VarComponents.back().push_back(MC);
23862 }
23863
23864 if (MVLI.ProcessedVarList.empty())
23865 return nullptr;
23866
23867 return OMPIsDevicePtrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23868 MVLI.VarBaseDeclarations,
23869 MVLI.VarComponents);
23870}
23871
23873 const OMPVarListLocTy &Locs) {
23874 MappableVarListInfo MVLI(VarList);
23875 for (Expr *RefExpr : VarList) {
23876 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
23877 SourceLocation ELoc;
23878 SourceRange ERange;
23879 Expr *SimpleRefExpr = RefExpr;
23880 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23881 /*AllowArraySection=*/true);
23882 if (Res.second) {
23883 // It will be analyzed later.
23884 MVLI.ProcessedVarList.push_back(RefExpr);
23885 }
23886 ValueDecl *D = Res.first;
23887 if (!D)
23888 continue;
23889
23890 // Check if the declaration in the clause does not show up in any data
23891 // sharing attribute.
23892 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23893 if (isOpenMPPrivate(DVar.CKind)) {
23894 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23895 << getOpenMPClauseName(DVar.CKind)
23896 << getOpenMPClauseName(OMPC_has_device_addr)
23897 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
23898 reportOriginalDsa(*this, DSAStack, D, DVar);
23899 continue;
23900 }
23901
23902 const Expr *ConflictExpr;
23903 if (DSAStack->checkMappableExprComponentListsForDecl(
23904 D, /*CurrentRegionOnly=*/true,
23905 [&ConflictExpr](
23907 OpenMPClauseKind) -> bool {
23908 ConflictExpr = R.front().getAssociatedExpression();
23909 return true;
23910 })) {
23911 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23912 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23913 << ConflictExpr->getSourceRange();
23914 continue;
23915 }
23916
23917 // Store the components in the stack so that they can be used to check
23918 // against other clauses later on.
23919 Expr *Component = SimpleRefExpr;
23920 auto *VD = dyn_cast<VarDecl>(D);
23921 if (VD && (isa<OMPArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23922 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23923 Component = DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
23925 Component, D, /*IsNonContiguous=*/false);
23926 DSAStack->addMappableExpressionComponents(
23927 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
23928
23929 // Record the expression we've just processed.
23930 if (!VD && !CurContext->isDependentContext()) {
23931 DeclRefExpr *Ref =
23932 buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
23933 assert(Ref && "has_device_addr capture failed");
23934 MVLI.ProcessedVarList.push_back(Ref);
23935 } else
23936 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
23937
23938 // Create a mappable component for the list item. List items in this clause
23939 // only need a component. We use a null declaration to signal fields in
23940 // 'this'.
23941 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23942 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23943 "Unexpected device pointer expression!");
23944 MVLI.VarBaseDeclarations.push_back(
23945 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23946 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23947 MVLI.VarComponents.back().push_back(MC);
23948 }
23949
23950 if (MVLI.ProcessedVarList.empty())
23951 return nullptr;
23952
23953 return OMPHasDeviceAddrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23954 MVLI.VarBaseDeclarations,
23955 MVLI.VarComponents);
23956}
23957
23959 Expr *Allocator, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
23960 SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
23961 if (Allocator) {
23962 // OpenMP [2.11.4 allocate Clause, Description]
23963 // allocator is an expression of omp_allocator_handle_t type.
23964 if (!findOMPAllocatorHandleT(*this, Allocator->getExprLoc(), DSAStack))
23965 return nullptr;
23966
23967 ExprResult AllocatorRes = DefaultLvalueConversion(Allocator);
23968 if (AllocatorRes.isInvalid())
23969 return nullptr;
23970 AllocatorRes = PerformImplicitConversion(AllocatorRes.get(),
23971 DSAStack->getOMPAllocatorHandleT(),
23973 /*AllowExplicit=*/true);
23974 if (AllocatorRes.isInvalid())
23975 return nullptr;
23976 Allocator = AllocatorRes.get();
23977 } else {
23978 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
23979 // allocate clauses that appear on a target construct or on constructs in a
23980 // target region must specify an allocator expression unless a requires
23981 // directive with the dynamic_allocators clause is present in the same
23982 // compilation unit.
23983 if (LangOpts.OpenMPIsTargetDevice &&
23984 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
23985 targetDiag(StartLoc, diag::err_expected_allocator_expression);
23986 }
23987 // Analyze and build list of variables.
23989 for (Expr *RefExpr : VarList) {
23990 assert(RefExpr && "NULL expr in OpenMP private clause.");
23991 SourceLocation ELoc;
23992 SourceRange ERange;
23993 Expr *SimpleRefExpr = RefExpr;
23994 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23995 if (Res.second) {
23996 // It will be analyzed later.
23997 Vars.push_back(RefExpr);
23998 }
23999 ValueDecl *D = Res.first;
24000 if (!D)
24001 continue;
24002
24003 auto *VD = dyn_cast<VarDecl>(D);
24004 DeclRefExpr *Ref = nullptr;
24005 if (!VD && !CurContext->isDependentContext())
24006 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
24007 Vars.push_back((VD || CurContext->isDependentContext())
24008 ? RefExpr->IgnoreParens()
24009 : Ref);
24010 }
24011
24012 if (Vars.empty())
24013 return nullptr;
24014
24015 if (Allocator)
24016 DSAStack->addInnerAllocatorExpr(Allocator);
24017 return OMPAllocateClause::Create(Context, StartLoc, LParenLoc, Allocator,
24018 ColonLoc, EndLoc, Vars);
24019}
24020
24022 SourceLocation StartLoc,
24023 SourceLocation LParenLoc,
24024 SourceLocation EndLoc) {
24026 for (Expr *RefExpr : VarList) {
24027 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
24028 SourceLocation ELoc;
24029 SourceRange ERange;
24030 Expr *SimpleRefExpr = RefExpr;
24031 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
24032 if (Res.second)
24033 // It will be analyzed later.
24034 Vars.push_back(RefExpr);
24035 ValueDecl *D = Res.first;
24036 if (!D)
24037 continue;
24038
24039 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
24040 // A list-item cannot appear in more than one nontemporal clause.
24041 if (const Expr *PrevRef =
24042 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
24043 Diag(ELoc, diag::err_omp_used_in_clause_twice)
24044 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
24045 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
24046 << getOpenMPClauseName(OMPC_nontemporal);
24047 continue;
24048 }
24049
24050 Vars.push_back(RefExpr);
24051 }
24052
24053 if (Vars.empty())
24054 return nullptr;
24055
24056 return OMPNontemporalClause::Create(Context, StartLoc, LParenLoc, EndLoc,
24057 Vars);
24058}
24059
24061 Stmt *AStmt, SourceLocation StartLoc,
24062 SourceLocation EndLoc) {
24063 if (!AStmt)
24064 return StmtError();
24065
24067
24068 return OMPScopeDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
24069}
24070
24072 SourceLocation StartLoc,
24073 SourceLocation LParenLoc,
24074 SourceLocation EndLoc) {
24076 for (Expr *RefExpr : VarList) {
24077 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
24078 SourceLocation ELoc;
24079 SourceRange ERange;
24080 Expr *SimpleRefExpr = RefExpr;
24081 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
24082 /*AllowArraySection=*/true);
24083 if (Res.second)
24084 // It will be analyzed later.
24085 Vars.push_back(RefExpr);
24086 ValueDecl *D = Res.first;
24087 if (!D)
24088 continue;
24089
24090 const DSAStackTy::DSAVarData DVar =
24091 DSAStack->getTopDSA(D, /*FromParent=*/true);
24092 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
24093 // A list item that appears in the inclusive or exclusive clause must appear
24094 // in a reduction clause with the inscan modifier on the enclosing
24095 // worksharing-loop, worksharing-loop SIMD, or simd construct.
24096 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
24097 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
24098 << RefExpr->getSourceRange();
24099
24100 if (DSAStack->getParentDirective() != OMPD_unknown)
24101 DSAStack->markDeclAsUsedInScanDirective(D);
24102 Vars.push_back(RefExpr);
24103 }
24104
24105 if (Vars.empty())
24106 return nullptr;
24107
24108 return OMPInclusiveClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
24109}
24110
24112 SourceLocation StartLoc,
24113 SourceLocation LParenLoc,
24114 SourceLocation EndLoc) {
24116 for (Expr *RefExpr : VarList) {
24117 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
24118 SourceLocation ELoc;
24119 SourceRange ERange;
24120 Expr *SimpleRefExpr = RefExpr;
24121 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
24122 /*AllowArraySection=*/true);
24123 if (Res.second)
24124 // It will be analyzed later.
24125 Vars.push_back(RefExpr);
24126 ValueDecl *D = Res.first;
24127 if (!D)
24128 continue;
24129
24130 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
24131 DSAStackTy::DSAVarData DVar;
24132 if (ParentDirective != OMPD_unknown)
24133 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
24134 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
24135 // A list item that appears in the inclusive or exclusive clause must appear
24136 // in a reduction clause with the inscan modifier on the enclosing
24137 // worksharing-loop, worksharing-loop SIMD, or simd construct.
24138 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
24139 DVar.Modifier != OMPC_REDUCTION_inscan) {
24140 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
24141 << RefExpr->getSourceRange();
24142 } else {
24143 DSAStack->markDeclAsUsedInScanDirective(D);
24144 }
24145 Vars.push_back(RefExpr);
24146 }
24147
24148 if (Vars.empty())
24149 return nullptr;
24150
24151 return OMPExclusiveClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
24152}
24153
24154/// Tries to find omp_alloctrait_t type.
24155static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
24156 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
24157 if (!OMPAlloctraitT.isNull())
24158 return true;
24159 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
24160 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
24161 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
24162 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
24163 return false;
24164 }
24165 Stack->setOMPAlloctraitT(PT.get());
24166 return true;
24167}
24168
24170 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
24172 // OpenMP [2.12.5, target Construct]
24173 // allocator is an identifier of omp_allocator_handle_t type.
24174 if (!findOMPAllocatorHandleT(*this, StartLoc, DSAStack))
24175 return nullptr;
24176 // OpenMP [2.12.5, target Construct]
24177 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
24178 if (llvm::any_of(
24179 Data,
24180 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
24181 !findOMPAlloctraitT(*this, StartLoc, DSAStack))
24182 return nullptr;
24183 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
24184 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
24185 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
24186 StringRef Allocator =
24187 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
24188 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
24189 PredefinedAllocators.insert(LookupSingleName(
24190 TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
24191 }
24192
24194 for (const UsesAllocatorsData &D : Data) {
24195 Expr *AllocatorExpr = nullptr;
24196 // Check allocator expression.
24197 if (D.Allocator->isTypeDependent()) {
24198 AllocatorExpr = D.Allocator;
24199 } else {
24200 // Traits were specified - need to assign new allocator to the specified
24201 // allocator, so it must be an lvalue.
24202 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
24203 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
24204 bool IsPredefinedAllocator = false;
24205 if (DRE) {
24206 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
24207 getAllocatorKind(*this, DSAStack, AllocatorExpr);
24208 IsPredefinedAllocator =
24209 AllocatorTy !=
24210 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
24211 }
24212 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
24213 QualType AllocatorExprType = AllocatorExpr->getType();
24214 bool IsTypeCompatible = IsPredefinedAllocator;
24215 IsTypeCompatible = IsTypeCompatible ||
24216 Context.hasSameUnqualifiedType(AllocatorExprType,
24217 OMPAllocatorHandleT);
24218 IsTypeCompatible =
24219 IsTypeCompatible ||
24220 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
24221 bool IsNonConstantLValue =
24222 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
24223 if (!DRE || !IsTypeCompatible ||
24224 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
24225 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
24226 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
24227 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
24228 continue;
24229 }
24230 // OpenMP [2.12.5, target Construct]
24231 // Predefined allocators appearing in a uses_allocators clause cannot have
24232 // traits specified.
24233 if (IsPredefinedAllocator && D.AllocatorTraits) {
24235 diag::err_omp_predefined_allocator_with_traits)
24237 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
24238 << cast<NamedDecl>(DRE->getDecl())->getName()
24239 << D.Allocator->getSourceRange();
24240 continue;
24241 }
24242 // OpenMP [2.12.5, target Construct]
24243 // Non-predefined allocators appearing in a uses_allocators clause must
24244 // have traits specified.
24245 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
24247 diag::err_omp_nonpredefined_allocator_without_traits);
24248 continue;
24249 }
24250 // No allocator traits - just convert it to rvalue.
24251 if (!D.AllocatorTraits)
24252 AllocatorExpr = DefaultLvalueConversion(AllocatorExpr).get();
24253 DSAStack->addUsesAllocatorsDecl(
24254 DRE->getDecl(),
24255 IsPredefinedAllocator
24256 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
24257 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
24258 }
24259 Expr *AllocatorTraitsExpr = nullptr;
24260 if (D.AllocatorTraits) {
24262 AllocatorTraitsExpr = D.AllocatorTraits;
24263 } else {
24264 // OpenMP [2.12.5, target Construct]
24265 // Arrays that contain allocator traits that appear in a uses_allocators
24266 // clause must be constant arrays, have constant values and be defined
24267 // in the same scope as the construct in which the clause appears.
24268 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
24269 // Check that traits expr is a constant array.
24270 QualType TraitTy;
24271 if (const ArrayType *Ty =
24272 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
24273 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
24274 TraitTy = ConstArrayTy->getElementType();
24275 if (TraitTy.isNull() ||
24277 DSAStack->getOMPAlloctraitT()) ||
24278 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
24279 /*CompareUnqualified=*/true))) {
24281 diag::err_omp_expected_array_alloctraits)
24282 << AllocatorTraitsExpr->getType();
24283 continue;
24284 }
24285 // Do not map by default allocator traits if it is a standalone
24286 // variable.
24287 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
24288 DSAStack->addUsesAllocatorsDecl(
24289 DRE->getDecl(),
24290 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
24291 }
24292 }
24293 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
24294 NewD.Allocator = AllocatorExpr;
24295 NewD.AllocatorTraits = AllocatorTraitsExpr;
24296 NewD.LParenLoc = D.LParenLoc;
24297 NewD.RParenLoc = D.RParenLoc;
24298 }
24299 return OMPUsesAllocatorsClause::Create(Context, StartLoc, LParenLoc, EndLoc,
24300 NewData);
24301}
24302
24304 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
24305 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
24307 for (Expr *RefExpr : Locators) {
24308 assert(RefExpr && "NULL expr in OpenMP shared clause.");
24309 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
24310 // It will be analyzed later.
24311 Vars.push_back(RefExpr);
24312 continue;
24313 }
24314
24315 SourceLocation ELoc = RefExpr->getExprLoc();
24316 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
24317
24318 if (!SimpleExpr->isLValue()) {
24319 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24320 << 1 << 0 << RefExpr->getSourceRange();
24321 continue;
24322 }
24323
24324 ExprResult Res;
24325 {
24326 Sema::TentativeAnalysisScope Trap(*this);
24327 Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
24328 }
24329 if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr) &&
24330 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
24331 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24332 << 1 << 0 << RefExpr->getSourceRange();
24333 continue;
24334 }
24335 Vars.push_back(SimpleExpr);
24336 }
24337
24338 return OMPAffinityClause::Create(Context, StartLoc, LParenLoc, ColonLoc,
24339 EndLoc, Modifier, Vars);
24340}
24341
24343 SourceLocation KindLoc,
24344 SourceLocation StartLoc,
24345 SourceLocation LParenLoc,
24346 SourceLocation EndLoc) {
24347 if (Kind == OMPC_BIND_unknown) {
24348 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24349 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
24350 /*Last=*/unsigned(OMPC_BIND_unknown))
24351 << getOpenMPClauseName(OMPC_bind);
24352 return nullptr;
24353 }
24354
24355 return OMPBindClause::Create(Context, Kind, KindLoc, StartLoc, LParenLoc,
24356 EndLoc);
24357}
24358
24360 SourceLocation StartLoc,
24361 SourceLocation LParenLoc,
24362 SourceLocation EndLoc) {
24363 Expr *ValExpr = Size;
24364 Stmt *HelperValStmt = nullptr;
24365
24366 // OpenMP [2.5, Restrictions]
24367 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
24368 // value.
24369 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_ompx_dyn_cgroup_mem,
24370 /*StrictlyPositive=*/false))
24371 return nullptr;
24372
24373 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24375 DKind, OMPC_ompx_dyn_cgroup_mem, LangOpts.OpenMP);
24376 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
24377 ValExpr = MakeFullExpr(ValExpr).get();
24378 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24379 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
24380 HelperValStmt = buildPreInits(Context, Captures);
24381 }
24382
24383 return new (Context) OMPXDynCGroupMemClause(
24384 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
24385}
24386
24389 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
24390 SourceLocation LParenLoc, SourceLocation EndLoc) {
24391
24392 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
24393 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
24394 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
24395 DepType != OMPC_DOACROSS_source_omp_cur_iteration &&
24396 DepType != OMPC_DOACROSS_source) {
24397 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
24398 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross);
24399 return nullptr;
24400 }
24401
24404 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
24405 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
24406 *this,
24407 DepType == OMPC_DOACROSS_source ||
24408 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
24409 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
24410 VarList, DSAStack, EndLoc);
24411 Vars = VarOffset.Vars;
24412 OpsOffs = VarOffset.OpsOffs;
24413 TotalDepCount = VarOffset.TotalDepCount;
24414 auto *C = OMPDoacrossClause::Create(Context, StartLoc, LParenLoc, EndLoc,
24415 DepType, DepLoc, ColonLoc, Vars,
24416 TotalDepCount.getZExtValue());
24417 if (DSAStack->isParentOrderedRegion())
24418 DSAStack->addDoacrossDependClause(C, OpsOffs);
24419 return C;
24420}
24421
24423 SourceLocation StartLoc,
24424 SourceLocation LParenLoc,
24425 SourceLocation EndLoc) {
24426 return new (Context) OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
24427}
24428
24430 SourceLocation EndLoc) {
24431 return new (Context) OMPXBareClause(StartLoc, EndLoc);
24432}
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3259
NodeId Parent
Definition: ASTDiff.cpp:191
int Id
Definition: ASTDiff.cpp:190
DynTypedNode Node
StringRef P
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
This file defines OpenMP nodes for declarative directives.
int Priority
Definition: Format.cpp:2956
llvm::DenseSet< const void * > Visited
Definition: HTMLLogger.cpp:146
unsigned Iter
Definition: HTMLLogger.cpp:154
static const Decl * getCanonicalDecl(const Decl *D)
#define X(type, name)
Definition: Value.h:142
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
llvm::DenseMap< Stmt *, Stmt * > MapTy
Definition: ParentMap.cpp:22
Implements a partial diagnostic that can be emitted anwyhere in a DiagnosticBuilder stream.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
CastType
Definition: SemaCast.cpp:47
static VarDecl * buildVarDecl(Sema &S, SourceLocation Loc, QualType Type, IdentifierInfo *II)
Build a variable declaration for move parameter.
static NamedDecl * findAcceptableDecl(Sema &SemaRef, NamedDecl *D, unsigned IDNS)
Retrieve the visible declaration corresponding to D, if any.
static Expr * getOrderedNumberExpr(ArrayRef< OMPClause * > Clauses)
static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack, bool Diagnose=true)
Tries to find omp_depend_t. type.
static Stmt * buildPreInits(ASTContext &Context, MutableArrayRef< Decl * > PreInits)
Build preinits statement for the given declarations.
static void argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id, SourceLocation Loc, QualType Ty, SmallVectorImpl< UnresolvedSet< 8 > > &Lookups)
static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR, Sema &SemaRef, Decl *D)
static bool checkGenericLoopLastprivate(Sema &S, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind K, DSAStackTy *Stack)
static bool checkSimdlenSafelenSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto, QualType NewType)
static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPDirectiveKind > AllowedNameModifiers)
static void handleDeclareVariantConstructTrait(DSAStackTy *Stack, OpenMPDirectiveKind DKind, bool ScopeEntry)
static VarDecl * precomputeExpr(Sema &Actions, SmallVectorImpl< Stmt * > &BodyStmts, Expr *E, StringRef Name)
static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type, Expr *UnresolvedMapper)
static bool checkReductionClauseWithNogroup(Sema &S, ArrayRef< OMPClause * > Clauses)
static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, SourceLocation M1Loc, SourceLocation M2Loc)
static OMPAllocateDeclAttr::AllocatorTypeTy getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator)
static bool isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind, bool StrictlyPositive, bool BuildCapture=false, OpenMPDirectiveKind DKind=OMPD_unknown, OpenMPDirectiveKind *CaptureRegion=nullptr, Stmt **HelperValStmt=nullptr)
static Expr * buildPostUpdate(Sema &S, ArrayRef< Expr * > PostUpdates)
Build postupdate expression for the given list of postupdates expressions.
static CapturedStmt * buildLoopVarFunc(Sema &Actions, QualType LoopVarTy, QualType LogicalTy, DeclRefExpr *StartExpr, Expr *Step, bool Deref)
Create a closure that computes the loop variable from the logical iteration number.
static ExprResult 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)
Build 'VarRef = Start + Iter * Step'.
static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion, OpenMPDirectiveKind NameModifier=OMPD_unknown)
static Expr * getCollapseNumberExpr(ArrayRef< OMPClause * > Clauses)
static Expr * getDirectCallExpr(Expr *E)
static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
static OMPCapturedExprDecl * buildCaptureDecl(Sema &S, IdentifierInfo *Id, Expr *CaptureExpr, bool WithInit, DeclContext *CurContext, bool AsExpression)
static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_allocator_handle_t type.
static bool isClauseMappable(ArrayRef< OMPClause * > Clauses)
Check if the variables in the mapping clause are externally visible.
static BinaryOperatorKind getRelatedCompoundReductionOp(BinaryOperatorKind BOK)
static bool checkMutuallyExclusiveClauses(Sema &S, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPClauseKind > MutuallyExclusiveClauses)
Find and diagnose mutually exclusive clause kinds.
static bool 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)
Called on a for stmt to check and extract its iteration space for further processing (such as collaps...
static bool checkOrderedOrderSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static OpenMPMapClauseKind getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M, bool IsAggregateOrDeclareTarget)
static const Expr * getExprAsWritten(const Expr *E)
static bool checkMapConflicts(Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E, bool CurrentRegionOnly, OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents, OpenMPClauseKind CKind)
static bool isOpenMPDeviceDelayedContext(Sema &S)
static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef)
Convert integer expression E to make it have at least Bits bits.
static std::pair< ValueDecl *, bool > getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, SourceRange &ERange, bool AllowArraySection=false, StringRef DiagType="")
static void applyOMPAllocateAttribute(Sema &S, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator, Expr *Alignment, SourceRange SR)
static bool checkOMPArraySectionConstantForReduction(ASTContext &Context, const OMPArraySectionExpr *OASE, bool &SingleElement, SmallVectorImpl< llvm::APSInt > &ArraySizes)
static CapturedStmt * buildDistanceFunc(Sema &Actions, QualType LogicalTy, BinaryOperator::Opcode Rel, Expr *StartExpr, Expr *StopExpr, Expr *StepExpr)
Create a closure that computes the number of iterations of a loop.
static bool checkPreviousOMPAllocateAttribute(Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator)
static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, Expr *NumIterations, Sema &SemaRef, Scope *S, DSAStackTy *Stack)
static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, ArrayRef< unsigned > Exclude=std::nullopt)
static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D, QualType Type, OpenMPClauseKind CKind, SourceLocation ELoc, bool AcceptIfMutable=true, bool ListItemNotVar=false)
static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr, SourceLocation VarLoc, OpenMPClauseKind Kind)
static const ValueDecl * getCanonicalDecl(const ValueDecl *D)
static const Expr * checkMapClauseExpressionBase(Sema &SemaRef, Expr *E, OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose)
Return the expression of the base of the mappable expression or null if it cannot be determined and d...
static bool hasClauses(ArrayRef< OMPClause * > Clauses, const OpenMPClauseKind K)
Check for existence of a map clause in the list of clauses.
static void processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Clauses)
Perform DFS through the structure/class data members trying to find member(s) with user-defined 'defa...
static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion, OpenMPDirectiveKind CancelRegion, SourceLocation StartLoc)
static DeclRefExpr * buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty, SourceLocation Loc, bool RefersToCapture=false)
static ExprResult buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, ExprResult Start, bool IsNonRectangularLB, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures)
Build 'VarRef = Start.
static DoacrossDataInfoTy ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource, ArrayRef< Expr * > VarList, DSAStackTy *Stack, SourceLocation EndLoc)
static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR, Sema &SemaRef, DSAStackTy *Stack, ValueDecl *VD)
static bool findOMPEventHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_event_handle_t type.
static ExprResult buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, Scope *S, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, QualType Ty, CXXCastPath &BasePath, Expr *UnresolvedReduction)
static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef)
Check if the given expression E is a constant integer that fits into Bits bits.
#define DSAStack
static void checkAllocateClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
static bool 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)
static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack, const ValueDecl *D, const DSAStackTy::DSAVarData &DVar, bool IsLoopIterVar=false)
static VarDecl * buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type, StringRef Name, const AttrVec *Attrs=nullptr, DeclRefExpr *OrigRef=nullptr)
Build a variable declaration for OpenMP loop iteration variable.
static DeclRefExpr * buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, bool WithInit)
static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_alloctrait_t type.
static void 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)
static bool isConstNotMutableType(Sema &SemaRef, QualType Type, bool AcceptIfMutable=true, bool *IsClassType=nullptr)
static void checkReductionClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
Check consistency of the reduction clauses.
static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef, DSAStackTy *Stack, QualType QTy, bool FullCheck=true)
static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, OpenMPDirectiveKind CurrentRegion, const DeclarationNameInfo &CurrentName, OpenMPDirectiveKind CancelRegion, OpenMPBindClauseKind BindKind, SourceLocation StartLoc)
static unsigned checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef, DSAStackTy &DSA, Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA, OMPLoopBasedDirective::HelperExprs &Built)
Called on a for stmt to check itself and nested loops (if any).
static OpenMPDefaultmapClauseKind getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD)
static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
Return true if it can be proven that the provided array expression (array section or array subscript)...
static T filterLookupForUDReductionAndMapper(SmallVectorImpl< U > &Lookups, const llvm::function_ref< T(ValueDecl *)> Gen)
static CharSourceRange getRange(const CharSourceRange &EditRange, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeMacroExpansion)
Definition: SourceCode.cpp:104
const char * Data
This file defines OpenMP AST classes for executable directives and clauses.
Allows QualTypes to be sorted and hence used in maps and sets.
SourceLocation Begin
This class visits every VarDecl that the initializer references and adds OMPDeclareTargetDeclAttr to ...
void declareTargetInitializer(Decl *TD)
A function that keeps a record of all the Decls that are variables, has OMPDeclareTargetDeclAttr,...
void VisitDeclRefExpr(DeclRefExpr *Node)
A StmtVisitor class function that visits all DeclRefExpr and adds OMPDeclareTargetDeclAttr to them.
void VisitExpr(Expr *Ex)
A function that iterates across each of the Expr's children.
APSInt & getInt()
Definition: APValue.h:423
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:182
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:1068
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
unsigned getIntWidth(QualType T) const
const llvm::fltSemantics & getFloatTypeSemantics(QualType T) const
Return the APFloat 'semantics' for the specified scalar floating point type.
QualType getMemberPointerType(QualType T, const Type *Cls) const
Return the uniqued reference to the type for a member pointer to the specified type in the specified ...
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, bool Unqualified=false, bool AllowCXX=false, bool IsConditionalOperator=false)
DeclarationNameTable DeclarationNames
Definition: ASTContext.h:643
QualType getUnsignedPointerDiffType() const
Return the unique unsigned counterpart of "ptrdiff_t" integer type.
QualType getVariableArrayType(QualType EltTy, Expr *NumElts, ArraySizeModifier ASM, unsigned IndexTypeQuals, SourceRange Brackets) const
Return a non-unique reference to the type for a variable array of the specified element type.
ASTMutationListener * getASTMutationListener() const
Retrieve a pointer to the AST mutation listener associated with this AST context, if any.
Definition: ASTContext.h:1197
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2549
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:2565
bool DeclMustBeEmitted(const Decl *D)
Determines if the decl can be CodeGen'ed or deserialized from PCH lazily, only when used; this is onl...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType VoidPtrTy
Definition: ASTContext.h:1113
void Deallocate(void *Ptr) const
Definition: ASTContext.h:719
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
CanQualType DependentTy
Definition: ASTContext.h:1114
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
Definition: ASTContext.h:1575
IdentifierTable & Idents
Definition: ASTContext.h:639
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getUIntPtrType() const
Return a type compatible with "uintptr_t" (C99 7.18.1.4), as defined by the target.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
CanQualType BoolTy
Definition: ASTContext.h:1087
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
CanQualType BoundMemberTy
Definition: ASTContext.h:1114
CharUnits getAlignOfGlobalVarInChars(QualType T, const VarDecl *VD) const
Return the alignment in characters that should be given to a global variable with type T.
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Definition: ASTContext.h:2592
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2315
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType VoidTy
Definition: ASTContext.h:1086
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
Definition: ASTContext.h:1553
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:752
bool typesAreCompatible(QualType T1, QualType T2, bool CompareUnqualified=false)
Compatibility predicates used to check assignment expressions.
An abstract interface that should be implemented by listeners that want to be notified when an AST en...
bool isUnset() const
Definition: Ownership.h:167
PtrTy get() const
Definition: Ownership.h:170
bool isInvalid() const
Definition: Ownership.h:166
bool isUsable() const
Definition: Ownership.h:168
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition: Expr.h:2663
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition: Type.h:3147
QualType getElementType() const
Definition: Type.h:3159
Attr - This represents one attribute.
Definition: Attr.h:42
Represents an attribute applied to a statement.
Definition: Stmt.h:2078
static AttributedStmt * Create(const ASTContext &C, SourceLocation Loc, ArrayRef< const Attr * > Attrs, Stmt *SubStmt)
Definition: Stmt.cpp:425
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3834
Expr * getLHS() const
Definition: Expr.h:3883
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition: Expr.cpp:2167
static Opcode getOpForCompoundAssignment(Opcode Opc)
Definition: Expr.h:3980
bool isRelationalOp() const
Definition: Expr.h:3928
SourceLocation getOperatorLoc() const
Definition: Expr.h:3875
SourceLocation getExprLoc() const
Definition: Expr.h:3874
static Opcode reverseComparisonOp(Opcode Opc)
Definition: Expr.h:3952
Expr * getRHS() const
Definition: Expr.h:3885
Opcode getOpcode() const
Definition: Expr.h:3878
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition: Expr.cpp:2129
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2528
Represents a C++ conversion function within a class.
Definition: DeclCXX.h:2855
A call to an overloaded operator written using operator syntax.
Definition: ExprCXX.h:81
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
bool hasMutableFields() const
Determine whether this class, or any of its class subobjects, contains a mutable field.
Definition: DeclCXX.h:1233
bool hasDefinition() const
Definition: DeclCXX.h:571
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:73
bool isValid() const
A scope specifier is present, and it refers to a real scope.
Definition: DeclSpec.h:214
SourceLocation getBeginLoc() const
Definition: DeclSpec.h:83
bool isSet() const
Deprecated.
Definition: DeclSpec.h:227
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const
Retrieve a nested-name-specifier with location information, copied into the given AST context.
Definition: DeclSpec.cpp:152
bool isInvalid() const
An error occurred during parsing of the scope specifier.
Definition: DeclSpec.h:212
Represents the this expression in C++.
Definition: ExprCXX.h:1148
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2819
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
Definition: Expr.cpp:1474
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.cpp:1618
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition: Expr.h:2989
QualType withConst() const
Retrieves a version of this type with const applied.
A wrapper class around a pointer that always points to its canonical declaration.
Definition: Redeclarable.h:349
Represents the body of a CapturedStmt, and serves as its DeclContext.
Definition: Decl.h:4651
unsigned getNumParams() const
Definition: Decl.h:4693
void setNothrow(bool Nothrow=true)
Definition: Decl.cpp:5403
ImplicitParamDecl * getParam(unsigned i) const
Definition: Decl.h:4695
Describes the capture of either a variable, or 'this', or variable-length array type.
Definition: Stmt.h:3768
This captures a statement into a function.
Definition: Stmt.h:3755
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
Definition: Stmt.cpp:1407
SourceRange getSourceRange() const LLVM_READONLY
Definition: Stmt.h:3958
Stmt * getCapturedStmt()
Retrieve the statement being captured.
Definition: Stmt.h:3859
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
Definition: Stmt.cpp:1431
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.h:3950
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition: Expr.h:3489
Declaration of a class template.
Complex values, per C99 6.2.5p11.
Definition: Type.h:2845
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:1604
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
Definition: Stmt.cpp:383
ConditionalOperator - The ?: ternary operator.
Definition: Expr.h:4173
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
Definition: StmtVisitor.h:195
Base class for callback objects used by Sema::CorrectTypo to check the validity of a potential typo c...
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
The results of name lookup within a DeclContext.
Definition: DeclBase.h:1379
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1446
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:2076
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
Definition: DeclBase.h:2201
bool isFileContext() const
Definition: DeclBase.h:2147
bool isExternCXXContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
Definition: DeclBase.cpp:1331
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
Definition: DeclBase.cpp:1265
DeclContext * getLexicalParent()
getLexicalParent - Returns the containing lexical DeclContext.
Definition: DeclBase.h:2092
bool isNamespace() const
Definition: DeclBase.h:2161
bool isTranslationUnit() const
Definition: DeclBase.h:2152
void addDecl(Decl *D)
Add the declaration D into this context.
Definition: DeclBase.cpp:1699
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition: DeclBase.h:2332
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
Definition: DeclBase.cpp:1316
bool Encloses(const DeclContext *DC) const
Determine whether this declaration context encloses the declaration context DC.
Definition: DeclBase.cpp:1335
void addHiddenDecl(Decl *D)
Add the declaration D to this context without modifying any lookup tables.
Definition: DeclBase.cpp:1673
static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls)
Definition: DeclGroup.h:68
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1260
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.cpp:551
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Definition: Expr.cpp:488
ValueDecl * getDecl()
Definition: Expr.h:1328
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Expr.cpp:556
ConstexprSpecKind getConstexprSpecifier() const
Definition: DeclSpec.h:828
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition: Stmt.h:1495
const Decl * getSingleDecl() const
Definition: Stmt.h:1510
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:85
T * getAttr() const
Definition: DeclBase.h:578
bool hasAttrs() const
Definition: DeclBase.h:523
void addAttr(Attr *A)
Definition: DeclBase.cpp:975
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition: DeclBase.h:598
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Definition: DeclBase.cpp:132
void markUsed(ASTContext &C)
Mark the declaration used, in the sense of odr-use.
Definition: DeclBase.cpp:545
bool isReferenced() const
Whether any declaration of this entity was referenced.
Definition: DeclBase.cpp:555
bool isCanonicalDecl() const
Whether this particular Decl is a canonical one.
Definition: DeclBase.h:984
bool isInvalidDecl() const
Definition: DeclBase.h:593
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition: DeclBase.h:564
void setAccess(AccessSpecifier AS)
Definition: DeclBase.h:507
SourceLocation getLocation() const
Definition: DeclBase.h:444
void setImplicit(bool I=true)
Definition: DeclBase.h:599
void setReferenced(bool R=true)
Definition: DeclBase.h:628
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
Definition: DeclBase.h:1049
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
Definition: DeclBase.cpp:530
DeclContext * getDeclContext()
Definition: DeclBase.h:453
AccessSpecifier getAccess() const
Definition: DeclBase.h:512
AttrVec & getAttrs()
Definition: DeclBase.h:529
void setDeclContext(DeclContext *DC)
setDeclContext - Set both the semantic and lexical DeclContext to DC.
Definition: DeclBase.cpp:336
bool hasAttr() const
Definition: DeclBase.h:582
void setLexicalDeclContext(DeclContext *DC)
Definition: DeclBase.cpp:340
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclBase.h:978
Kind getKind() const
Definition: DeclBase.h:447
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition: DeclBase.h:432
DeclarationName getIdentifier(const IdentifierInfo *ID)
Create a declaration name that is a simple identifier.
The name of a declaration.
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
bool isEmpty() const
Evaluates true when this declaration name is empty.
Information about one declarator, including the parsed type information and the identifier.
Definition: DeclSpec.h:1899
void SetIdentifier(IdentifierInfo *Id, SourceLocation IdLoc)
Set the name of this declarator to be the given identifier.
Definition: DeclSpec.h:2338
const DeclSpec & getDeclSpec() const
getDeclSpec - Return the declaration-specifier that this declarator was declared with.
Definition: DeclSpec.h:2046
SourceLocation getIdentifierLoc() const
Definition: DeclSpec.h:2335
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclSpec.h:2082
void setFunctionDefinitionKind(FunctionDefinitionKind Val)
Definition: DeclSpec.h:2732
const CXXScopeSpec & getCXXScopeSpec() const
getCXXScopeSpec - Return the C++ scope specifier (global scope or nested-name-specifier) that is part...
Definition: DeclSpec.h:2061
IdentifierInfo * getIdentifier() const
Definition: DeclSpec.h:2329
bool isInvalidType() const
Definition: DeclSpec.h:2713
RAII object that enters a new expression evaluation context.
The return type of classify().
Definition: Expr.h:330
This represents one expression.
Definition: Expr.h:110
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
bool isGLValue() const
Definition: Expr.h:280
@ SE_AllowSideEffects
Allow any unmodeled side effect.
Definition: Expr.h:671
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition: Expr.cpp:3050
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition: Expr.h:175
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition: Expr.h:437
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition: Expr.h:192
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
Definition: Expr.h:239
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Skip past any parentheses and lvalue casts which might surround this expression until reaching a fixe...
Definition: Expr.cpp:3062
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3045
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3033
bool containsErrors() const
Whether this expression contains subexpressions which had errors, e.g.
Definition: Expr.h:245
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3041
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition: Expr.h:277
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition: Expr.h:444
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition: Expr.h:221
bool isIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3025
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:277
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
QualType getType() const
Definition: Expr.h:142
Represents difference between two FPOptions values.
Definition: LangOptions.h:870
Represents a member of a struct/union/class.
Definition: Decl.h:3025
bool isBitField() const
Determines whether this field is a bitfield.
Definition: Decl.h:3116
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
Definition: Decl.h:3249
static FloatingLiteral * Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L)
Definition: Expr.cpp:1058
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition: Stmt.h:2779
Represents a function declaration or definition.
Definition: Decl.h:1959
const ParmVarDecl * getParamDecl(unsigned i) const
Definition: Decl.h:2674
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:2651
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition: Decl.h:2407
bool isConsteval() const
Definition: Decl.h:2419
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition: Decl.cpp:3657
Represents a prototype with parameter type info, e.g.
Definition: Type.h:4199
One of these records is kept for each identifier that is lexed.
void setMangledOpenMPVariantName(bool I)
Set whether this is the mangled name of an OpenMP variant.
StringRef getName() const
Return the actual identifier string.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IfStmt - This represents an if/then/else.
Definition: Stmt.h:2136
ImaginaryLiteral - We support imaginary integer and floating point literals, like "1....
Definition: Expr.h:1712
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition: Expr.cpp:2060
ImplicitConversionSequence - Represents an implicit conversion sequence, which may be a standard conv...
Definition: Overload.h:540
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateCopy(SourceLocation InitLoc, SourceLocation EqualLoc, bool AllowExplicitConvs=false)
Create a copy initialization.
Describes the sequence of initializations required to initialize a given object or reference with a s...
ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)
Perform the actual initialization of the given entity based on the computed initialization sequence.
Definition: SemaInit.cpp:8578
Describes an entity that is being initialized.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Definition: Expr.cpp:957
Describes the capture of a variable or of this, or of a C++1y init-capture.
Definition: LambdaCapture.h:25
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:418
A class for iterating through a result set and possibly filtering out results.
Definition: Lookup.h:670
Represents the results of name lookup.
Definition: Lookup.h:46
LLVM_ATTRIBUTE_REINITIALIZES void clear()
Clears out any current state.
Definition: Lookup.h:600
DeclClass * getAsSingle() const
Definition: Lookup.h:553
bool empty() const
Return true if no decls were found.
Definition: Lookup.h:359
Filter makeFilter()
Create a filter for this result set.
Definition: Lookup.h:744
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
Definition: Lookup.h:563
bool isAmbiguous() const
Definition: Lookup.h:321
bool isSingleResult() const
Determines if this names a single result which is not an unresolved value using decl.
Definition: Lookup.h:328
NamedDecl * getRepresentativeDecl() const
Fetches a representative decl. Useful for lazy diagnostics.
Definition: Lookup.h:570
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
Definition: Lookup.h:629
iterator end() const
Definition: Lookup.h:356
static bool isVisible(Sema &SemaRef, NamedDecl *D)
Determine whether the given declaration is visible to the program.
iterator begin() const
Definition: Lookup.h:355
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:3182
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition: Expr.h:3261
Expr * getBase() const
Definition: Expr.h:3255
static MemberExpr * CreateImplicit(const ASTContext &C, Expr *Base, bool IsArrow, ValueDecl *MemberDecl, QualType T, ExprValueKind VK, ExprObjectKind OK)
Create an implicit MemberExpr, with no location, qualifier, template arguments, and so on.
Definition: Expr.h:3239
SourceLocation getExprLoc() const LLVM_READONLY
Definition: Expr.h:3373
This represents a decl that may have a name.
Definition: Decl.h:249
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:270
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:276
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:315
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
Definition: Decl.h:292
virtual void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const
Appends a human-readable name for this declaration into the given stream.
Definition: Decl.cpp:1826
A C++ nested-name-specifier augmented with source location information.
This represents 'acq_rel' clause in the '#pragma omp atomic|flush' directives.
This represents 'acquire' clause in the '#pragma omp atomic|flush' directives.
static OMPAffinityClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Creates clause with a modifier a list of locator items.
static OMPAlignClause * Create(const ASTContext &C, Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'align' clause with the given alignment.
static OMPAlignedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Expr *A)
Creates clause with a list of variables VL and alignment A.
static OMPAllocateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, Expr *Allocator, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static bool classof(const OMPClause *T)
Definition: OpenMPClause.h:515
static OMPAllocateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL, ArrayRef< OMPClause * > CL)
Definition: DeclOpenMP.cpp:57
This represents 'allocator' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:354
OpenMP 5.0 [2.1.5, Array Sections].
Definition: ExprOpenMP.h:56
Expr * getLength()
Get length of array section.
Definition: ExprOpenMP.h:102
SourceLocation getColonLocFirst() const
Definition: ExprOpenMP.h:118
Expr * getBase()
An array section can be written only as Base[LowerBound:Length].
Definition: ExprOpenMP.h:85
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition: Expr.cpp:5049
Expr * getLowerBound()
Get lower bound of array section.
Definition: ExprOpenMP.h:94
An explicit cast in C or a C-style cast in C++, which uses the syntax ([s1][s2]......
Definition: ExprOpenMP.h:148
Expr * getBase()
Fetches base expression of array shaping expression.
Definition: ExprOpenMP.h:214
This represents 'at' clause in the '#pragma omp error' directive.
SourceLocation getAtKindKwLoc() const
Returns location of clause kind.
OpenMPAtClauseKind getAtKind() const
Returns kind of the clause.
This represents 'atomic_default_mem_order' clause in the '#pragma omp requires' directive.
static OMPAtomicDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expressions Exprs)
Creates directive with a list of Clauses and 'x', 'v' and 'expr' parts of the atomic construct (see S...
Definition: StmtOpenMP.cpp:917
static OMPBarrierDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates directive.
Definition: StmtOpenMP.cpp:781
This represents 'bind' clause in the '#pragma omp ...' directives.
static OMPBindClause * Create(const ASTContext &C, OpenMPBindClauseKind K, SourceLocation KLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'bind' clause with kind K ('teams', 'parallel', or 'thread').
static OMPCancelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind CancelRegion)
Creates directive.
Definition: StmtOpenMP.cpp:837
static OMPCancellationPointDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Creates directive.
Definition: StmtOpenMP.cpp:823
static OMPCanonicalLoop * create(const ASTContext &Ctx, Stmt *LoopStmt, CapturedStmt *DistanceFunc, CapturedStmt *LoopVarFunc, DeclRefExpr *LoopVarRef)
Create a new OMPCanonicalLoop.
Definition: StmtOpenMP.h:163
This represents 'capture' clause in the '#pragma omp atomic' directive.
Pseudo declaration for capturing expressions.
Definition: DeclOpenMP.h:383
static OMPCapturedExprDecl * Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, QualType T, SourceLocation StartLoc)
Definition: DeclOpenMP.cpp:174
Class that represents a component of a mappable expression.
static OMPClauseWithPostUpdate * get(OMPClause *C)
Class that handles pre-initialization statement for some clauses, like 'shedule', 'firstprivate' etc.
Definition: OpenMPClause.h:195
static OMPClauseWithPreInit * get(OMPClause *C)
This is a basic class for representing single OpenMP clause.
Definition: OpenMPClause.h:55
SourceLocation getBeginLoc() const
Returns the starting location of the clause.
Definition: OpenMPClause.h:71
SourceLocation getEndLoc() const
Returns the ending location of the clause.
Definition: OpenMPClause.h:74
OpenMPClauseKind getClauseKind() const
Returns kind of OpenMP clause (private, shared, reduction, etc.).
Definition: OpenMPClause.h:83
This represents 'collapse' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:977
This represents 'compare' clause in the '#pragma omp atomic' directive.
static OMPCopyinClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
static OMPCopyprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
This represents '#pragma omp critical' directive.
Definition: StmtOpenMP.h:2092
static OMPCriticalDirective * Create(const ASTContext &C, const DeclarationNameInfo &Name, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
Definition: StmtOpenMP.cpp:583
DeclarationNameInfo getDirectiveName() const
Return name of the directive.
Definition: StmtOpenMP.h:2147
This represents '#pragma omp declare mapper ...' directive.
Definition: DeclOpenMP.h:287
static OMPDeclareMapperDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, DeclarationName VarName, ArrayRef< OMPClause * > Clauses, OMPDeclareMapperDecl *PrevDeclInScope)
Creates declare mapper node.
Definition: DeclOpenMP.cpp:142
This represents '#pragma omp declare reduction ...' directive.
Definition: DeclOpenMP.h:177
static OMPDeclareReductionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, OMPDeclareReductionDecl *PrevDeclInScope)
Create declare reduction node.
Definition: DeclOpenMP.cpp:112
This represents 'default' clause in the '#pragma omp ...' directive.
This represents 'defaultmap' clause in the '#pragma omp ...' directive.
This represents implicit clause 'depend' for the '#pragma omp task' directive.
static OMPDependClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, DependDataTy Data, Expr *DepModifier, ArrayRef< Expr * > VL, unsigned NumLoops)
Creates clause with a list of variables VL.
static OMPDepobjClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Depobj)
Creates clause.
static OMPDepobjDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:868
This represents 'destroy' clause in the '#pragma omp depobj' directive or the '#pragma omp interop' d...
This represents 'detach' clause in the '#pragma omp task' directive.
This represents 'device' clause in the '#pragma omp ...' directive.
static OMPDispatchDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, SourceLocation TargetCallLoc)
Creates directive with a list of Clauses.
This represents 'dist_schedule' clause in the '#pragma omp ...' directive.
static OMPDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, OpenMPDirectiveKind ParamPrevMappedDirective)
Creates directive with a list of Clauses.
static OMPDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents the 'doacross' clause for the '#pragma omp ordered' directive.
static OMPDoacrossClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VL, unsigned NumLoops)
Creates clause with a list of expressions VL.
This represents 'dynamic_allocators' clause in the '#pragma omp requires' directive.
static OMPErrorDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Definition: StmtOpenMP.cpp:766
static OMPExclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This is a basic class for representing single OpenMP executable directive.
Definition: StmtOpenMP.h:266
OpenMPDirectiveKind getDirectiveKind() const
Definition: StmtOpenMP.h:569
This represents 'fail' clause in the '#pragma omp atomic' directive.
This represents 'filter' clause in the '#pragma omp ...' directive.
This represents 'final' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:630
static OMPFirstprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PrivateVL, ArrayRef< Expr * > InitVL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents implicit clause 'flush' for the '#pragma omp flush' directive.
static OMPFlushClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPFlushDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:853
static OMPForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel, OpenMPDirectiveKind ParamPrevMappedDirective)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:336
static OMPForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:453
static OMPFromClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
Representation of the 'full' clause of the '#pragma omp unroll' directive.
Definition: OpenMPClause.h:879
static OMPFullClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Build an AST node for a 'full' clause.
static OMPGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'grainsize' clause in the '#pragma omp ...' directive.
static OMPHasDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
This represents 'hint' clause in the '#pragma omp ...' directive.
This represents 'if' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:527
static OMPInReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > TaskgroupDescriptors, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
static OMPInclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPInitClause * Create(const ASTContext &C, Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Creates a fully specified clause.
static OMPInteropDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
static OMPIsDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPLastprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
This represents clause 'linear' in the '#pragma omp ...' directives.
Expr * getStep()
Returns linear step.
void setUpdates(ArrayRef< Expr * > UL)
Sets the list of update expressions for linear variables.
privates_range privates()
void setFinals(ArrayRef< Expr * > FL)
Sets the list of final update expressions for linear variables.
void setUsedExprs(ArrayRef< Expr * > UE)
Sets the list of used expressions for the linear clause.
static OMPLinearClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation StepModifierLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PL, ArrayRef< Expr * > IL, Expr *Step, Expr *CalcStep, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL and a linear step Step.
Expr * getCalcStep()
Returns expression to calculate linear step.
OpenMPLinearClauseKind getModifier() const
Return modifier.
The base class for all loop-based directives, including loop transformation directives.
Definition: StmtOpenMP.h:698
static bool doForAllLoops(Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops, llvm::function_ref< bool(unsigned, Stmt *)> Callback, llvm::function_ref< void(OMPLoopTransformationDirective *)> OnTransformationCallback)
Calls the specified callback function for all the loops in CurStmt, from the outermost to the innermo...
Definition: StmtOpenMP.cpp:125
The base class for all loop transformation directives.
Definition: StmtOpenMP.h:975
static OMPMapClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapModifiers, ArrayRef< SourceLocation > MapModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId, OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc)
Creates clause with a list of variables VL.
static OMPMaskedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPMasterDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt)
Creates directive.
Definition: StmtOpenMP.cpp:568
static OMPMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'mergeable' clause in the '#pragma omp ...' directive.
This represents 'message' clause in the '#pragma omp error' directive.
Expr * getMessageString() const
Returns message string of the clause.
This represents 'nocontext' clause in the '#pragma omp ...' directive.
This represents 'nogroup' clause in the '#pragma omp ...' directive.
static OMPNontemporalClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'novariants' clause in the '#pragma omp ...' directive.
This represents 'nowait' clause in the '#pragma omp ...' directive.
This represents 'num_tasks' clause in the '#pragma omp ...' directive.
This represents 'num_teams' clause in the '#pragma omp ...' directive.
This represents 'num_threads' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:676
This represents 'order' clause in the '#pragma omp ...' directive.
SourceLocation getKindKwLoc() const
Returns location of clause kind.
OpenMPOrderClauseKind getKind() const
Returns kind of the clause.
This represents 'ordered' clause in the '#pragma omp ...' directive.
Expr * getNumForLoops() const
Return the number of associated for-loops.
static OMPOrderedClause * Create(const ASTContext &C, Expr *Num, unsigned NumLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'ordered' clause.
static OMPOrderedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
Definition: StmtOpenMP.cpp:898
static OMPParallelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:281
static OMPParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:599
static OMPParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:644
static OMPParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelMaskedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:704
static OMPParallelMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelMasterDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:688
static OMPParallelMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelSectionsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:720
Representation of the 'partial' clause of the '#pragma omp unroll' directive.
Definition: OpenMPClause.h:907
static OMPPartialClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Factor)
Build an AST node for a 'partial' clause.
Expr * getFactor() const
Returns the argument of the clause or nullptr if not set.
Definition: OpenMPClause.h:946
This represents 'priority' clause in the '#pragma omp ...' directive.
static OMPPrivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PrivateVL)
Creates clause with a list of variables VL.
This represents 'proc_bind' clause in the '#pragma omp ...' directive.
This represents 'read' clause in the '#pragma omp atomic' directive.
static OMPReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, OpenMPReductionClauseModifier Modifier, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > CopyOps, ArrayRef< Expr * > CopyArrayTemps, ArrayRef< Expr * > CopyArrayElems, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
This represents 'relaxed' clause in the '#pragma omp atomic' directives.
This represents 'release' clause in the '#pragma omp atomic|flush' directives.
This represents '#pragma omp requires...' directive.
Definition: DeclOpenMP.h:416
clauselist_range clauselists()
Definition: DeclOpenMP.h:441
static OMPRequiresDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< OMPClause * > CL)
Create requires node.
Definition: DeclOpenMP.cpp:85
This represents 'reverse_offload' clause in the '#pragma omp requires' directive.
This represents 'simd' clause in the '#pragma omp ...' directive.
This represents 'safelen' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:721
Expr * getSafelen() const
Return safe iteration space distance.
Definition: OpenMPClause.h:741
static OMPScanDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:883
This represents 'schedule' clause in the '#pragma omp ...' directive.
SourceLocation getFirstScheduleModifierLoc() const
Get the first modifier location.
OpenMPScheduleClauseModifier getSecondScheduleModifier() const
Get the second modifier of the clause.
OpenMPScheduleClauseModifier getFirstScheduleModifier() const
Get the first modifier of the clause.
SourceLocation getSecondScheduleModifierLoc() const
Get the second modifier location.
static OMPScopeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
Definition: StmtOpenMP.cpp:534
static OMPSectionDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, bool HasCancel)
Creates directive.
Definition: StmtOpenMP.cpp:516
static OMPSectionsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:496
This represents 'seq_cst' clause in the '#pragma omp atomic' directive.
This represents 'severity' clause in the '#pragma omp error' directive.
OpenMPSeverityClauseKind getSeverityKind() const
Returns kind of the clause.
SourceLocation getSeverityKindKwLoc() const
Returns location of clause kind.
static OMPSharedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, OpenMPDirectiveKind ParamPrevMappedDirective)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:300
This represents 'simdlen' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:756
Expr * getSimdlen() const
Return safe iteration space distance.
Definition: OpenMPClause.h:776
static OMPSingleDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:551
This represents the 'sizes' clause in the '#pragma omp tile' directive.
Definition: OpenMPClause.h:788
static OMPSizesClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Sizes)
Build a 'sizes' AST node.
unsigned getNumSizes() const
Returns the number of list items.
Definition: OpenMPClause.h:828
MutableArrayRef< Expr * > getSizesRefs()
Returns the tile size expressions.
Definition: OpenMPClause.h:831
static OMPTargetDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:942
static OMPTargetEnterDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetExitDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetParallelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:958
static OMPTargetParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:976
static OMPTargetParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetUpdateDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTaskDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, bool HasCancel)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:739
static OMPTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTaskReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
static OMPTaskgroupDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *ReductionRef)
Creates directive.
Definition: StmtOpenMP.cpp:807
static OMPTaskwaitDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
Definition: StmtOpenMP.cpp:793
static OMPTaskyieldDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates directive.
Definition: StmtOpenMP.cpp:755
static OMPTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'thread_limit' clause in the '#pragma omp ...' directive.
This represents '#pragma omp threadprivate ...' directive.
Definition: DeclOpenMP.h:110
static OMPThreadPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
Definition: DeclOpenMP.cpp:28
This represents 'threads' clause in the '#pragma omp ...' directive.
static OMPTileDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp tile'.
Definition: StmtOpenMP.cpp:410
static OMPToClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
Helper data structure representing the traits in a match clause of an declare variant or metadirectiv...
bool anyScoreOrCondition(llvm::function_ref< bool(Expr *&, bool)> Cond)
void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const
Create a variant match info object from this trait info object.
This represents 'unified_address' clause in the '#pragma omp requires' directive.
This represents 'unified_shared_memory' clause in the '#pragma omp requires' directive.
static OMPUnrollDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, unsigned NumGeneratedLoops, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp unroll'.
Definition: StmtOpenMP.cpp:431
This represents 'untied' clause in the '#pragma omp ...' directive.
static OMPUpdateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates clause for 'atomic' directive.
This represents the 'use' clause in '#pragma omp ...' directives.
static OMPUseDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPUseDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< Expr * > PrivateVars, ArrayRef< Expr * > Inits, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPUsesAllocatorsClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< OMPUsesAllocatorsClause::Data > Data)
Creates clause with a list of allocators Data.
varlist_range varlists()
Definition: OpenMPClause.h:319
SourceLocation getLParenLoc() const
Returns the location of '('.
Definition: OpenMPClause.h:335
unsigned varlist_size() const
Definition: OpenMPClause.h:316
This represents 'weak' clause in the '#pragma omp atomic' directives.
This represents 'write' clause in the '#pragma omp atomic' directive.
This represents 'ompx_attribute' clause in a directive that might generate an outlined function.
This represents 'ompx_bare' clause in the '#pragma omp target teams ...' directive.
This represents 'ompx_dyn_cgroup_mem' clause in the '#pragma omp target ...' directive.
Wrapper for void* pointer.
Definition: Ownership.h:50
void * getAsOpaquePtr() const
Definition: Ownership.h:90
PtrTy get() const
Definition: Ownership.h:80
static OpaquePtr make(PtrTy P)
Definition: Ownership.h:60
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition: Expr.h:1168
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition: Expr.h:1218
void setIsUnique(bool V)
Definition: Expr.h:1220
Represents a parameter to a function.
Definition: Decl.h:1749
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
Definition: Decl.cpp:2915
IdentifierTable & getIdentifierTable()
static PseudoObjectExpr * Create(const ASTContext &Context, Expr *syntactic, ArrayRef< Expr * > semantic, unsigned resultIndex)
Definition: Expr.cpp:4861
A (possibly-)qualified type.
Definition: Type.h:737
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
Definition: Type.cpp:2665
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition: Type.h:6990
QualType withRestrict() const
Definition: Type.h:967
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
Definition: Type.cpp:3403
QualType withConst() const
Definition: Type.h:951
void addConst()
Add the const type qualifier to this QualType.
Definition: Type.h:948
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:804
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: Type.h:6902
bool isConstant(const ASTContext &Ctx) const
Definition: Type.h:897
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition: Type.h:7102
QualType getCanonicalType() const
Definition: Type.h:6954
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:6995
bool isMoreQualifiedThan(QualType Other) const
Determine whether this type is more qualified than the other given type, requiring exact equality for...
Definition: Type.h:7073
const Type * getTypePtrOrNull() const
Definition: Type.h:6906
Represents a struct/union/class.
Definition: Decl.h:4133
field_range fields() const
Definition: Decl.h:4339
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:5092
decl_type * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
Definition: Redeclarable.h:204
decl_type * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
Definition: Redeclarable.h:226
Base for LValueReferenceType and RValueReferenceType.
Definition: Type.h:3009
Scope - A scope is a transient data structure that is used while parsing the program.
Definition: Scope.h:41
bool isDeclScope(const Decl *D) const
isDeclScope - Return true if this is the scope that the specified decl is declared in.
Definition: Scope.h:375
Scope * getBreakParent()
getBreakParent - Return the closest scope that a break statement would be affected by.
Definition: Scope.h:299
bool isOpenMPOrderClauseScope() const
Determine whether this scope is some OpenMP directive with order clause which specifies concurrent sc...
Definition: Scope.h:524
const Scope * getParent() const
getParent - Return the scope that this is nested in.
Definition: Scope.h:264
bool isOpenMPLoopScope() const
Determine whether this scope is a loop having OpenMP loop directive attached.
Definition: Scope.h:517
@ OpenMPOrderClauseScope
This is a scope of some OpenMP directive with order clause which specifies concurrent.
Definition: Scope.h:150
A RAII object to enter scope of a compound statement.
Definition: Sema.h:1037
Expr * get() const
Definition: Sema.h:6045
A generic diagnostic builder for errors which may or may not be deferred.
Definition: Sema.h:598
@ K_Nop
Emit no diagnostics.
Definition: Sema.h:602
@ K_Deferred
Create a deferred diagnostic, which is emitted only if the function it's attached to is codegen'ed.
Definition: Sema.h:612
@ K_Immediate
Emit the diagnostic immediately (i.e., behave like Sema::Diag()).
Definition: Sema.h:604
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition: Sema.h:9794
Abstract base class used for diagnosing integer constant expression violations.
Definition: Sema.h:5994
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:426
OMPClause * ActOnOpenMPXBareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_bare' clause.
OMPClause * 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=false, ArrayRef< Expr * > UnresolvedMappers=std::nullopt)
Called on well-formed 'map' clause.
OMPClause * ActOnOpenMPWeakClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'weak' clause.
ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo)
Package the given type and TSI into a ParsedType.
Definition: SemaType.cpp:6768
OMPClause * ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data, Expr *DepModifier, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depend' clause.
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
OMPClause * ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'init' clause.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition: Sema.h:869
const ValueDecl * getOpenMPDeclareMapperVarName() const
OMPClause * ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart(Scope *S, DeclContext *DC, DeclarationName Name, ArrayRef< std::pair< QualType, SourceLocation > > ReductionTypes, AccessSpecifier AS, Decl *PrevDeclInScope=nullptr)
Called on start of '#pragma omp declare reduction'.
DeclGroupPtrTy 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)
Called on well-formed '#pragma omp declare simd' after parsing of the associated method/function.
OMPClause * ActOnOpenMPNumThreadsClause(Expr *NumThreads, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_threads' clause.
bool isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S=nullptr, bool AllowInlineNamespace=false) const
isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true if 'D' is in Scope 'S',...
Definition: SemaDecl.cpp:1575
ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val)
Definition: SemaExpr.cpp:3859
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:16292
void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath)
ExprResult IgnoredValueConversions(Expr *E)
IgnoredValueConversions - Given that an expression's result is syntactically ignored,...
OMPClause * ActOnOpenMPNovariantsClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'novariants' clause.
StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target teams' after parsing of the associated statement.
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition: Sema.h:7607
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
Definition: Sema.h:7648
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
Definition: Sema.h:7650
@ LookupAnyName
Look up any declaration with any name.
Definition: Sema.h:7652
OMPClause * ActOnOpenMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'write' clause.
OMPClause * ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, ArrayRef< unsigned > Arguments, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, ArrayRef< SourceLocation > ArgumentsLoc, SourceLocation DelimLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPExclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'exclusive' clause.
static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind)
Return the number of captured regions created for an OpenMP directive.
OMPClause * ActOnOpenMPUseDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_ptr' clause.
ImplicitConversionSequence TryImplicitConversion(Expr *From, QualType ToType, bool SuppressUserConversions, AllowedExplicit AllowExplicit, bool InOverloadResolution, bool CStyle, bool AllowObjCWritebackConversion)
StmtResult ActOnOpenMPScanDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scan'.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: Sema.cpp:1911
void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init)
Check if the current region is an OpenMP loop region and if it is, mark loop control variable,...
void ActOnOpenMPEndAssumesDirective()
Called on well-formed '#pragma omp end assumes'.
OMPClause * ActOnOpenMPFlushClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'flush' pseudo clause.
void DiagnoseUnterminatedOpenMPDeclareTarget()
Report unterminated 'omp declare target' or 'omp begin declare target' at the end of a compilation un...
OMPClause * ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'device' clause.
OMPClause * ActOnOpenMPUseDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_addr' clause.
OMPClause * ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'priority' clause.
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
Definition: Sema.h:3648
OMPClause * ActOnOpenMPOrderClause(OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'order' clause.
StmtResult ActOnOpenMPOrderedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp ordered' after parsing of the associated statement.
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl=nullptr, ExpressionEvaluationContextRecord::ExpressionKind Type=ExpressionEvaluationContextRecord::EK_Other)
Definition: SemaExpr.cpp:18205
StmtResult ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancellation point'.
ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E, bool IsConstexpr=false)
CheckBooleanCondition - Diagnose problems involving the use of the given expression as a boolean cond...
Definition: SemaExpr.cpp:21143
OMPClause * ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nowait' clause.
bool isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const
OMPClause * ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc)
SmallVector< sema::FunctionScopeInfo *, 4 > FunctionScopes
Stack containing information about each of the nested function, block, and method scopes that are cur...
Definition: Sema.h:979
StmtResult ActOnOpenMPDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for' after parsing of the associated statement...
@ AR_inaccessible
Definition: Sema.h:1210
PoppedFunctionScopePtr PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP=nullptr, const Decl *D=nullptr, QualType BlockType=QualType())
Pop a function (or block or lambda or captured region) scope from the stack.
Definition: Sema.cpp:2260
OMPClause * ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'dynamic_allocators' clause.
bool CheckCXXThisCapture(SourceLocation Loc, bool Explicit=false, bool BuildAndDiagnose=true, const unsigned *const FunctionScopeIndexToStopAt=nullptr, bool ByCopy=false)
Make sure the value of 'this' is actually available in the current context, if it is a potentially ev...
OMPClause * ActOnOpenMPAllocateClause(Expr *Allocator, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocate' clause.
StmtResult ActOnOpenMPTargetSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target simd' after parsing of the associated statement.
StmtResult ActOnOpenMPForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for' after parsing of the associated statement.
NamedDecl * HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists)
Definition: SemaDecl.cpp:6344
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, AllowFoldKind CanFold=NoFold)
VerifyIntegerConstantExpression - Verifies that an expression is an ICE, and reports the appropriate ...
Definition: SemaExpr.cpp:17996
StmtResult ActOnOpenMPLoopnest(Stmt *AStmt)
Process a canonical OpenMP loop nest that can either be a canonical literal loop (ForStmt or CXXForRa...
OMPClause * ActOnOpenMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'simd' clause.
StmtResult ActOnOpenMPTargetParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel for' after parsing of the associated statement.
FPOptionsOverride CurFPFeatureOverrides()
Definition: Sema.h:1556
ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, SourceLocation StartLoc, DeclarationName VN)
Build the mapper variable of '#pragma omp declare mapper'.
StmtResult ActOnOpenMPTaskwaitDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskwait'.
void MarkDeclarationsReferencedInExpr(Expr *E, bool SkipLocalVariables=false, ArrayRef< const Expr * > StopAt=std::nullopt)
Mark any declarations that appear within this expression or any potentially-evaluated subexpressions ...
Definition: SemaExpr.cpp:20928
TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D)
Check variable declaration in 'omp declare mapper' construct.
StmtResult ActOnOpenMPDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for simd' after parsing of the associated stat...
DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef< OMPClause * > ClauseList)
Called on well-formed '#pragma omp requires'.
void startOpenMPLoop()
If the current region is a loop-based region, mark the start of the loop construct.
OMPClause * ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'destroy' clause.
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
Definition: Sema.cpp:1489
ExprResult PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter)
Perform a contextual implicit conversion.
OMPClause * ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'bind' clause.
ExprResult PerformImplicitConversion(Expr *From, QualType ToType, const ImplicitConversionSequence &ICS, AssignmentAction Action, CheckedConversionKind CCK=CCK_ImplicitConversion)
PerformImplicitConversion - Perform an implicit conversion of the expression From to the type ToType ...
bool isInOpenMPTaskUntiedContext() const
Return true if currently in OpenMP task with untied clause context.
StmtResult ActOnOpenMPMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop' after parsing of the associated statement.
ASTContext & Context
Definition: Sema.h:1030
StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target exit data' after parsing of the associated statement.
OMPClause * ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'final' clause.
void ActOnCapturedRegionError()
Definition: SemaStmt.cpp:4927
StmtResult ActOnOpenMPFlushDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp flush'.
OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef< Expr * > Vars, const OMPVarListLocTy &Locs, OpenMPVarListDataTy &Data)
OMPClause * ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'hint' clause.
SemaDiagnosticBuilder diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as host cod...
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed '#pragma omp threadprivate'.
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
Definition: SemaDecl.cpp:62
@ AllowFold
Definition: Sema.h:6010
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
Definition: SemaDecl.cpp:1517
void CleanupVarDeclMarking()
Definition: SemaExpr.cpp:20429
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
Definition: SemaExpr.cpp:755
ASTContext & getASTContext() const
Definition: Sema.h:501
void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, const FunctionDecl *Callee, SourceLocation Loc)
Finishes analysis of the deferred functions calls that may be declared as host/nohost during device/h...
StmtResult ActOnOpenMPDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPSharedClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'shared' clause.
NamedDecl * LookupSingleName(Scope *S, DeclarationName Name, SourceLocation Loc, LookupNameKind NameKind, RedeclarationKind Redecl=NotForRedeclaration)
Look up a name, looking for a single declaration.
ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:16571
StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target update'.
StmtResult ActOnOpenMPSingleDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp single' after parsing of the associated statement.
bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc, TryCaptureKind Kind, SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType, QualType &DeclRefType, const unsigned *const FunctionScopeIndexToStopAt)
Try to capture the given variable.
Definition: SemaExpr.cpp:19722
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for simd' after parsing of the as...
void MarkVariableReferenced(SourceLocation Loc, VarDecl *Var)
Mark a variable referenced, and check whether it is odr-used (C++ [basic.def.odr]p2,...
Definition: SemaExpr.cpp:20680
OMPClause * ActOnOpenMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'capture' clause.
void PopExpressionEvaluationContext()
Definition: SemaExpr.cpp:18631
StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)
End of OpenMP region.
StmtResult ActOnOpenMPParallelMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop' after parsing of the associated statemen...
StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target parallel' after parsing of the associated statement.
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition: Sema.h:947
bool isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified global variable must be captured by outer capture regions.
OMPClause * ActOnOpenMPAtClause(OpenMPAtClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'at' clause.
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
Definition: SemaExpr.cpp:2199
StmtResult ActOnOpenMPParallelMasterDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel master' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target' after parsing of the associated statement.
StmtResult ActOnOpenMPCancelDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancel'.
OMPClause * ActOnOpenMPReductionClause(ArrayRef< Expr * > VarList, OpenMPReductionClauseModifier Modifier, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=std::nullopt)
Called on well-formed 'reduction' clause.
OMPClause * ActOnOpenMPUntiedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'untied' clause.
void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc, ArrayRef< Expr * > Args, AssociatedNamespaceSet &AssociatedNamespaces, AssociatedClassSet &AssociatedClasses)
Find the associated classes and namespaces for argument-dependent lookup for a call with the given se...
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id, OpenMPDirectiveKind Kind)
Called on correct id-expression from the '#pragma omp threadprivate'.
OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, SourceLocation IdLoc=SourceLocation())
Check declaration inside target region.
OMPClause * ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'update' clause.
ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc, Expr *Op)
void PushFunctionScope()
Enter a new function scope.
Definition: Sema.cpp:2141
OMPClause * ActOnOpenMPFirstprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'firstprivate' clause.
void tryCaptureOpenMPLambdas(ValueDecl *V)
Function tries to capture lambda's captured variables in the OpenMP region before the original lambda...
StmtResult ActOnOpenMPDepobjDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp depobj'.
StmtResult ActOnOpenMPInteropDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp interop'.
OMPClause * ActOnOpenMPXDynCGroupMemClause(Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_dyn_cgroup_mem' clause.
const LangOptions & getLangOpts() const
Definition: Sema.h:494
TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, CorrectTypoKind Mode, DeclContext *MemberContext=nullptr, bool EnteringContext=false, const ObjCObjectPointerType *OPT=nullptr, bool RecordFailure=true)
Try to "correct" a typo in the source code by finding visible declarations whose names are similar to...
OMPClause * ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'severity' clause.
OMPClause * ActOnOpenMPAcquireClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acquire' clause.
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
OMPClause * ActOnOpenMPScheduleClause(OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'schedule' clause.
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind PrevMappedDirective=llvm::omp::OMPD_unknown)
void ActOnOpenMPIteratorVarDecl(VarDecl *VD)
Preprocessor & PP
Definition: Sema.h:1029
OMPClause * ActOnOpenMPHasDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'has_device_addr' clause.
ExprResult BuildCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr, bool IsExecConfig=false, bool AllowRecovery=false)
BuildCallExpr - Handle a call to Fn with the specified array of arguments.
Definition: SemaExpr.cpp:7195
AccessResult CheckBaseClassAccess(SourceLocation AccessLoc, QualType Base, QualType Derived, const CXXBasePath &Path, unsigned DiagID, bool ForceCheck=false, bool ForceUnprivileged=false)
Checks access for a hierarchy conversion.
OMPClause * ActOnOpenMPAcqRelClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acq_rel' clause.
StmtResult ActOnOpenMPParallelMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop simd' after parsing of the associated sta...
void ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(Decl *D, SmallVectorImpl< FunctionDecl * > &Bases)
Register D as specialization of all base functions in Bases in the current omp begin/end declare vari...
ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind, bool StrictlyPositive=true, bool SuppressExprDiags=false)
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)
Called on well-formed '#pragma omp allocate'.
void CheckExtraCXXDefaultArguments(Declarator &D)
CheckExtraCXXDefaultArguments - Check for any extra default arguments in the declarator,...
OMPClause * ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'simdlen' clause.
const LangOptions & LangOpts
Definition: Sema.h:1028
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
Definition: Sema.cpp:2375
OMPClause * ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'filter' clause.
OMPClause * ActOnOpenMPAffinityClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Called on well-formed 'affinity' clause.
OMPClause * ActOnOpenMPProcBindClause(llvm::omp::ProcBindKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'proc_bind' clause.
OMPThreadPrivateDecl * CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef< Expr * > VarList)
Builds a new OpenMPThreadPrivateDecl and checks its correctness.
SemaDiagnosticBuilder diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as device c...
bool isInOpenMPAssumeScope() const
Check if there is an active global omp begin assumes directive.
Definition: Sema.h:13578
void startOpenMPCXXRangeFor()
If the current region is a range loop-based region, mark the start of the loop construct.
void setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, unsigned Level)
Sets OpenMP capture kind (OMPC_private, OMPC_firstprivate, OMPC_map etc.) for FD based on DSA for the...
OMPClause * ActOnOpenMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'seq_cst' clause.
StmtResult ActOnOpenMPMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPAlignClause(Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'align' clause.
StmtResult ActOnOpenMPForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for simd' after parsing of the associated statement.
DeclContext * getCurLexicalContext() const
Definition: Sema.h:873
OMPClause * ActOnOpenMPNumTeamsClause(Expr *NumTeams, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_teams' clause.
bool isInOpenMPDeclareTargetContext() const
Return true inside OpenMP declare target region.
Definition: Sema.h:13706
bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, bool AllowBuiltinCreation=false, bool EnteringContext=false)
Performs name lookup for a name that was parsed in the source code, and may contain a C++ scope speci...
void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT, DeclareTargetContextInfo &DTCI)
Called on correct id-expression from the '#pragma omp declare target'.
OMPClause * ActOnOpenMPInReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=std::nullopt)
Called on well-formed 'in_reduction' clause.
OMPClause * ActOnOpenMPDefaultClause(llvm::omp::DefaultKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'default' clause.
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
Definition: SemaCast.cpp:3331
void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, CapturedRegionKind Kind, unsigned NumParams)
Definition: SemaStmt.cpp:4838
OMPClause * ActOnOpenMPNocontextClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nocontext' clause.
StmtResult ActOnOpenMPMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop simd' after parsing of the associated statement.
sema::FunctionScopeInfo * getCurFunction() const
Definition: Sema.h:1064
OMPClause * ActOnOpenMPAlignedClause(ArrayRef< Expr * > VarList, Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'aligned' clause.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for' after parsing of the associa...
StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel sections' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target enter data' after parsing of the associated statement.
Expr * BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit)
Build a CXXThisExpr and mark it referenced in the current context.
OMPClause * ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation NameModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'if' clause.
ExprResult ActOnOpenMPCall(ExprResult Call, Scope *Scope, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig)
Given the potential call expression Call, determine if there is a specialization via the OpenMP decla...
StmtResult ActOnOpenMPTargetTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute' after parsing of the associated statement...
OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)
Called on well-formed 'uses_allocators' clause.
OMPClause * ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc, SourceLocation LParenLoc=SourceLocation(), Expr *NumForLoops=nullptr)
Called on well-formed 'ordered' clause.
StmtResult ActOnOpenMPParallelMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop simd' after parsing of the associated sta...
StmtResult ActOnOpenMPTaskDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp task' after parsing of the associated statement.
ExprResult DefaultLvalueConversion(Expr *E)
Definition: SemaExpr.cpp:645
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
Definition: Sema.h:11968
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< Expr * > AdjustArgsNothing, ArrayRef< Expr * > AdjustArgsNeedDevicePtr, ArrayRef< OMPInteropInfo > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)
Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.
FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, bool Final=false)
Definition: SemaDecl.cpp:20608
StmtResult ActOnOpenMPUnrollDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp unroll' after parsing of its clauses and the associated statement.
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
OMPClause * ActOnOpenMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'mergeable' clause.
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
Definition: Sema.cpp:2331
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition: Sema.h:1163
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope)
Initialization of captured region for OpenMP region.
bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, OpenMPLinearClauseKind LinKind, QualType Type, bool IsDeclareSimd=false)
Checks that the specified declaration matches requirements for the linear decls.
StmtResult ActOnOpenMPDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute' after parsing of the associated statement.
VarDecl * ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
void ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D)
Act on D, a function definition inside of an omp [begin/end] assumes.
StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp barrier'.
StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp master' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskgroup'.
OMPClause * ActOnOpenMPReleaseClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'release' clause.
OMPClause * ActOnOpenMPCopyinClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyin' clause.
StmtResult ActOnCapturedRegionEnd(Stmt *S)
Definition: SemaStmt.cpp:4942
StmtResult ActOnOpenMPTargetTeamsDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute simd' after parsing of the associated stat...
StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp critical' after parsing of the associated statement.
StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel masked' after parsing of the associated statement.
bool isInOpenMPDeclareVariantScope() const
Can we exit an OpenMP declare variant scope at the moment.
Definition: Sema.h:13446
OMPClause * ActOnOpenMPDistScheduleClause(OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'dist_schedule' clause.
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E)
Definition: SemaExpr.cpp:4341
void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, VarDecl *OmpPrivParm)
Finish current declare reduction construct initializer.
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
Definition: SemaExpr.cpp:21731
StmtResult ActOnOpenMPMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp masked' after parsing of the.
OMPClause * ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'use' clause.
OMPClause * ActOnOpenMPFullClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-form 'full' clauses.
bool inTemplateInstantiation() const
Determine whether we are currently performing template instantiation.
Definition: Sema.h:10722
void ActOnOpenMPEndDeclareVariant()
Handle a omp end declare variant.
@ TryCapture_ExplicitByVal
Definition: Sema.h:5460
StmtResult ActOnOpenMPTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute' after parsing of the associated statement.
@ AA_Initializing
Definition: Sema.h:5384
@ AA_Converting
Definition: Sema.h:5383
@ AA_Casting
Definition: Sema.h:5386
OMPClause * ActOnOpenMPFailClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'fail' clause.
OMPClause * ActOnOpenMPCompareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'compare' clause.
bool areMultiversionVariantFunctionsCompatible(const FunctionDecl *OldFD, const FunctionDecl *NewFD, const PartialDiagnostic &NoProtoDiagID, const PartialDiagnosticAt &NoteCausedDiagIDAt, const PartialDiagnosticAt &NoSupportDiagIDAt, const PartialDiagnosticAt &DiffDiagIDAt, bool TemplatesSupported, bool ConstexprSupported, bool CLinkageMayDiffer)
Checks if the variant/multiversion functions are compatible.
Definition: SemaDecl.cpp:11285
OMPClause * ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'detach' clause.
ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, Expr *CondExpr, Expr *LHSExpr, Expr *RHSExpr)
ActOnConditionalOp - Parse a ?: operation.
Definition: SemaExpr.cpp:9709
RedeclarationKind forRedeclarationInCurContext() const
Definition: Sema.h:7701
StmtResult ActOnOpenMPTargetParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPLinearClause(ArrayRef< Expr * > VarList, Expr *Step, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind, SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation StepModifierLoc, SourceLocation EndLoc)
Called on well-formed 'linear' clause.
OMPClause * ActOnOpenMPXAttributeClause(ArrayRef< const Attr * > Attrs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_attribute' clause.
void ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, SmallVectorImpl< FunctionDecl * > &Bases)
The declarator D defines a function in the scope S which is nested in an omp begin/end declare varian...
DeclGroupPtrTy ActOnOpenMPDeclareMapperDirective(Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType, SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS, Expr *MapperVarRef, ArrayRef< OMPClause * > Clauses, Decl *PrevDeclInScope=nullptr)
Called on start of '#pragma omp declare mapper'.
StmtResult ActOnOpenMPTargetParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel for simd' after parsing of the associated statemen...
NamedDecl * lookupOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)
Searches for the provided declaration name for OpenMP declare target directive.
StmtResult ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp section' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid)
Called at the end of '#pragma omp declare reduction'.
void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI)
Handle a omp begin declare variant.
bool isCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind=CompleteTypeKind::Default)
Definition: Sema.h:11943
VarDecl * isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo=false, unsigned StopAt=0)
Check if the specified variable is used in one of the private clauses (private, firstprivate,...
@ CTK_ErrorRecovery
Definition: Sema.h:7859
@ Private
The private module fragment, between 'module :private;' and the end of the translation unit.
Definition: Sema.h:786
void setFunctionHasBranchProtectedScope()
Definition: Sema.cpp:2316
OMPClause * ActOnOpenMPCopyprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyprivate' clause.
OMPClause * ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depobj' pseudo clause.
QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare mapper' construct.
OMPClause * ActOnOpenMPThreadLimitClause(Expr *ThreadLimit, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'thread_limit' clause.
bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called on the start of target region i.e. '#pragma omp declare target'.
const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective()
Called at the end of target region i.e. '#pragma omp end declare target'.
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
OMPClause * ActOnOpenMPPrivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'private' clause.
StmtResult ActOnOpenMPDispatchDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp dispatch' after parsing of the.
OMPClause * ActOnOpenMPToClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers=std::nullopt)
Called on well-formed 'to' clause.
std::pair< StringRef, QualType > CapturedParamNameType
Definition: Sema.h:8934
OMPClause * ActOnOpenMPNontemporalClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nontemporal' clause.
ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS=nullptr, bool isClassName=false, bool HasTrailingDot=false, ParsedType ObjectType=nullptr, bool IsCtorOrDtorName=false, bool WantNontrivialTypeSourceInfo=false, bool IsClassTemplateDeductionContext=true, ImplicitTypenameContext AllowImplicitTypename=ImplicitTypenameContext::No, IdentifierInfo **CorrectedII=nullptr)
If the identifier refers to a type name within this scope, return the declaration of that type.
Definition: SemaDecl.cpp:286
OMPClause * ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
bool isInOpenMPTargetExecutionDirective() const
Return true inside OpenMP target region.
OMPClause * ActOnOpenMPTaskReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=std::nullopt)
Called on well-formed 'task_reduction' clause.
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
Definition: SemaExpr.cpp:5898
StmtResult ActOnOpenMPTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'threads' clause.
OMPClause * ActOnOpenMPAtomicDefaultMemOrderClause(OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'atomic_default_mem_order' clause.
@ PotentiallyEvaluated
The current expression is potentially evaluated at run time, which means that code may be generated t...
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
void ActOnOpenMPDeclareTargetInitializer(Decl *D)
Adds OMPDeclareTargetDeclAttr to referenced variables in declare target directive.
TypeSourceInfo * GetTypeForDeclarator(Declarator &D)
GetTypeForDeclarator - Convert the type for the specified declarator to Type instances.
Definition: SemaType.cpp:6102
void diagnoseTypo(const TypoCorrection &Correction, const PartialDiagnostic &TypoDiag, bool ErrorRecovery=true)
OMPClause * ActOnOpenMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier, Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'grainsize' clause.
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
Definition: SemaStmt.cpp:75
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Definition: SemaType.cpp:9249
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
Definition: Sema.h:1002
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
Definition: SemaInternal.h:24
StmtResult ActOnOpenMPTargetTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams loop' after parsing of the associated statement.
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
OMPClause * ActOnOpenMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'read' clause.
StmtResult ActOnOpenMPTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'doacross' clause.
StmtResult ActOnOpenMPSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp sections' after parsing of the associated statement.
void StartOpenMPDSABlock(OpenMPDirectiveKind K, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc)
Called on start of new data sharing attribute block.
void DiscardCleanupsInEvaluationContext()
Definition: SemaExpr.cpp:18709
StmtResult ActOnOpenMPErrorDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, bool InExContext=true)
Called on well-formed '#pragma omp error'.
void PushDeclContext(Scope *S, DeclContext *DC)
Set the current declaration context until it gets popped.
Definition: SemaDecl.cpp:1324
StmtResult ActOnOpenMPParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for' after parsing of the associated statement.
bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, unsigned OpenMPCaptureLevel) const
Return true if the provided declaration VD should be captured by reference.
OMPClause * ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'num_tasks' clause.
MemberExpr * BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec *SS, SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl, bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK, ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs=nullptr)
llvm::SmallDenseMap< const ValueDecl *, const Expr *, 4 > VarsWithInheritedDSAType
Definition: Sema.h:13745
StmtResult ActOnOpenMPTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPPartialClause(Expr *FactorExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'partial' clauses.
OMPClause * ActOnOpenMPSafelenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'safelen' clause.
ExprResult DefaultFunctionArrayConversion(Expr *E, bool Diagnose=true)
DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
Definition: SemaExpr.cpp:521
ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK, ExprObjectKind OK, SourceLocation Loc)
StmtResult ActOnOpenMPAtomicDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp atomic' after parsing of the associated statement.
void PopDeclContext()
Definition: SemaDecl.cpp:1331
void EndOpenMPDSABlock(Stmt *CurDirective)
Called on end of data sharing attribute block.
OMPClause * ActOnOpenMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nogroup' clause.
StmtResult ActOnOpenMPParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel' after parsing of the associated statement.
void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S, bool ConsiderLinkage, bool AllowInlineNamespace)
Filters out lookup results that don't fall within the given scope as determined by isDeclInScope.
Definition: SemaDecl.cpp:1597
StmtResult ActOnOpenMPTileDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp tile' after parsing of its clauses and the associated statement.
StmtResult ActOnOpenMPScopeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scope' after parsing of the associated statement.
StmtResult ActOnOpenMPParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel loop' after parsing of the associated statement.
void ActOnUninitializedDecl(Decl *dcl)
Definition: SemaDecl.cpp:14057
StmtResult ActOnOpenMPTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop' after parsing of the associated statement.
OMPClause * ActOnOpenMPMessageClause(Expr *MS, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'message' clause.
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
Definition: SemaDecl.cpp:13503
StmtResult ActOnOpenMPTeamsDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPLastprivateClause(ArrayRef< Expr * > VarList, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'lastprivate' clause.
void ActOnOpenMPAssumesDirective(SourceLocation Loc, OpenMPDirectiveKind DKind, ArrayRef< std::string > Assumptions, bool SkippedClauses)
Called on well-formed '#pragma omp [begin] assume[s]'.
OMPClause * ActOnOpenMPSizesClause(ArrayRef< Expr * > SizeExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'sizes' clause.
void EndOpenMPClause()
End analysis of clauses.
bool isOpenMPRebuildMemberExpr(ValueDecl *D)
The member expression(this->fd) needs to be rebuilt in the template instantiation to generate private...
StmtResult ActOnOpenMPGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp loop' after parsing of the associated statement.
SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD=nullptr)
Definition: Sema.cpp:1894
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr)
Definition: SemaExpr.cpp:16135
StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskyield'.
OMPClause * ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'reverse_offload' clause.
ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr)
CreateBuiltinBinOp - Creates a new built-in binary operation with operator Opc at location TokLoc.
Definition: SemaExpr.cpp:15604
StmtResult ActOnOpenMPTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for simd' after parsing of the associate...
bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base)
Determine whether the type Derived is a C++ class that is derived from the type Base.
sema::FunctionScopeInfo * getEnclosingFunction() const
Definition: Sema.cpp:2346
StmtResult ActOnOpenMPMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop' after parsing of the associated statement.
sema::CapturedRegionScopeInfo * getCurCapturedRegion()
Retrieve the current captured region, if any.
Definition: Sema.cpp:2713
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
std::optional< std::pair< FunctionDecl *, Expr * > > checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, OMPTraitInfo &TI, unsigned NumAppendArgs, SourceRange SR)
Checks '#pragma omp declare variant' variant function and original functions after parsing of the ass...
bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation=false, bool ForceNoCPlusPlus=false)
Perform unqualified name lookup starting from a given scope.
static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo=nullptr)
Definition: SemaType.cpp:3213
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)
Finish current declare reduction construct initializer.
OMPClause * ActOnOpenMPDefaultmapClause(OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'defaultmap' clause.
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
Definition: SemaStmt.cpp:411
StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt)
Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to an OpenMP loop directive.
StmtResult ActOnOpenMPParallelMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop' after parsing of the associated statemen...
StmtResult ActOnOpenMPTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for' after parsing of the associated sta...
OMPClause * ActOnOpenMPInclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'inclusive' clause.
StmtResult ActOnOpenMPParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for simd' after parsing of the associated statement.
OpenMPClauseKind isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, unsigned CapLevel) const
Check if the specified variable is used in 'private' clause.
FullExprArg MakeFullExpr(Expr *Arg)
Definition: Sema.h:6059
OMPClause * ActOnOpenMPCollapseClause(Expr *NumForLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'collapse' clause.
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
Definition: Sema.h:1021
bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified variable is captured by 'target' directive.
OMPRequiresDecl * CheckOMPRequiresDecl(SourceLocation Loc, ArrayRef< OMPClause * > Clauses)
Check restrictions on Requires directive.
OMPClause * ActOnOpenMPIsDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'is_device_ptr' clause.
StmtResult ActOnOpenMPTargetDataDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target data' after parsing of the associated statement.
OMPClause * ActOnOpenMPAllocatorClause(Expr *Allocator, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocator' clause.
OMPClause * ActOnOpenMPFromClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers=std::nullopt)
Called on well-formed 'from' clause.
StmtResult ActOnOpenMPSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp simd' after parsing of the associated statement.
void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called once a target context is completed, that can be when a '#pragma omp end declare target' was en...
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition: Sema.h:6967
OMPClause * ActOnOpenMPRelaxedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'relaxed' clause.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
void setBegin(SourceLocation b)
SourceLocation getBegin() const
void setEnd(SourceLocation e)
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Definition: StmtVisitor.h:185
Stmt - This represents one statement.
Definition: Stmt.h:84
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Stmt.cpp:350
child_range children()
Definition: Stmt.cpp:287
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:326
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical, bool ProfileLambdaExpr=false) const
Produce a unique representation of the given statement.
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
Definition: Stmt.cpp:197
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:338
bool isTLSSupported() const
Whether the target supports thread-local storage.
Definition: TargetInfo.h:1525
bool isVLASupported() const
Whether target supports variable-length arrays.
Definition: TargetInfo.h:1536
A semantic tree transformation that allows one to transform one abstract syntax tree into another.
Represents a declaration of a type.
Definition: Decl.h:3357
A container of type source information.
Definition: Type.h:6873
QualType getType() const
Return the type wrapped by this type source info.
Definition: Type.h:6884
The base class of the type hierarchy.
Definition: Type.h:1606
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1819
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
Definition: Type.cpp:1958
bool isArrayType() const
Definition: Type.h:7220
bool isArithmeticType() const
Definition: Type.cpp:2218
bool isPointerType() const
Definition: Type.h:7154
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: Type.h:7479
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:7724
bool isReferenceType() const
Definition: Type.h:7166
bool isEnumeralType() const
Definition: Type.h:7248
bool isScalarType() const
Definition: Type.h:7538
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:651
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
Definition: Type.cpp:2173
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition: Type.h:2428
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition: Type.h:7412
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2420
bool isAnyComplexType() const
Definition: Type.h:7252
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
Definition: Type.h:2094
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition: Type.cpp:2123
bool isFunctionProtoType() const
Definition: Type.h:2263
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
Definition: Type.h:7580
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition: Type.h:2438
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition: Type.h:7710
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition: Type.cpp:2299
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
Definition: Type.h:7674
bool isFunctionType() const
Definition: Type.h:7150
bool isStructureOrClassType() const
Definition: Type.cpp:607
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:2203
bool isFloatingType() const
Definition: Type.cpp:2186
bool isAnyPointerType() const
Definition: Type.h:7158
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:7657
bool isRecordType() const
Definition: Type.h:7244
bool isUnionType() const
Definition: Type.cpp:621
bool isFunctionNoProtoType() const
Definition: Type.h:2262
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition: Type.cpp:1823
Simple class containing the result of Sema::CorrectTypo.
NamedDecl * getCorrectionDecl() const
Gets the pointer to the declaration of the typo correction.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition: Expr.h:2182
Expr * getSubExpr() const
Definition: Expr.h:2227
Opcode getOpcode() const
Definition: Expr.h:2222
static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, UnresolvedSetIterator Begin, UnresolvedSetIterator End)
Definition: ExprCXX.cpp:373
void append(iterator I, iterator E)
void addDecl(NamedDecl *D)
Definition: UnresolvedSet.h:91
A set of unresolved declarations.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:706
void setType(QualType newType)
Definition: Decl.h:718
QualType getType() const
Definition: Decl.h:717
Represents a variable declaration or definition.
Definition: Decl.h:918
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition: Decl.cpp:2148
bool isFunctionOrMethodVarDecl() const
Similar to isLocalVarDecl, but excludes variables declared in blocks.
Definition: Decl.h:1251
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition: Decl.h:1546
TLSKind getTLSKind() const
Definition: Decl.cpp:2165
bool hasInit() const
Definition: Decl.cpp:2395
void setInitStyle(InitializationStyle Style)
Definition: Decl.h:1429
InitializationStyle getInitStyle() const
The style of initialization for this declaration.
Definition: Decl.h:1443
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
Definition: Decl.cpp:2257
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:2187
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition: Decl.cpp:2254
@ CInit
C-style initialization with assignment.
Definition: Decl.h:923
@ CallInit
Call-style initialization (C++98)
Definition: Decl.h:926
bool isStaticDataMember() const
Determines whether this is a static data member.
Definition: Decl.h:1267
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition: Decl.h:1210
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition: Decl.h:1192
bool isFileVarDecl() const
Returns true for file scoped variable declaration.
Definition: Decl.h:1326
const Expr * getInit() const
Definition: Decl.h:1352
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition: Decl.h:1168
@ TLS_None
Not a TLS variable.
Definition: Decl.h:938
void setInit(Expr *I)
Definition: Decl.cpp:2454
@ DeclarationOnly
This declaration is only a declaration.
Definition: Decl.h:1279
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
Definition: Decl.h:1237
bool isDirectInit() const
Whether the initializer is a direct-initializer (list or call).
Definition: Decl.h:1448
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
Definition: Decl.h:1213
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition: Decl.h:1152
bool isUsableInConstantExpressions(const ASTContext &C) const
Determine whether this variable's value can be used in a constant expression, according to the releva...
Definition: Decl.cpp:2505
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
Definition: Decl.h:1246
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Definition: Decl.h:1342
Directive - Abstract class representing a parsed verify directive.
Retains information about a captured region.
Definition: ScopeInfo.h:810
CapturedDecl * TheCapturedDecl
The CapturedDecl for this statement.
Definition: ScopeInfo.h:813
Retains information about a function, method, or block that is currently being parsed.
Definition: ScopeInfo.h:104
SmallVector< CompoundScopeInfo, 4 > CompoundScopes
The stack of currently active compound statement scopes in the function.
Definition: ScopeInfo.h:228
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
Definition: AttrIterator.h:33
Defines the clang::TargetInfo interface.
bool LE(InterpState &S, CodePtr OpPC)
Definition: Interp.h:871
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
@ Self
'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
@ Device
'device' clause, allowed on the 'update' construct.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
Definition: OperatorKinds.h:21
@ OO_None
Not an overloaded operator.
Definition: OperatorKinds.h:22
@ NUM_OVERLOADED_OPERATORS
Definition: OperatorKinds.h:26
bool isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a teams directive in the outermost n...
bool checkFailClauseParameter(OpenMPClauseKind FailClauseParameter)
Checks if the parameter to the fail clause in "#pragma atomic compare fail" is restricted only to mem...
@ CPlusPlus
Definition: LangStandard.h:54
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
bool isOpenMPLoopTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive.
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
Definition: OpenMPKinds.h:24
OpenMPDefaultmapClauseModifier
OpenMP modifiers for 'defaultmap' clause.
Definition: OpenMPKinds.h:118
@ OMPC_DEFAULTMAP_MODIFIER_last
Definition: OpenMPKinds.h:123
@ OMPC_DEFAULTMAP_MODIFIER_unknown
Definition: OpenMPKinds.h:119
OpenMPOrderClauseModifier
OpenMP modifiers for 'order' clause.
Definition: OpenMPKinds.h:171
@ OMPC_ORDER_MODIFIER_unknown
Definition: OpenMPKinds.h:172
@ OMPC_ORDER_MODIFIER_last
Definition: OpenMPKinds.h:175
ExprObjectKind
A further classification of the kind of object referenced by an l-value or x-value.
Definition: Specifiers.h:146
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition: Specifiers.h:148
OpenMPAtClauseKind
OpenMP attributes for 'at' clause.
Definition: OpenMPKinds.h:135
@ OMPC_AT_unknown
Definition: OpenMPKinds.h:138
Expr * AssertSuccess(ExprResult R)
Definition: Ownership.h:274
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
Definition: Lambda.h:37
@ LCK_This
Capturing the *this object by reference.
Definition: Lambda.h:34
OpenMPReductionClauseModifier
OpenMP modifiers for 'reduction' clause.
Definition: OpenMPKinds.h:186
@ OMPC_REDUCTION_unknown
Definition: OpenMPKinds.h:189
BinaryOperatorKind
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
Definition: OpenMPKinds.h:38
@ OMPC_SCHEDULE_MODIFIER_last
Definition: OpenMPKinds.h:43
@ OMPC_SCHEDULE_MODIFIER_unknown
Definition: OpenMPKinds.h:39
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
Definition: OpenMPKinds.h:27
const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)
@ CR_Default
Definition: CapturedStmt.h:17
@ CR_OpenMP
Definition: CapturedStmt.h:19
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
bool isOpenMPPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of private clauses like 'private', 'firstprivate',...
@ SC_Auto
Definition: Specifiers.h:253
@ SC_Register
Definition: Specifiers.h:254
@ SC_None
Definition: Specifiers.h:247
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
Definition: OpenMPKinds.h:103
@ OMPC_DIST_SCHEDULE_unknown
Definition: OpenMPKinds.h:106
for(auto typeArg :T->getTypeArgsAsWritten())
static constexpr StringRef getOpenMPVariantManglingSeparatorStr()
OpenMP variants are mangled early based on their OpenMP context selector.
Definition: Decl.h:5012
OpenMPDoacrossClauseModifier
OpenMP dependence types for 'doacross' clause.
Definition: OpenMPKinds.h:219
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
static constexpr unsigned NumberOfOMPMapClauseModifiers
Number of allowed map-type-modifiers.
Definition: OpenMPKinds.h:87
ExprResult ExprEmpty()
Definition: Ownership.h:271
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
StmtResult StmtError()
Definition: Ownership.h:265
@ SD_Static
Static storage duration.
Definition: Specifiers.h:327
@ Parameter
The parameter type of a method or function.
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
Definition: OpenMPKinds.h:200
@ OMPC_BIND_unknown
Definition: OpenMPKinds.h:203
OpenMPLastprivateModifier
OpenMP 'lastprivate' clause modifier.
Definition: OpenMPKinds.h:157
@ OMPC_LASTPRIVATE_unknown
Definition: OpenMPKinds.h:160
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
Definition: OpenMPKinds.h:54
@ OMPC_DEPEND_unknown
Definition: OpenMPKinds.h:58
OpenMPGrainsizeClauseModifier
Definition: OpenMPKinds.h:206
@ OMPC_GRAINSIZE_unknown
Definition: OpenMPKinds.h:209
OpenMPNumTasksClauseModifier
Definition: OpenMPKinds.h:212
@ OMPC_NUMTASKS_unknown
Definition: OpenMPKinds.h:215
ActionResult< Expr * > ExprResult
Definition: Ownership.h:248
ExprResult ExprError()
Definition: Ownership.h:264
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
Definition: OpenMPKinds.h:142
@ OMPC_SEVERITY_unknown
Definition: OpenMPKinds.h:145
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
static constexpr unsigned NumberOfOMPMotionModifiers
Number of allowed motion-modifiers.
Definition: OpenMPKinds.h:99
OpenMPMotionModifierKind
OpenMP modifier kind for 'to' or 'from' clause.
Definition: OpenMPKinds.h:91
@ OMPC_MOTION_MODIFIER_unknown
Definition: OpenMPKinds.h:95
OpenMPDefaultmapClauseKind
OpenMP attributes for 'defaultmap' clause.
Definition: OpenMPKinds.h:110
@ OMPC_DEFAULTMAP_unknown
Definition: OpenMPKinds.h:114
bool isOpenMPThreadPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of threadprivate clauses like 'threadprivate',...
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
Definition: OpenMPKinds.h:62
@ OMPC_LINEAR_unknown
Definition: OpenMPKinds.h:66
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
Definition: Specifiers.h:129
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition: Specifiers.h:132
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition: Specifiers.h:136
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPAtomicDefaultMemOrderClauseKind
OpenMP attributes for 'atomic_default_mem_order' clause.
Definition: OpenMPKinds.h:127
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
Definition: OpenMPKinds.h:131
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
ActionResult< Decl * > DeclResult
Definition: Ownership.h:254
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T -> getSizeExpr()))
OpenMPDeviceClauseModifier
OpenMP modifiers for 'device' clause.
Definition: OpenMPKinds.h:47
@ OMPC_DEVICE_unknown
Definition: OpenMPKinds.h:50
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
Definition: OpenMPKinds.h:78
@ OMPC_MAP_MODIFIER_unknown
Definition: OpenMPKinds.h:79
bool isOpenMPCombinedParallelADirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a combined construct for which the first construct is a parallel...
bool isOpenMPNestingDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a distribute directive in the outerm...
OpenMPOrderClauseKind
OpenMP attributes for 'order' clause.
Definition: OpenMPKinds.h:164
@ OMPC_ORDER_unknown
Definition: OpenMPKinds.h:167
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
Definition: OpenMPKinds.h:30
@ OMPC_SCHEDULE_unknown
Definition: OpenMPKinds.h:34
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
Definition: Specifiers.h:120
@ AS_public
Definition: Specifiers.h:121
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Definition: OpenMPKinds.h:70
@ OMPC_MAP_unknown
Definition: OpenMPKinds.h:74
unsigned long uint64_t
#define false
Definition: stdbool.h:22
#define bool
Definition: stdbool.h:20
unsigned operator()(argument_type DK)
OpenMPDirectiveKind argument_type
const Expr * RHS
The original right-hand side.
Definition: ExprCXX.h:310
BinaryOperatorKind Opcode
The original opcode, prior to rewriting.
Definition: ExprCXX.h:306
const Expr * LHS
The original left-hand side.
Definition: ExprCXX.h:308
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
SourceLocation getLoc() const
getLoc - Returns the main location of the declaration name.
DeclarationName getName() const
getName - Returns the embedded declaration name.
void setLoc(SourceLocation L)
setLoc - Sets the main location of the declaration name.
void setName(DeclarationName N)
setName - Sets the embedded declaration name.
SourceLocation getBeginLoc() const
getBeginLoc - Retrieve the location of the first token.
std::string getAsString() const
getAsString - Retrieve the human-readable string for this name.
SourceLocation getEndLoc() const LLVM_READONLY
EvalResult is a struct with detailed info about an evaluated expression.
Definition: Expr.h:642
APValue Val
Val - This is the value the expression can be folded to.
Definition: Expr.h:644
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
Definition: Expr.h:630
Extra information about a function prototype.
Definition: Type.h:4278
llvm::SmallVector< Expr *, 4 > PreferTypes
Definition: OpenMPKinds.h:232
Expr * ParForInDistCond
'omp parallel for' loop condition used when composed with 'omp distribute' in the same construct and ...
Definition: StmtOpenMP.h:751
Expr * LB
DistributeLowerBound - used when composing 'omp distribute' with 'omp for' in a same construct.
Definition: StmtOpenMP.h:725
Expr * Init
Distribute loop iteration variable init used when composing 'omp distribute' with 'omp for' in a same...
Definition: StmtOpenMP.h:735
Expr * NUB
Update of UpperBound for statically scheduled omp loops for outer loop in combined constructs (e....
Definition: StmtOpenMP.h:744
Expr * EUB
DistributeEnsureUpperBound - used when composing 'omp distribute' with 'omp for' in a same construct,...
Definition: StmtOpenMP.h:731
Expr * UB
DistributeUpperBound - used when composing 'omp distribute' with 'omp for' in a same construct.
Definition: StmtOpenMP.h:728
Expr * NLB
Update of LowerBound for statically scheduled omp loops for outer loop in combined constructs (e....
Definition: StmtOpenMP.h:741
Expr * DistCond
Distribute Loop condition used when composing 'omp distribute' with 'omp for' in a same construct whe...
Definition: StmtOpenMP.h:747
Expr * Cond
Distribute Loop condition used when composing 'omp distribute' with 'omp for' in a same construct.
Definition: StmtOpenMP.h:738
The expressions built for the OpenMP loop CodeGen for the whole collapsed loop nest.
Definition: StmtOpenMP.h:756
Expr * LastIteration
Loop last iteration number.
Definition: StmtOpenMP.h:760
SmallVector< Expr *, 4 > DependentInits
List of initializers required for the generation of the non-rectangular loops.
Definition: StmtOpenMP.h:818
SmallVector< Expr *, 4 > Inits
Expressions for loop counters inits for CodeGen.
Definition: StmtOpenMP.h:808
Expr * PrevEUB
PrevEUB - expression similar to EUB but to be used when loop scheduling uses PrevLB and PrevUB (e....
Definition: StmtOpenMP.h:802
Expr * DistInc
DistInc - increment expression for distribute loop when found combined with a further loop level (e....
Definition: StmtOpenMP.h:796
Expr * IL
IsLastIteration - local flag variable passed to runtime.
Definition: StmtOpenMP.h:774
SmallVector< Expr *, 4 > PrivateCounters
PrivateCounters Loop counters.
Definition: StmtOpenMP.h:806
bool builtAll()
Check if all the expressions are built (does not check the worksharing ones).
Definition: StmtOpenMP.h:830
Expr * CalcLastIteration
Calculation of last iteration.
Definition: StmtOpenMP.h:764
SmallVector< Expr *, 4 > Updates
Expressions for loop counters update for CodeGen.
Definition: StmtOpenMP.h:810
Expr * ST
Stride - local variable passed to runtime.
Definition: StmtOpenMP.h:780
SmallVector< Expr *, 4 > Finals
Final loop counter values for GodeGen.
Definition: StmtOpenMP.h:812
SmallVector< Expr *, 4 > FinalsConditions
List of final conditions required for the generation of the non-rectangular loops.
Definition: StmtOpenMP.h:821
Expr * PreCond
Loop pre-condition.
Definition: StmtOpenMP.h:766
Stmt * PreInits
Init statement for all captured expressions.
Definition: StmtOpenMP.h:823
Expr * IterationVarRef
Loop iteration variable.
Definition: StmtOpenMP.h:758
Expr * NumIterations
Loop number of iterations.
Definition: StmtOpenMP.h:762
SmallVector< Expr *, 4 > Counters
Counters Loop counters.
Definition: StmtOpenMP.h:804
Expr * NLB
Update of LowerBound for statically scheduled 'omp for' loops.
Definition: StmtOpenMP.h:784
Expr * PrevUB
PreviousUpperBound - local variable passed to runtime in the enclosing schedule or null if that does ...
Definition: StmtOpenMP.h:792
DistCombinedHelperExprs DistCombinedFields
Expressions used when combining OpenMP loop pragmas.
Definition: StmtOpenMP.h:826
void clear(unsigned Size)
Initialize all the fields to null.
Definition: StmtOpenMP.h:840
Expr * EUB
EnsureUpperBound – expression UB = min(UB, NumIterations).
Definition: StmtOpenMP.h:782
Expr * UB
UpperBound - local variable passed to runtime.
Definition: StmtOpenMP.h:778
Expr * NUB
Update of UpperBound for statically scheduled 'omp for' loops.
Definition: StmtOpenMP.h:786
Expr * LB
LowerBound - local variable passed to runtime.
Definition: StmtOpenMP.h:776
Expr * PrevLB
PreviousLowerBound - local variable passed to runtime in the enclosing schedule or null if that does ...
Definition: StmtOpenMP.h:789
SmallVector< Expr *, 4 > DependentCounters
List of counters required for the generation of the non-rectangular loops.
Definition: StmtOpenMP.h:815
Expr * Init
Loop iteration variable init.
Definition: StmtOpenMP.h:770
Data for list of allocators.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Expr * AllocatorTraits
Allocator traits.
This structure contains most locations needed for by an OMPVarListClause.
Definition: OpenMPClause.h:259
SourceLocation StartLoc
Starting location of the clause (the clause keyword).
Definition: OpenMPClause.h:261
SourceLocation LParenLoc
Location of '('.
Definition: OpenMPClause.h:263
SourceLocation EndLoc
Ending location of the clause.
Definition: OpenMPClause.h:265
std::optional< Expr * > Indirect
The directive with indirect clause.
Definition: Sema.h:13651
OMPDeclareTargetDeclAttr::DevTypeTy DT
The 'device_type' as parsed from the clause.
Definition: Sema.h:13645
OpenMPDirectiveKind Kind
The directive kind, begin declare target or declare target.
Definition: Sema.h:13648
SourceLocation Loc
The directive location.
Definition: Sema.h:13654
llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped
Explicitly listed variables and functions in a 'to' or 'link' clause.
Definition: Sema.h:13642
Data used for processing a list of variables in OpenMP clauses.
Definition: Sema.h:14419
Data for list of allocators.
Definition: Sema.h:14614
SourceLocation RParenLoc
Definition: Sema.h:14620
Expr * Allocator
Allocator.
Definition: Sema.h:14616
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Definition: Sema.h:14620
Expr * AllocatorTraits
Allocator traits.
Definition: Sema.h:14618
Clang specific specialization of the OMPContext to lookup target features.