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
15#include "TreeTransform.h"
19#include "clang/AST/Decl.h"
20#include "clang/AST/DeclCXX.h"
23#include "clang/AST/StmtCXX.h"
33#include "clang/Sema/Lookup.h"
35#include "clang/Sema/Scope.h"
37#include "clang/Sema/Sema.h"
39#include "llvm/ADT/IndexedMap.h"
40#include "llvm/ADT/PointerEmbeddedInt.h"
41#include "llvm/ADT/STLExtras.h"
42#include "llvm/ADT/SmallSet.h"
43#include "llvm/ADT/StringExtras.h"
44#include "llvm/Frontend/OpenMP/OMPAssume.h"
45#include "llvm/Frontend/OpenMP/OMPConstants.h"
46#include <optional>
47#include <set>
48
49using namespace clang;
50using namespace llvm::omp;
51
52//===----------------------------------------------------------------------===//
53// Stack of data-sharing attributes for variables
54//===----------------------------------------------------------------------===//
55
57 Sema &SemaRef, Expr *E,
59 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
60
61namespace {
62/// Default data sharing attributes, which can be applied to directive.
63enum DefaultDataSharingAttributes {
64 DSA_unspecified = 0, /// Data sharing attribute not specified.
65 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
66 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
67 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
68 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
69};
70
71/// Stack for tracking declarations used in OpenMP directives and
72/// clauses and their data-sharing attributes.
73class DSAStackTy {
74public:
75 struct DSAVarData {
76 OpenMPDirectiveKind DKind = OMPD_unknown;
77 OpenMPClauseKind CKind = OMPC_unknown;
78 unsigned Modifier = 0;
79 const Expr *RefExpr = nullptr;
80 DeclRefExpr *PrivateCopy = nullptr;
81 SourceLocation ImplicitDSALoc;
82 bool AppliedToPointee = false;
83 DSAVarData() = default;
84 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
85 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
86 SourceLocation ImplicitDSALoc, unsigned Modifier,
87 bool AppliedToPointee)
88 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
89 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
90 AppliedToPointee(AppliedToPointee) {}
91 };
92 using OperatorOffsetTy =
94 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
95 /// Kind of the declaration used in the uses_allocators clauses.
96 enum class UsesAllocatorsDeclKind {
97 /// Predefined allocator
98 PredefinedAllocator,
99 /// User-defined allocator
100 UserDefinedAllocator,
101 /// The declaration that represent allocator trait
102 AllocatorTrait,
103 };
104
105private:
106 struct DSAInfo {
107 OpenMPClauseKind Attributes = OMPC_unknown;
108 unsigned Modifier = 0;
109 /// Pointer to a reference expression and a flag which shows that the
110 /// variable is marked as lastprivate(true) or not (false).
111 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
112 DeclRefExpr *PrivateCopy = nullptr;
113 /// true if the attribute is applied to the pointee, not the variable
114 /// itself.
115 bool AppliedToPointee = false;
116 };
117 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
118 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
119 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
120 using LoopControlVariablesMapTy =
121 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
122 /// Struct that associates a component with the clause kind where they are
123 /// found.
124 struct MappedExprComponentTy {
126 OpenMPClauseKind Kind = OMPC_unknown;
127 };
128 using MappedExprComponentsTy =
129 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
130 using CriticalsWithHintsTy =
131 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
132 struct ReductionData {
133 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
134 SourceRange ReductionRange;
135 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
136 ReductionData() = default;
137 void set(BinaryOperatorKind BO, SourceRange RR) {
138 ReductionRange = RR;
139 ReductionOp = BO;
140 }
141 void set(const Expr *RefExpr, SourceRange RR) {
142 ReductionRange = RR;
143 ReductionOp = RefExpr;
144 }
145 };
146 using DeclReductionMapTy =
147 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
148 struct DefaultmapInfo {
149 OpenMPDefaultmapClauseModifier ImplicitBehavior =
151 SourceLocation SLoc;
152 DefaultmapInfo() = default;
154 : ImplicitBehavior(M), SLoc(Loc) {}
155 };
156
157 struct SharingMapTy {
158 DeclSAMapTy SharingMap;
159 DeclReductionMapTy ReductionMap;
160 UsedRefMapTy AlignedMap;
161 UsedRefMapTy NontemporalMap;
162 MappedExprComponentsTy MappedExprComponents;
163 LoopControlVariablesMapTy LCVMap;
164 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
165 SourceLocation DefaultAttrLoc;
166 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1];
167 OpenMPDirectiveKind Directive = OMPD_unknown;
168 /// GenericLoopDirective with bind clause is mapped to other directives,
169 /// like for, distribute and simd. Presently, set MappedDirective to
170 /// OMPLoop. This may also be used in a similar way for other constructs.
171 OpenMPDirectiveKind MappedDirective = OMPD_unknown;
172 DeclarationNameInfo DirectiveName;
173 Scope *CurScope = nullptr;
174 DeclContext *Context = nullptr;
175 SourceLocation ConstructLoc;
176 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
177 /// get the data (loop counters etc.) about enclosing loop-based construct.
178 /// This data is required during codegen.
179 DoacrossClauseMapTy DoacrossDepends;
180 /// First argument (Expr *) contains optional argument of the
181 /// 'ordered' clause, the second one is true if the regions has 'ordered'
182 /// clause, false otherwise.
183 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
184 bool RegionHasOrderConcurrent = false;
185 unsigned AssociatedLoops = 1;
186 bool HasMutipleLoops = false;
187 const Decl *PossiblyLoopCounter = nullptr;
188 bool NowaitRegion = false;
189 bool UntiedRegion = false;
190 bool CancelRegion = false;
191 bool LoopStart = false;
192 bool BodyComplete = false;
193 SourceLocation PrevScanLocation;
194 SourceLocation PrevOrderedLocation;
195 SourceLocation InnerTeamsRegionLoc;
196 /// Reference to the taskgroup task_reduction reference expression.
197 Expr *TaskgroupReductionRef = nullptr;
198 llvm::DenseSet<QualType> MappedClassesQualTypes;
199 SmallVector<Expr *, 4> InnerUsedAllocators;
200 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
201 /// List of globals marked as declare target link in this target region
202 /// (isOpenMPTargetExecutionDirective(Directive) == true).
203 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
204 /// List of decls used in inclusive/exclusive clauses of the scan directive.
205 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
206 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
207 UsesAllocatorsDecls;
208 /// Data is required on creating capture fields for implicit
209 /// default first|private clause.
210 struct ImplicitDefaultFDInfoTy {
211 /// Field decl.
212 const FieldDecl *FD = nullptr;
213 /// Nesting stack level
214 size_t StackLevel = 0;
215 /// Capture variable decl.
216 VarDecl *VD = nullptr;
217 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
218 VarDecl *VD)
219 : FD(FD), StackLevel(StackLevel), VD(VD) {}
220 };
221 /// List of captured fields
223 ImplicitDefaultFirstprivateFDs;
224 Expr *DeclareMapperVar = nullptr;
225 SmallVector<VarDecl *, 16> IteratorVarDecls;
226 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
227 Scope *CurScope, SourceLocation Loc)
228 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
229 ConstructLoc(Loc) {}
230 SharingMapTy() = default;
231 };
232
233 using StackTy = SmallVector<SharingMapTy, 4>;
234
235 /// Stack of used declaration and their data-sharing attributes.
236 DeclSAMapTy Threadprivates;
237 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
239 /// true, if check for DSA must be from parent directive, false, if
240 /// from current directive.
241 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
242 Sema &SemaRef;
243 bool ForceCapturing = false;
244 /// true if all the variables in the target executable directives must be
245 /// captured by reference.
246 bool ForceCaptureByReferenceInTargetExecutable = false;
247 CriticalsWithHintsTy Criticals;
248 unsigned IgnoredStackElements = 0;
249
250 /// Iterators over the stack iterate in order from innermost to outermost
251 /// directive.
252 using const_iterator = StackTy::const_reverse_iterator;
253 const_iterator begin() const {
254 return Stack.empty() ? const_iterator()
255 : Stack.back().first.rbegin() + IgnoredStackElements;
256 }
257 const_iterator end() const {
258 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
259 }
260 using iterator = StackTy::reverse_iterator;
261 iterator begin() {
262 return Stack.empty() ? iterator()
263 : Stack.back().first.rbegin() + IgnoredStackElements;
264 }
265 iterator end() {
266 return Stack.empty() ? iterator() : Stack.back().first.rend();
267 }
268
269 // Convenience operations to get at the elements of the stack.
270
271 bool isStackEmpty() const {
272 return Stack.empty() ||
273 Stack.back().second != CurrentNonCapturingFunctionScope ||
274 Stack.back().first.size() <= IgnoredStackElements;
275 }
276 size_t getStackSize() const {
277 return isStackEmpty() ? 0
278 : Stack.back().first.size() - IgnoredStackElements;
279 }
280
281 SharingMapTy *getTopOfStackOrNull() {
282 size_t Size = getStackSize();
283 if (Size == 0)
284 return nullptr;
285 return &Stack.back().first[Size - 1];
286 }
287 const SharingMapTy *getTopOfStackOrNull() const {
288 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
289 }
290 SharingMapTy &getTopOfStack() {
291 assert(!isStackEmpty() && "no current directive");
292 return *getTopOfStackOrNull();
293 }
294 const SharingMapTy &getTopOfStack() const {
295 return const_cast<DSAStackTy &>(*this).getTopOfStack();
296 }
297
298 SharingMapTy *getSecondOnStackOrNull() {
299 size_t Size = getStackSize();
300 if (Size <= 1)
301 return nullptr;
302 return &Stack.back().first[Size - 2];
303 }
304 const SharingMapTy *getSecondOnStackOrNull() const {
305 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
306 }
307
308 /// Get the stack element at a certain level (previously returned by
309 /// \c getNestingLevel).
310 ///
311 /// Note that nesting levels count from outermost to innermost, and this is
312 /// the reverse of our iteration order where new inner levels are pushed at
313 /// the front of the stack.
314 SharingMapTy &getStackElemAtLevel(unsigned Level) {
315 assert(Level < getStackSize() && "no such stack element");
316 return Stack.back().first[Level];
317 }
318 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
319 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
320 }
321
322 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
323
324 /// Checks if the variable is a local for OpenMP region.
325 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
326
327 /// Vector of previously declared requires directives
329 /// omp_allocator_handle_t type.
330 QualType OMPAllocatorHandleT;
331 /// omp_depend_t type.
332 QualType OMPDependT;
333 /// omp_event_handle_t type.
334 QualType OMPEventHandleT;
335 /// omp_alloctrait_t type.
336 QualType OMPAlloctraitT;
337 /// Expression for the predefined allocators.
338 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
339 nullptr};
340 /// Vector of previously encountered target directives
341 SmallVector<SourceLocation, 2> TargetLocations;
342 SourceLocation AtomicLocation;
343 /// Vector of declare variant construct traits.
345
346public:
347 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
348
349 /// Sets omp_allocator_handle_t type.
350 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
351 /// Gets omp_allocator_handle_t type.
352 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
353 /// Sets omp_alloctrait_t type.
354 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
355 /// Gets omp_alloctrait_t type.
356 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
357 /// Sets the given default allocator.
358 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
359 Expr *Allocator) {
360 OMPPredefinedAllocators[AllocatorKind] = Allocator;
361 }
362 /// Returns the specified default allocator.
363 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
364 return OMPPredefinedAllocators[AllocatorKind];
365 }
366 /// Sets omp_depend_t type.
367 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
368 /// Gets omp_depend_t type.
369 QualType getOMPDependT() const { return OMPDependT; }
370
371 /// Sets omp_event_handle_t type.
372 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
373 /// Gets omp_event_handle_t type.
374 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
375
376 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
377 OpenMPClauseKind getClauseParsingMode() const {
378 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
379 return ClauseKindMode;
380 }
381 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
382
383 bool isBodyComplete() const {
384 const SharingMapTy *Top = getTopOfStackOrNull();
385 return Top && Top->BodyComplete;
386 }
387 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
388
389 bool isForceVarCapturing() const { return ForceCapturing; }
390 void setForceVarCapturing(bool V) { ForceCapturing = V; }
391
392 void setForceCaptureByReferenceInTargetExecutable(bool V) {
393 ForceCaptureByReferenceInTargetExecutable = V;
394 }
395 bool isForceCaptureByReferenceInTargetExecutable() const {
396 return ForceCaptureByReferenceInTargetExecutable;
397 }
398
399 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
400 Scope *CurScope, SourceLocation Loc) {
401 assert(!IgnoredStackElements &&
402 "cannot change stack while ignoring elements");
403 if (Stack.empty() ||
404 Stack.back().second != CurrentNonCapturingFunctionScope)
405 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
406 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
407 Stack.back().first.back().DefaultAttrLoc = Loc;
408 }
409
410 void pop() {
411 assert(!IgnoredStackElements &&
412 "cannot change stack while ignoring elements");
413 assert(!Stack.back().first.empty() &&
414 "Data-sharing attributes stack is empty!");
415 Stack.back().first.pop_back();
416 }
417
418 /// RAII object to temporarily leave the scope of a directive when we want to
419 /// logically operate in its parent.
420 class ParentDirectiveScope {
421 DSAStackTy &Self;
422 bool Active;
423
424 public:
425 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
426 : Self(Self), Active(false) {
427 if (Activate)
428 enable();
429 }
430 ~ParentDirectiveScope() { disable(); }
431 void disable() {
432 if (Active) {
433 --Self.IgnoredStackElements;
434 Active = false;
435 }
436 }
437 void enable() {
438 if (!Active) {
439 ++Self.IgnoredStackElements;
440 Active = true;
441 }
442 }
443 };
444
445 /// Marks that we're started loop parsing.
446 void loopInit() {
447 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
448 "Expected loop-based directive.");
449 getTopOfStack().LoopStart = true;
450 }
451 /// Start capturing of the variables in the loop context.
452 void loopStart() {
453 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
454 "Expected loop-based directive.");
455 getTopOfStack().LoopStart = false;
456 }
457 /// true, if variables are captured, false otherwise.
458 bool isLoopStarted() const {
459 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
460 "Expected loop-based directive.");
461 return !getTopOfStack().LoopStart;
462 }
463 /// Marks (or clears) declaration as possibly loop counter.
464 void resetPossibleLoopCounter(const Decl *D = nullptr) {
465 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
466 }
467 /// Gets the possible loop counter decl.
468 const Decl *getPossiblyLoopCunter() const {
469 return getTopOfStack().PossiblyLoopCounter;
470 }
471 /// Start new OpenMP region stack in new non-capturing function.
472 void pushFunction() {
473 assert(!IgnoredStackElements &&
474 "cannot change stack while ignoring elements");
475 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
476 assert(!isa<CapturingScopeInfo>(CurFnScope));
477 CurrentNonCapturingFunctionScope = CurFnScope;
478 }
479 /// Pop region stack for non-capturing function.
480 void popFunction(const FunctionScopeInfo *OldFSI) {
481 assert(!IgnoredStackElements &&
482 "cannot change stack while ignoring elements");
483 if (!Stack.empty() && Stack.back().second == OldFSI) {
484 assert(Stack.back().first.empty());
485 Stack.pop_back();
486 }
487 CurrentNonCapturingFunctionScope = nullptr;
488 for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
489 if (!isa<CapturingScopeInfo>(FSI)) {
490 CurrentNonCapturingFunctionScope = FSI;
491 break;
492 }
493 }
494 }
495
496 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
497 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
498 }
499 const std::pair<const OMPCriticalDirective *, llvm::APSInt>
500 getCriticalWithHint(const DeclarationNameInfo &Name) const {
501 auto I = Criticals.find(Name.getAsString());
502 if (I != Criticals.end())
503 return I->second;
504 return std::make_pair(nullptr, llvm::APSInt());
505 }
506 /// If 'aligned' declaration for given variable \a D was not seen yet,
507 /// add it and return NULL; otherwise return previous occurrence's expression
508 /// for diagnostics.
509 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
510 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
511 /// add it and return NULL; otherwise return previous occurrence's expression
512 /// for diagnostics.
513 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
514
515 /// Register specified variable as loop control variable.
516 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
517 /// Check if the specified variable is a loop control variable for
518 /// current region.
519 /// \return The index of the loop control variable in the list of associated
520 /// for-loops (from outer to inner).
521 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
522 /// Check if the specified variable is a loop control variable for
523 /// parent region.
524 /// \return The index of the loop control variable in the list of associated
525 /// for-loops (from outer to inner).
526 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
527 /// Check if the specified variable is a loop control variable for
528 /// current region.
529 /// \return The index of the loop control variable in the list of associated
530 /// for-loops (from outer to inner).
531 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
532 unsigned Level) const;
533 /// Get the loop control variable for the I-th loop (or nullptr) in
534 /// parent directive.
535 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
536
537 /// Marks the specified decl \p D as used in scan directive.
538 void markDeclAsUsedInScanDirective(ValueDecl *D) {
539 if (SharingMapTy *Stack = getSecondOnStackOrNull())
540 Stack->UsedInScanDirective.insert(D);
541 }
542
543 /// Checks if the specified declaration was used in the inner scan directive.
544 bool isUsedInScanDirective(ValueDecl *D) const {
545 if (const SharingMapTy *Stack = getTopOfStackOrNull())
546 return Stack->UsedInScanDirective.contains(D);
547 return false;
548 }
549
550 /// Adds explicit data sharing attribute to the specified declaration.
551 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
552 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
553 bool AppliedToPointee = false);
554
555 /// Adds additional information for the reduction items with the reduction id
556 /// represented as an operator.
557 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
559 /// Adds additional information for the reduction items with the reduction id
560 /// represented as reduction identifier.
561 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
562 const Expr *ReductionRef);
563 /// Returns the location and reduction operation from the innermost parent
564 /// region for the given \p D.
565 const DSAVarData
566 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
568 Expr *&TaskgroupDescriptor) const;
569 /// Returns the location and reduction operation from the innermost parent
570 /// region for the given \p D.
571 const DSAVarData
572 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
573 const Expr *&ReductionRef,
574 Expr *&TaskgroupDescriptor) const;
575 /// Return reduction reference expression for the current taskgroup or
576 /// parallel/worksharing directives with task reductions.
577 Expr *getTaskgroupReductionRef() const {
578 assert((getTopOfStack().Directive == OMPD_taskgroup ||
579 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
580 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
581 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
582 "taskgroup reference expression requested for non taskgroup or "
583 "parallel/worksharing directive.");
584 return getTopOfStack().TaskgroupReductionRef;
585 }
586 /// Checks if the given \p VD declaration is actually a taskgroup reduction
587 /// descriptor variable at the \p Level of OpenMP regions.
588 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
589 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
590 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
591 ->getDecl() == VD;
592 }
593
594 /// Returns data sharing attributes from top of the stack for the
595 /// specified declaration.
596 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
597 /// Returns data-sharing attributes for the specified declaration.
598 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
599 /// Returns data-sharing attributes for the specified declaration.
600 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
601 /// Checks if the specified variables has data-sharing attributes which
602 /// match specified \a CPred predicate in any directive which matches \a DPred
603 /// predicate.
604 const DSAVarData
605 hasDSA(ValueDecl *D,
606 const llvm::function_ref<bool(OpenMPClauseKind, bool,
607 DefaultDataSharingAttributes)>
608 CPred,
609 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
610 bool FromParent) const;
611 /// Checks if the specified variables has data-sharing attributes which
612 /// match specified \a CPred predicate in any innermost directive which
613 /// matches \a DPred predicate.
614 const DSAVarData
615 hasInnermostDSA(ValueDecl *D,
616 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
617 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
618 bool FromParent) const;
619 /// Checks if the specified variables has explicit data-sharing
620 /// attributes which match specified \a CPred predicate at the specified
621 /// OpenMP region.
622 bool
623 hasExplicitDSA(const ValueDecl *D,
624 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
625 unsigned Level, bool NotLastprivate = false) const;
626
627 /// Returns true if the directive at level \Level matches in the
628 /// specified \a DPred predicate.
629 bool hasExplicitDirective(
630 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
631 unsigned Level) const;
632
633 /// Finds a directive which matches specified \a DPred predicate.
634 bool hasDirective(
635 const llvm::function_ref<bool(
637 DPred,
638 bool FromParent) const;
639
640 /// Returns currently analyzed directive.
641 OpenMPDirectiveKind getCurrentDirective() const {
642 const SharingMapTy *Top = getTopOfStackOrNull();
643 return Top ? Top->Directive : OMPD_unknown;
644 }
645 OpenMPDirectiveKind getMappedDirective() const {
646 const SharingMapTy *Top = getTopOfStackOrNull();
647 return Top ? Top->MappedDirective : OMPD_unknown;
648 }
649 void setCurrentDirective(OpenMPDirectiveKind NewDK) {
650 SharingMapTy *Top = getTopOfStackOrNull();
651 assert(Top &&
652 "Before calling setCurrentDirective Top of Stack not to be NULL.");
653 // Store the old into MappedDirective & assign argument NewDK to Directive.
654 Top->Directive = NewDK;
655 }
656 void setMappedDirective(OpenMPDirectiveKind NewDK) {
657 SharingMapTy *Top = getTopOfStackOrNull();
658 assert(Top &&
659 "Before calling setMappedDirective Top of Stack not to be NULL.");
660 // Store the old into MappedDirective & assign argument NewDK to Directive.
661 Top->MappedDirective = NewDK;
662 }
663 /// Returns directive kind at specified level.
664 OpenMPDirectiveKind getDirective(unsigned Level) const {
665 assert(!isStackEmpty() && "No directive at specified level.");
666 return getStackElemAtLevel(Level).Directive;
667 }
668 /// Returns the capture region at the specified level.
669 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
670 unsigned OpenMPCaptureLevel) const {
672 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
673 return CaptureRegions[OpenMPCaptureLevel];
674 }
675 /// Returns parent directive.
676 OpenMPDirectiveKind getParentDirective() const {
677 const SharingMapTy *Parent = getSecondOnStackOrNull();
678 return Parent ? Parent->Directive : OMPD_unknown;
679 }
680
681 /// Add requires decl to internal vector
682 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
683
684 /// Checks if the defined 'requires' directive has specified type of clause.
685 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
686 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
687 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
688 return isa<ClauseType>(C);
689 });
690 });
691 }
692
693 /// Checks for a duplicate clause amongst previously declared requires
694 /// directives
695 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
696 bool IsDuplicate = false;
697 for (OMPClause *CNew : ClauseList) {
698 for (const OMPRequiresDecl *D : RequiresDecls) {
699 for (const OMPClause *CPrev : D->clauselists()) {
700 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
701 SemaRef.Diag(CNew->getBeginLoc(),
702 diag::err_omp_requires_clause_redeclaration)
703 << getOpenMPClauseName(CNew->getClauseKind());
704 SemaRef.Diag(CPrev->getBeginLoc(),
705 diag::note_omp_requires_previous_clause)
706 << getOpenMPClauseName(CPrev->getClauseKind());
707 IsDuplicate = true;
708 }
709 }
710 }
711 }
712 return IsDuplicate;
713 }
714
715 /// Add location of previously encountered target to internal vector
716 void addTargetDirLocation(SourceLocation LocStart) {
717 TargetLocations.push_back(LocStart);
718 }
719
720 /// Add location for the first encountered atomicc directive.
721 void addAtomicDirectiveLoc(SourceLocation Loc) {
722 if (AtomicLocation.isInvalid())
723 AtomicLocation = Loc;
724 }
725
726 /// Returns the location of the first encountered atomic directive in the
727 /// module.
728 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
729
730 // Return previously encountered target region locations.
731 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
732 return TargetLocations;
733 }
734
735 /// Set default data sharing attribute to none.
736 void setDefaultDSANone(SourceLocation Loc) {
737 getTopOfStack().DefaultAttr = DSA_none;
738 getTopOfStack().DefaultAttrLoc = Loc;
739 }
740 /// Set default data sharing attribute to shared.
741 void setDefaultDSAShared(SourceLocation Loc) {
742 getTopOfStack().DefaultAttr = DSA_shared;
743 getTopOfStack().DefaultAttrLoc = Loc;
744 }
745 /// Set default data sharing attribute to private.
746 void setDefaultDSAPrivate(SourceLocation Loc) {
747 getTopOfStack().DefaultAttr = DSA_private;
748 getTopOfStack().DefaultAttrLoc = Loc;
749 }
750 /// Set default data sharing attribute to firstprivate.
751 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
752 getTopOfStack().DefaultAttr = DSA_firstprivate;
753 getTopOfStack().DefaultAttrLoc = Loc;
754 }
755 /// Set default data mapping attribute to Modifier:Kind
756 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
758 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
759 DMI.ImplicitBehavior = M;
760 DMI.SLoc = Loc;
761 }
762 /// Check whether the implicit-behavior has been set in defaultmap
763 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
764 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
765 return getTopOfStack()
766 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
767 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
768 getTopOfStack()
769 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
770 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
771 getTopOfStack()
772 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
773 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
774 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
776 }
777
778 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
779 return ConstructTraits;
780 }
781 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
782 bool ScopeEntry) {
783 if (ScopeEntry)
784 ConstructTraits.append(Traits.begin(), Traits.end());
785 else
786 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
787 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
788 assert(Top == Trait && "Something left a trait on the stack!");
789 (void)Trait;
790 (void)Top;
791 }
792 }
793
794 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
795 return getStackSize() <= Level ? DSA_unspecified
796 : getStackElemAtLevel(Level).DefaultAttr;
797 }
798 DefaultDataSharingAttributes getDefaultDSA() const {
799 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
800 }
801 SourceLocation getDefaultDSALocation() const {
802 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
803 }
805 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
806 return isStackEmpty()
808 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
809 }
811 getDefaultmapModifierAtLevel(unsigned Level,
812 OpenMPDefaultmapClauseKind Kind) const {
813 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
814 }
815 bool isDefaultmapCapturedByRef(unsigned Level,
816 OpenMPDefaultmapClauseKind Kind) const {
818 getDefaultmapModifierAtLevel(Level, Kind);
819 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
820 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
821 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
822 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
823 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom);
824 }
825 return true;
826 }
827 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
829 switch (Kind) {
830 case OMPC_DEFAULTMAP_scalar:
831 case OMPC_DEFAULTMAP_pointer:
832 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
833 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
834 (M == OMPC_DEFAULTMAP_MODIFIER_default);
835 case OMPC_DEFAULTMAP_aggregate:
836 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
837 default:
838 break;
839 }
840 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
841 }
842 bool mustBeFirstprivateAtLevel(unsigned Level,
843 OpenMPDefaultmapClauseKind Kind) const {
845 getDefaultmapModifierAtLevel(Level, Kind);
846 return mustBeFirstprivateBase(M, Kind);
847 }
848 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
849 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
850 return mustBeFirstprivateBase(M, Kind);
851 }
852
853 /// Checks if the specified variable is a threadprivate.
854 bool isThreadPrivate(VarDecl *D) {
855 const DSAVarData DVar = getTopDSA(D, false);
856 return isOpenMPThreadPrivate(DVar.CKind);
857 }
858
859 /// Marks current region as ordered (it has an 'ordered' clause).
860 void setOrderedRegion(bool IsOrdered, const Expr *Param,
861 OMPOrderedClause *Clause) {
862 if (IsOrdered)
863 getTopOfStack().OrderedRegion.emplace(Param, Clause);
864 else
865 getTopOfStack().OrderedRegion.reset();
866 }
867 /// Returns true, if region is ordered (has associated 'ordered' clause),
868 /// false - otherwise.
869 bool isOrderedRegion() const {
870 if (const SharingMapTy *Top = getTopOfStackOrNull())
871 return Top->OrderedRegion.has_value();
872 return false;
873 }
874 /// Returns optional parameter for the ordered region.
875 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
876 if (const SharingMapTy *Top = getTopOfStackOrNull())
877 if (Top->OrderedRegion)
878 return *Top->OrderedRegion;
879 return std::make_pair(nullptr, nullptr);
880 }
881 /// Returns true, if parent region is ordered (has associated
882 /// 'ordered' clause), false - otherwise.
883 bool isParentOrderedRegion() const {
884 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
885 return Parent->OrderedRegion.has_value();
886 return false;
887 }
888 /// Returns optional parameter for the ordered region.
889 std::pair<const Expr *, OMPOrderedClause *>
890 getParentOrderedRegionParam() const {
891 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
892 if (Parent->OrderedRegion)
893 return *Parent->OrderedRegion;
894 return std::make_pair(nullptr, nullptr);
895 }
896 /// Marks current region as having an 'order' clause.
897 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
898 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
899 }
900 /// Returns true, if parent region is order (has associated
901 /// 'order' clause), false - otherwise.
902 bool isParentOrderConcurrent() const {
903 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
904 return Parent->RegionHasOrderConcurrent;
905 return false;
906 }
907 /// Marks current region as nowait (it has a 'nowait' clause).
908 void setNowaitRegion(bool IsNowait = true) {
909 getTopOfStack().NowaitRegion = IsNowait;
910 }
911 /// Returns true, if parent region is nowait (has associated
912 /// 'nowait' clause), false - otherwise.
913 bool isParentNowaitRegion() const {
914 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
915 return Parent->NowaitRegion;
916 return false;
917 }
918 /// Marks current region as untied (it has a 'untied' clause).
919 void setUntiedRegion(bool IsUntied = true) {
920 getTopOfStack().UntiedRegion = IsUntied;
921 }
922 /// Return true if current region is untied.
923 bool isUntiedRegion() const {
924 const SharingMapTy *Top = getTopOfStackOrNull();
925 return Top ? Top->UntiedRegion : false;
926 }
927 /// Marks parent region as cancel region.
928 void setParentCancelRegion(bool Cancel = true) {
929 if (SharingMapTy *Parent = getSecondOnStackOrNull())
930 Parent->CancelRegion |= Cancel;
931 }
932 /// Return true if current region has inner cancel construct.
933 bool isCancelRegion() const {
934 const SharingMapTy *Top = getTopOfStackOrNull();
935 return Top ? Top->CancelRegion : false;
936 }
937
938 /// Mark that parent region already has scan directive.
939 void setParentHasScanDirective(SourceLocation Loc) {
940 if (SharingMapTy *Parent = getSecondOnStackOrNull())
941 Parent->PrevScanLocation = Loc;
942 }
943 /// Return true if current region has inner cancel construct.
944 bool doesParentHasScanDirective() const {
945 const SharingMapTy *Top = getSecondOnStackOrNull();
946 return Top ? Top->PrevScanLocation.isValid() : false;
947 }
948 /// Return true if current region has inner cancel construct.
949 SourceLocation getParentScanDirectiveLoc() const {
950 const SharingMapTy *Top = getSecondOnStackOrNull();
951 return Top ? Top->PrevScanLocation : SourceLocation();
952 }
953 /// Mark that parent region already has ordered directive.
954 void setParentHasOrderedDirective(SourceLocation Loc) {
955 if (SharingMapTy *Parent = getSecondOnStackOrNull())
956 Parent->PrevOrderedLocation = Loc;
957 }
958 /// Return true if current region has inner ordered construct.
959 bool doesParentHasOrderedDirective() const {
960 const SharingMapTy *Top = getSecondOnStackOrNull();
961 return Top ? Top->PrevOrderedLocation.isValid() : false;
962 }
963 /// Returns the location of the previously specified ordered directive.
964 SourceLocation getParentOrderedDirectiveLoc() const {
965 const SharingMapTy *Top = getSecondOnStackOrNull();
966 return Top ? Top->PrevOrderedLocation : SourceLocation();
967 }
968
969 /// Set collapse value for the region.
970 void setAssociatedLoops(unsigned Val) {
971 getTopOfStack().AssociatedLoops = Val;
972 if (Val > 1)
973 getTopOfStack().HasMutipleLoops = true;
974 }
975 /// Return collapse value for region.
976 unsigned getAssociatedLoops() const {
977 const SharingMapTy *Top = getTopOfStackOrNull();
978 return Top ? Top->AssociatedLoops : 0;
979 }
980 /// Returns true if the construct is associated with multiple loops.
981 bool hasMutipleLoops() const {
982 const SharingMapTy *Top = getTopOfStackOrNull();
983 return Top ? Top->HasMutipleLoops : false;
984 }
985
986 /// Marks current target region as one with closely nested teams
987 /// region.
988 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
989 if (SharingMapTy *Parent = getSecondOnStackOrNull())
990 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
991 }
992 /// Returns true, if current region has closely nested teams region.
993 bool hasInnerTeamsRegion() const {
994 return getInnerTeamsRegionLoc().isValid();
995 }
996 /// Returns location of the nested teams region (if any).
997 SourceLocation getInnerTeamsRegionLoc() const {
998 const SharingMapTy *Top = getTopOfStackOrNull();
999 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
1000 }
1001
1002 Scope *getCurScope() const {
1003 const SharingMapTy *Top = getTopOfStackOrNull();
1004 return Top ? Top->CurScope : nullptr;
1005 }
1006 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
1007 SourceLocation getConstructLoc() const {
1008 const SharingMapTy *Top = getTopOfStackOrNull();
1009 return Top ? Top->ConstructLoc : SourceLocation();
1010 }
1011
1012 /// Do the check specified in \a Check to all component lists and return true
1013 /// if any issue is found.
1014 bool checkMappableExprComponentListsForDecl(
1015 const ValueDecl *VD, bool CurrentRegionOnly,
1016 const llvm::function_ref<
1019 Check) const {
1020 if (isStackEmpty())
1021 return false;
1022 auto SI = begin();
1023 auto SE = end();
1024
1025 if (SI == SE)
1026 return false;
1027
1028 if (CurrentRegionOnly)
1029 SE = std::next(SI);
1030 else
1031 std::advance(SI, 1);
1032
1033 for (; SI != SE; ++SI) {
1034 auto MI = SI->MappedExprComponents.find(VD);
1035 if (MI != SI->MappedExprComponents.end())
1037 MI->second.Components)
1038 if (Check(L, MI->second.Kind))
1039 return true;
1040 }
1041 return false;
1042 }
1043
1044 /// Do the check specified in \a Check to all component lists at a given level
1045 /// and return true if any issue is found.
1046 bool checkMappableExprComponentListsForDeclAtLevel(
1047 const ValueDecl *VD, unsigned Level,
1048 const llvm::function_ref<
1051 Check) const {
1052 if (getStackSize() <= Level)
1053 return false;
1054
1055 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1056 auto MI = StackElem.MappedExprComponents.find(VD);
1057 if (MI != StackElem.MappedExprComponents.end())
1059 MI->second.Components)
1060 if (Check(L, MI->second.Kind))
1061 return true;
1062 return false;
1063 }
1064
1065 /// Create a new mappable expression component list associated with a given
1066 /// declaration and initialize it with the provided list of components.
1067 void addMappableExpressionComponents(
1068 const ValueDecl *VD,
1070 OpenMPClauseKind WhereFoundClauseKind) {
1071 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1072 // Create new entry and append the new components there.
1073 MEC.Components.resize(MEC.Components.size() + 1);
1074 MEC.Components.back().append(Components.begin(), Components.end());
1075 MEC.Kind = WhereFoundClauseKind;
1076 }
1077
1078 unsigned getNestingLevel() const {
1079 assert(!isStackEmpty());
1080 return getStackSize() - 1;
1081 }
1082 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1083 SharingMapTy *Parent = getSecondOnStackOrNull();
1084 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1085 Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1086 }
1087 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1088 getDoacrossDependClauses() const {
1089 const SharingMapTy &StackElem = getTopOfStack();
1090 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1091 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1092 return llvm::make_range(Ref.begin(), Ref.end());
1093 }
1094 return llvm::make_range(StackElem.DoacrossDepends.end(),
1095 StackElem.DoacrossDepends.end());
1096 }
1097
1098 // Store types of classes which have been explicitly mapped
1099 void addMappedClassesQualTypes(QualType QT) {
1100 SharingMapTy &StackElem = getTopOfStack();
1101 StackElem.MappedClassesQualTypes.insert(QT);
1102 }
1103
1104 // Return set of mapped classes types
1105 bool isClassPreviouslyMapped(QualType QT) const {
1106 const SharingMapTy &StackElem = getTopOfStack();
1107 return StackElem.MappedClassesQualTypes.contains(QT);
1108 }
1109
1110 /// Adds global declare target to the parent target region.
1111 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1112 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1113 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1114 "Expected declare target link global.");
1115 for (auto &Elem : *this) {
1116 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1117 Elem.DeclareTargetLinkVarDecls.push_back(E);
1118 return;
1119 }
1120 }
1121 }
1122
1123 /// Returns the list of globals with declare target link if current directive
1124 /// is target.
1125 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1126 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1127 "Expected target executable directive.");
1128 return getTopOfStack().DeclareTargetLinkVarDecls;
1129 }
1130
1131 /// Adds list of allocators expressions.
1132 void addInnerAllocatorExpr(Expr *E) {
1133 getTopOfStack().InnerUsedAllocators.push_back(E);
1134 }
1135 /// Return list of used allocators.
1136 ArrayRef<Expr *> getInnerAllocators() const {
1137 return getTopOfStack().InnerUsedAllocators;
1138 }
1139 /// Marks the declaration as implicitly firstprivate nin the task-based
1140 /// regions.
1141 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1142 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1143 }
1144 /// Checks if the decl is implicitly firstprivate in the task-based region.
1145 bool isImplicitTaskFirstprivate(Decl *D) const {
1146 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1147 }
1148
1149 /// Marks decl as used in uses_allocators clause as the allocator.
1150 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1151 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1152 }
1153 /// Checks if specified decl is used in uses allocator clause as the
1154 /// allocator.
1155 std::optional<UsesAllocatorsDeclKind>
1156 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1157 const SharingMapTy &StackElem = getTopOfStack();
1158 auto I = StackElem.UsesAllocatorsDecls.find(D);
1159 if (I == StackElem.UsesAllocatorsDecls.end())
1160 return std::nullopt;
1161 return I->getSecond();
1162 }
1163 std::optional<UsesAllocatorsDeclKind>
1164 isUsesAllocatorsDecl(const Decl *D) const {
1165 const SharingMapTy &StackElem = getTopOfStack();
1166 auto I = StackElem.UsesAllocatorsDecls.find(D);
1167 if (I == StackElem.UsesAllocatorsDecls.end())
1168 return std::nullopt;
1169 return I->getSecond();
1170 }
1171
1172 void addDeclareMapperVarRef(Expr *Ref) {
1173 SharingMapTy &StackElem = getTopOfStack();
1174 StackElem.DeclareMapperVar = Ref;
1175 }
1176 const Expr *getDeclareMapperVarRef() const {
1177 const SharingMapTy *Top = getTopOfStackOrNull();
1178 return Top ? Top->DeclareMapperVar : nullptr;
1179 }
1180
1181 /// Add a new iterator variable.
1182 void addIteratorVarDecl(VarDecl *VD) {
1183 SharingMapTy &StackElem = getTopOfStack();
1184 StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl());
1185 }
1186 /// Check if variable declaration is an iterator VarDecl.
1187 bool isIteratorVarDecl(const VarDecl *VD) const {
1188 const SharingMapTy *Top = getTopOfStackOrNull();
1189 if (!Top)
1190 return false;
1191
1192 return llvm::is_contained(Top->IteratorVarDecls, VD->getCanonicalDecl());
1193 }
1194 /// get captured field from ImplicitDefaultFirstprivateFDs
1195 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1196 const_iterator I = begin();
1197 const_iterator EndI = end();
1198 size_t StackLevel = getStackSize();
1199 for (; I != EndI; ++I) {
1200 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1201 break;
1202 StackLevel--;
1203 }
1204 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1205 if (I == EndI)
1206 return nullptr;
1207 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1208 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1209 return IFD.VD;
1210 return nullptr;
1211 }
1212 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1213 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1214 const_iterator I = begin();
1215 const_iterator EndI = end();
1216 for (; I != EndI; ++I)
1217 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1218 break;
1219 if (I == EndI)
1220 return false;
1221 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1222 if (IFD.VD == VD)
1223 return true;
1224 return false;
1225 }
1226 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1227 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1228 iterator I = begin();
1229 const_iterator EndI = end();
1230 size_t StackLevel = getStackSize();
1231 for (; I != EndI; ++I) {
1232 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1233 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1234 break;
1235 }
1236 StackLevel--;
1237 }
1238 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1239 }
1240};
1241
1242bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1243 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1244}
1245
1246bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1247 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1248 DKind == OMPD_unknown;
1249}
1250
1251} // namespace
1252
1253static const Expr *getExprAsWritten(const Expr *E) {
1254 if (const auto *FE = dyn_cast<FullExpr>(E))
1255 E = FE->getSubExpr();
1256
1257 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1258 E = MTE->getSubExpr();
1259
1260 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1261 E = Binder->getSubExpr();
1262
1263 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1264 E = ICE->getSubExprAsWritten();
1265 return E->IgnoreParens();
1266}
1267
1269 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1270}
1271
1272static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1273 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1274 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1275 D = ME->getMemberDecl();
1276 const auto *VD = dyn_cast<VarDecl>(D);
1277 const auto *FD = dyn_cast<FieldDecl>(D);
1278 if (VD != nullptr) {
1279 VD = VD->getCanonicalDecl();
1280 D = VD;
1281 } else {
1282 assert(FD);
1283 FD = FD->getCanonicalDecl();
1284 D = FD;
1285 }
1286 return D;
1287}
1288
1290 return const_cast<ValueDecl *>(
1291 getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1292}
1293
1294DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1295 ValueDecl *D) const {
1296 D = getCanonicalDecl(D);
1297 auto *VD = dyn_cast<VarDecl>(D);
1298 const auto *FD = dyn_cast<FieldDecl>(D);
1299 DSAVarData DVar;
1300 if (Iter == end()) {
1301 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1302 // in a region but not in construct]
1303 // File-scope or namespace-scope variables referenced in called routines
1304 // in the region are shared unless they appear in a threadprivate
1305 // directive.
1306 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1307 DVar.CKind = OMPC_shared;
1308
1309 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1310 // in a region but not in construct]
1311 // Variables with static storage duration that are declared in called
1312 // routines in the region are shared.
1313 if (VD && VD->hasGlobalStorage())
1314 DVar.CKind = OMPC_shared;
1315
1316 // Non-static data members are shared by default.
1317 if (FD)
1318 DVar.CKind = OMPC_shared;
1319
1320 return DVar;
1321 }
1322
1323 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1324 // in a Construct, C/C++, predetermined, p.1]
1325 // Variables with automatic storage duration that are declared in a scope
1326 // inside the construct are private.
1327 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1328 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1329 DVar.CKind = OMPC_private;
1330 return DVar;
1331 }
1332
1333 DVar.DKind = Iter->Directive;
1334 // Explicitly specified attributes and local variables with predetermined
1335 // attributes.
1336 if (Iter->SharingMap.count(D)) {
1337 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1338 DVar.RefExpr = Data.RefExpr.getPointer();
1339 DVar.PrivateCopy = Data.PrivateCopy;
1340 DVar.CKind = Data.Attributes;
1341 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1342 DVar.Modifier = Data.Modifier;
1343 DVar.AppliedToPointee = Data.AppliedToPointee;
1344 return DVar;
1345 }
1346
1347 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1348 // in a Construct, C/C++, implicitly determined, p.1]
1349 // In a parallel or task construct, the data-sharing attributes of these
1350 // variables are determined by the default clause, if present.
1351 switch (Iter->DefaultAttr) {
1352 case DSA_shared:
1353 DVar.CKind = OMPC_shared;
1354 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1355 return DVar;
1356 case DSA_none:
1357 return DVar;
1358 case DSA_firstprivate:
1359 if (VD && VD->getStorageDuration() == SD_Static &&
1360 VD->getDeclContext()->isFileContext()) {
1361 DVar.CKind = OMPC_unknown;
1362 } else {
1363 DVar.CKind = OMPC_firstprivate;
1364 }
1365 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1366 return DVar;
1367 case DSA_private:
1368 // each variable with static storage duration that is declared
1369 // in a namespace or global scope and referenced in the construct,
1370 // and that does not have a predetermined data-sharing attribute
1371 if (VD && VD->getStorageDuration() == SD_Static &&
1372 VD->getDeclContext()->isFileContext()) {
1373 DVar.CKind = OMPC_unknown;
1374 } else {
1375 DVar.CKind = OMPC_private;
1376 }
1377 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1378 return DVar;
1379 case DSA_unspecified:
1380 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1381 // in a Construct, implicitly determined, p.2]
1382 // In a parallel construct, if no default clause is present, these
1383 // variables are shared.
1384 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1385 if ((isOpenMPParallelDirective(DVar.DKind) &&
1386 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1387 isOpenMPTeamsDirective(DVar.DKind)) {
1388 DVar.CKind = OMPC_shared;
1389 return DVar;
1390 }
1391
1392 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1393 // in a Construct, implicitly determined, p.4]
1394 // In a task construct, if no default clause is present, a variable that in
1395 // the enclosing context is determined to be shared by all implicit tasks
1396 // bound to the current team is shared.
1397 if (isOpenMPTaskingDirective(DVar.DKind)) {
1398 DSAVarData DVarTemp;
1399 const_iterator I = Iter, E = end();
1400 do {
1401 ++I;
1402 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1403 // Referenced in a Construct, implicitly determined, p.6]
1404 // In a task construct, if no default clause is present, a variable
1405 // whose data-sharing attribute is not determined by the rules above is
1406 // firstprivate.
1407 DVarTemp = getDSA(I, D);
1408 if (DVarTemp.CKind != OMPC_shared) {
1409 DVar.RefExpr = nullptr;
1410 DVar.CKind = OMPC_firstprivate;
1411 return DVar;
1412 }
1413 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1414 DVar.CKind =
1415 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1416 return DVar;
1417 }
1418 }
1419 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1420 // in a Construct, implicitly determined, p.3]
1421 // For constructs other than task, if no default clause is present, these
1422 // variables inherit their data-sharing attributes from the enclosing
1423 // context.
1424 return getDSA(++Iter, D);
1425}
1426
1427const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1428 const Expr *NewDE) {
1429 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1430 D = getCanonicalDecl(D);
1431 SharingMapTy &StackElem = getTopOfStack();
1432 auto It = StackElem.AlignedMap.find(D);
1433 if (It == StackElem.AlignedMap.end()) {
1434 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1435 StackElem.AlignedMap[D] = NewDE;
1436 return nullptr;
1437 }
1438 assert(It->second && "Unexpected nullptr expr in the aligned map");
1439 return It->second;
1440}
1441
1442const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1443 const Expr *NewDE) {
1444 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1445 D = getCanonicalDecl(D);
1446 SharingMapTy &StackElem = getTopOfStack();
1447 auto It = StackElem.NontemporalMap.find(D);
1448 if (It == StackElem.NontemporalMap.end()) {
1449 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1450 StackElem.NontemporalMap[D] = NewDE;
1451 return nullptr;
1452 }
1453 assert(It->second && "Unexpected nullptr expr in the aligned map");
1454 return It->second;
1455}
1456
1457void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1458 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1459 D = getCanonicalDecl(D);
1460 SharingMapTy &StackElem = getTopOfStack();
1461 StackElem.LCVMap.try_emplace(
1462 D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1463}
1464
1465const DSAStackTy::LCDeclInfo
1466DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1467 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1468 D = getCanonicalDecl(D);
1469 const SharingMapTy &StackElem = getTopOfStack();
1470 auto It = StackElem.LCVMap.find(D);
1471 if (It != StackElem.LCVMap.end())
1472 return It->second;
1473 return {0, nullptr};
1474}
1475
1476const DSAStackTy::LCDeclInfo
1477DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1478 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1479 D = getCanonicalDecl(D);
1480 for (unsigned I = Level + 1; I > 0; --I) {
1481 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1482 auto It = StackElem.LCVMap.find(D);
1483 if (It != StackElem.LCVMap.end())
1484 return It->second;
1485 }
1486 return {0, nullptr};
1487}
1488
1489const DSAStackTy::LCDeclInfo
1490DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1491 const SharingMapTy *Parent = getSecondOnStackOrNull();
1492 assert(Parent && "Data-sharing attributes stack is empty");
1493 D = getCanonicalDecl(D);
1494 auto It = Parent->LCVMap.find(D);
1495 if (It != Parent->LCVMap.end())
1496 return It->second;
1497 return {0, nullptr};
1498}
1499
1500const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1501 const SharingMapTy *Parent = getSecondOnStackOrNull();
1502 assert(Parent && "Data-sharing attributes stack is empty");
1503 if (Parent->LCVMap.size() < I)
1504 return nullptr;
1505 for (const auto &Pair : Parent->LCVMap)
1506 if (Pair.second.first == I)
1507 return Pair.first;
1508 return nullptr;
1509}
1510
1511void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1512 DeclRefExpr *PrivateCopy, unsigned Modifier,
1513 bool AppliedToPointee) {
1514 D = getCanonicalDecl(D);
1515 if (A == OMPC_threadprivate) {
1516 DSAInfo &Data = Threadprivates[D];
1517 Data.Attributes = A;
1518 Data.RefExpr.setPointer(E);
1519 Data.PrivateCopy = nullptr;
1520 Data.Modifier = Modifier;
1521 } else {
1522 DSAInfo &Data = getTopOfStack().SharingMap[D];
1523 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1524 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1525 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1526 (isLoopControlVariable(D).first && A == OMPC_private));
1527 Data.Modifier = Modifier;
1528 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1529 Data.RefExpr.setInt(/*IntVal=*/true);
1530 return;
1531 }
1532 const bool IsLastprivate =
1533 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1534 Data.Attributes = A;
1535 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1536 Data.PrivateCopy = PrivateCopy;
1537 Data.AppliedToPointee = AppliedToPointee;
1538 if (PrivateCopy) {
1539 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1540 Data.Modifier = Modifier;
1541 Data.Attributes = A;
1542 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1543 Data.PrivateCopy = nullptr;
1544 Data.AppliedToPointee = AppliedToPointee;
1545 }
1546 }
1547}
1548
1549/// Build a variable declaration for OpenMP loop iteration variable.
1551 StringRef Name, const AttrVec *Attrs = nullptr,
1552 DeclRefExpr *OrigRef = nullptr) {
1553 DeclContext *DC = SemaRef.CurContext;
1554 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1555 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
1556 auto *Decl =
1557 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
1558 if (Attrs) {
1559 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1560 I != E; ++I)
1561 Decl->addAttr(*I);
1562 }
1563 Decl->setImplicit();
1564 if (OrigRef) {
1565 Decl->addAttr(
1566 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1567 }
1568 return Decl;
1569}
1570
1572 SourceLocation Loc,
1573 bool RefersToCapture = false) {
1574 D->setReferenced();
1575 D->markUsed(S.Context);
1577 SourceLocation(), D, RefersToCapture, Loc, Ty,
1578 VK_LValue);
1579}
1580
1581void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1582 BinaryOperatorKind BOK) {
1583 D = getCanonicalDecl(D);
1584 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1585 assert(
1586 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1587 "Additional reduction info may be specified only for reduction items.");
1588 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1589 assert(ReductionData.ReductionRange.isInvalid() &&
1590 (getTopOfStack().Directive == OMPD_taskgroup ||
1591 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1592 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1593 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1594 "Additional reduction info may be specified only once for reduction "
1595 "items.");
1596 ReductionData.set(BOK, SR);
1597 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1598 if (!TaskgroupReductionRef) {
1599 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1600 SemaRef.Context.VoidPtrTy, ".task_red.");
1601 TaskgroupReductionRef =
1602 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1603 }
1604}
1605
1606void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1607 const Expr *ReductionRef) {
1608 D = getCanonicalDecl(D);
1609 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1610 assert(
1611 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1612 "Additional reduction info may be specified only for reduction items.");
1613 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1614 assert(ReductionData.ReductionRange.isInvalid() &&
1615 (getTopOfStack().Directive == OMPD_taskgroup ||
1616 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1617 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1618 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1619 "Additional reduction info may be specified only once for reduction "
1620 "items.");
1621 ReductionData.set(ReductionRef, SR);
1622 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1623 if (!TaskgroupReductionRef) {
1624 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1625 SemaRef.Context.VoidPtrTy, ".task_red.");
1626 TaskgroupReductionRef =
1627 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1628 }
1629}
1630
1631const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1632 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1633 Expr *&TaskgroupDescriptor) const {
1634 D = getCanonicalDecl(D);
1635 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1636 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1637 const DSAInfo &Data = I->SharingMap.lookup(D);
1638 if (Data.Attributes != OMPC_reduction ||
1639 Data.Modifier != OMPC_REDUCTION_task)
1640 continue;
1641 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1642 if (!ReductionData.ReductionOp ||
1643 ReductionData.ReductionOp.is<const Expr *>())
1644 return DSAVarData();
1645 SR = ReductionData.ReductionRange;
1646 BOK = ReductionData.ReductionOp.get<ReductionData::BOKPtrType>();
1647 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1648 "expression for the descriptor is not "
1649 "set.");
1650 TaskgroupDescriptor = I->TaskgroupReductionRef;
1651 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1652 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1653 /*AppliedToPointee=*/false);
1654 }
1655 return DSAVarData();
1656}
1657
1658const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1659 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1660 Expr *&TaskgroupDescriptor) const {
1661 D = getCanonicalDecl(D);
1662 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1663 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1664 const DSAInfo &Data = I->SharingMap.lookup(D);
1665 if (Data.Attributes != OMPC_reduction ||
1666 Data.Modifier != OMPC_REDUCTION_task)
1667 continue;
1668 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1669 if (!ReductionData.ReductionOp ||
1670 !ReductionData.ReductionOp.is<const Expr *>())
1671 return DSAVarData();
1672 SR = ReductionData.ReductionRange;
1673 ReductionRef = ReductionData.ReductionOp.get<const Expr *>();
1674 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1675 "expression for the descriptor is not "
1676 "set.");
1677 TaskgroupDescriptor = I->TaskgroupReductionRef;
1678 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1679 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1680 /*AppliedToPointee=*/false);
1681 }
1682 return DSAVarData();
1683}
1684
1685bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1686 D = D->getCanonicalDecl();
1687 for (const_iterator E = end(); I != E; ++I) {
1688 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1689 isOpenMPTargetExecutionDirective(I->Directive)) {
1690 if (I->CurScope) {
1691 Scope *TopScope = I->CurScope->getParent();
1692 Scope *CurScope = getCurScope();
1693 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1694 CurScope = CurScope->getParent();
1695 return CurScope != TopScope;
1696 }
1697 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1698 if (I->Context == DC)
1699 return true;
1700 return false;
1701 }
1702 }
1703 return false;
1704}
1705
1707 bool AcceptIfMutable = true,
1708 bool *IsClassType = nullptr) {
1709 ASTContext &Context = SemaRef.getASTContext();
1710 Type = Type.getNonReferenceType().getCanonicalType();
1711 bool IsConstant = Type.isConstant(Context);
1712 Type = Context.getBaseElementType(Type);
1713 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1715 : nullptr;
1716 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1717 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1718 RD = CTD->getTemplatedDecl();
1719 if (IsClassType)
1720 *IsClassType = RD;
1721 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1722 RD->hasDefinition() && RD->hasMutableFields());
1723}
1724
1725static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1727 SourceLocation ELoc,
1728 bool AcceptIfMutable = true,
1729 bool ListItemNotVar = false) {
1730 ASTContext &Context = SemaRef.getASTContext();
1731 bool IsClassType;
1732 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
1733 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1734 : IsClassType ? diag::err_omp_const_not_mutable_variable
1735 : diag::err_omp_const_variable;
1736 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseName(CKind);
1737 if (!ListItemNotVar && D) {
1738 const VarDecl *VD = dyn_cast<VarDecl>(D);
1739 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1741 SemaRef.Diag(D->getLocation(),
1742 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1743 << D;
1744 }
1745 return true;
1746 }
1747 return false;
1748}
1749
1750const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1751 bool FromParent) {
1752 D = getCanonicalDecl(D);
1753 DSAVarData DVar;
1754
1755 auto *VD = dyn_cast<VarDecl>(D);
1756 auto TI = Threadprivates.find(D);
1757 if (TI != Threadprivates.end()) {
1758 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1759 DVar.CKind = OMPC_threadprivate;
1760 DVar.Modifier = TI->getSecond().Modifier;
1761 return DVar;
1762 }
1763 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1764 DVar.RefExpr = buildDeclRefExpr(
1765 SemaRef, VD, D->getType().getNonReferenceType(),
1766 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1767 DVar.CKind = OMPC_threadprivate;
1768 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1769 return DVar;
1770 }
1771 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1772 // in a Construct, C/C++, predetermined, p.1]
1773 // Variables appearing in threadprivate directives are threadprivate.
1774 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1775 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1776 SemaRef.getLangOpts().OpenMPUseTLS &&
1777 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1778 (VD && VD->getStorageClass() == SC_Register &&
1779 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1780 DVar.RefExpr = buildDeclRefExpr(
1781 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1782 DVar.CKind = OMPC_threadprivate;
1783 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1784 return DVar;
1785 }
1786 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1787 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1788 !isLoopControlVariable(D).first) {
1789 const_iterator IterTarget =
1790 std::find_if(begin(), end(), [](const SharingMapTy &Data) {
1791 return isOpenMPTargetExecutionDirective(Data.Directive);
1792 });
1793 if (IterTarget != end()) {
1794 const_iterator ParentIterTarget = IterTarget + 1;
1795 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1796 if (isOpenMPLocal(VD, Iter)) {
1797 DVar.RefExpr =
1798 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1799 D->getLocation());
1800 DVar.CKind = OMPC_threadprivate;
1801 return DVar;
1802 }
1803 }
1804 if (!isClauseParsingMode() || IterTarget != begin()) {
1805 auto DSAIter = IterTarget->SharingMap.find(D);
1806 if (DSAIter != IterTarget->SharingMap.end() &&
1807 isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1808 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1809 DVar.CKind = OMPC_threadprivate;
1810 return DVar;
1811 }
1812 const_iterator End = end();
1813 if (!SemaRef.OpenMP().isOpenMPCapturedByRef(
1814 D, std::distance(ParentIterTarget, End),
1815 /*OpenMPCaptureLevel=*/0)) {
1816 DVar.RefExpr =
1817 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1818 IterTarget->ConstructLoc);
1819 DVar.CKind = OMPC_threadprivate;
1820 return DVar;
1821 }
1822 }
1823 }
1824 }
1825
1826 if (isStackEmpty())
1827 // Not in OpenMP execution region and top scope was already checked.
1828 return DVar;
1829
1830 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1831 // in a Construct, C/C++, predetermined, p.4]
1832 // Static data members are shared.
1833 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1834 // in a Construct, C/C++, predetermined, p.7]
1835 // Variables with static storage duration that are declared in a scope
1836 // inside the construct are shared.
1837 if (VD && VD->isStaticDataMember()) {
1838 // Check for explicitly specified attributes.
1839 const_iterator I = begin();
1840 const_iterator EndI = end();
1841 if (FromParent && I != EndI)
1842 ++I;
1843 if (I != EndI) {
1844 auto It = I->SharingMap.find(D);
1845 if (It != I->SharingMap.end()) {
1846 const DSAInfo &Data = It->getSecond();
1847 DVar.RefExpr = Data.RefExpr.getPointer();
1848 DVar.PrivateCopy = Data.PrivateCopy;
1849 DVar.CKind = Data.Attributes;
1850 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1851 DVar.DKind = I->Directive;
1852 DVar.Modifier = Data.Modifier;
1853 DVar.AppliedToPointee = Data.AppliedToPointee;
1854 return DVar;
1855 }
1856 }
1857
1858 DVar.CKind = OMPC_shared;
1859 return DVar;
1860 }
1861
1862 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1863 // The predetermined shared attribute for const-qualified types having no
1864 // mutable members was removed after OpenMP 3.1.
1865 if (SemaRef.LangOpts.OpenMP <= 31) {
1866 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1867 // in a Construct, C/C++, predetermined, p.6]
1868 // Variables with const qualified type having no mutable member are
1869 // shared.
1870 if (isConstNotMutableType(SemaRef, D->getType())) {
1871 // Variables with const-qualified type having no mutable member may be
1872 // listed in a firstprivate clause, even if they are static data members.
1873 DSAVarData DVarTemp = hasInnermostDSA(
1874 D,
1875 [](OpenMPClauseKind C, bool) {
1876 return C == OMPC_firstprivate || C == OMPC_shared;
1877 },
1878 MatchesAlways, FromParent);
1879 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1880 return DVarTemp;
1881
1882 DVar.CKind = OMPC_shared;
1883 return DVar;
1884 }
1885 }
1886
1887 // Explicitly specified attributes and local variables with predetermined
1888 // attributes.
1889 const_iterator I = begin();
1890 const_iterator EndI = end();
1891 if (FromParent && I != EndI)
1892 ++I;
1893 if (I == EndI)
1894 return DVar;
1895 auto It = I->SharingMap.find(D);
1896 if (It != I->SharingMap.end()) {
1897 const DSAInfo &Data = It->getSecond();
1898 DVar.RefExpr = Data.RefExpr.getPointer();
1899 DVar.PrivateCopy = Data.PrivateCopy;
1900 DVar.CKind = Data.Attributes;
1901 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1902 DVar.DKind = I->Directive;
1903 DVar.Modifier = Data.Modifier;
1904 DVar.AppliedToPointee = Data.AppliedToPointee;
1905 }
1906
1907 return DVar;
1908}
1909
1910const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1911 bool FromParent) const {
1912 if (isStackEmpty()) {
1913 const_iterator I;
1914 return getDSA(I, D);
1915 }
1916 D = getCanonicalDecl(D);
1917 const_iterator StartI = begin();
1918 const_iterator EndI = end();
1919 if (FromParent && StartI != EndI)
1920 ++StartI;
1921 return getDSA(StartI, D);
1922}
1923
1924const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1925 unsigned Level) const {
1926 if (getStackSize() <= Level)
1927 return DSAVarData();
1928 D = getCanonicalDecl(D);
1929 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1930 return getDSA(StartI, D);
1931}
1932
1933const DSAStackTy::DSAVarData
1934DSAStackTy::hasDSA(ValueDecl *D,
1935 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1936 DefaultDataSharingAttributes)>
1937 CPred,
1938 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1939 bool FromParent) const {
1940 if (isStackEmpty())
1941 return {};
1942 D = getCanonicalDecl(D);
1943 const_iterator I = begin();
1944 const_iterator EndI = end();
1945 if (FromParent && I != EndI)
1946 ++I;
1947 for (; I != EndI; ++I) {
1948 if (!DPred(I->Directive) &&
1949 !isImplicitOrExplicitTaskingRegion(I->Directive))
1950 continue;
1951 const_iterator NewI = I;
1952 DSAVarData DVar = getDSA(NewI, D);
1953 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1954 return DVar;
1955 }
1956 return {};
1957}
1958
1959const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1960 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1961 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1962 bool FromParent) const {
1963 if (isStackEmpty())
1964 return {};
1965 D = getCanonicalDecl(D);
1966 const_iterator StartI = begin();
1967 const_iterator EndI = end();
1968 if (FromParent && StartI != EndI)
1969 ++StartI;
1970 if (StartI == EndI || !DPred(StartI->Directive))
1971 return {};
1972 const_iterator NewI = StartI;
1973 DSAVarData DVar = getDSA(NewI, D);
1974 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1975 ? DVar
1976 : DSAVarData();
1977}
1978
1979bool DSAStackTy::hasExplicitDSA(
1980 const ValueDecl *D,
1981 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1982 unsigned Level, bool NotLastprivate) const {
1983 if (getStackSize() <= Level)
1984 return false;
1985 D = getCanonicalDecl(D);
1986 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1987 auto I = StackElem.SharingMap.find(D);
1988 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1989 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1990 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1991 return true;
1992 // Check predetermined rules for the loop control variables.
1993 auto LI = StackElem.LCVMap.find(D);
1994 if (LI != StackElem.LCVMap.end())
1995 return CPred(OMPC_private, /*AppliedToPointee=*/false);
1996 return false;
1997}
1998
1999bool DSAStackTy::hasExplicitDirective(
2000 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2001 unsigned Level) const {
2002 if (getStackSize() <= Level)
2003 return false;
2004 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2005 return DPred(StackElem.Directive);
2006}
2007
2008bool DSAStackTy::hasDirective(
2009 const llvm::function_ref<bool(OpenMPDirectiveKind,
2011 DPred,
2012 bool FromParent) const {
2013 // We look only in the enclosing region.
2014 size_t Skip = FromParent ? 2 : 1;
2015 for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
2016 I != E; ++I) {
2017 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2018 return true;
2019 }
2020 return false;
2021}
2022
2023void SemaOpenMP::InitDataSharingAttributesStack() {
2024 VarDataSharingAttributesStack = new DSAStackTy(SemaRef);
2025}
2026
2027#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2028
2029void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2030
2031void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2032 DSAStack->popFunction(OldFSI);
2033}
2034
2036 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2037 "Expected OpenMP device compilation.");
2039}
2040
2041namespace {
2042/// Status of the function emission on the host/device.
2043enum class FunctionEmissionStatus {
2044 Emitted,
2045 Discarded,
2046 Unknown,
2047};
2048} // anonymous namespace
2049
2052 const FunctionDecl *FD) {
2053 assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&
2054 "Expected OpenMP device compilation.");
2055
2056 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2057 if (FD) {
2059 switch (FES) {
2061 Kind = SemaDiagnosticBuilder::K_Immediate;
2062 break;
2064 // TODO: We should always delay diagnostics here in case a target
2065 // region is in a function we do not emit. However, as the
2066 // current diagnostics are associated with the function containing
2067 // the target region and we do not emit that one, we would miss out
2068 // on diagnostics for the target region itself. We need to anchor
2069 // the diagnostics with the new generated function *or* ensure we
2070 // emit diagnostics associated with the surrounding function.
2072 ? SemaDiagnosticBuilder::K_Deferred
2073 : SemaDiagnosticBuilder::K_Immediate;
2074 break;
2077 Kind = SemaDiagnosticBuilder::K_Nop;
2078 break;
2080 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2081 break;
2082 }
2083 }
2084
2085 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2086}
2087
2090 const FunctionDecl *FD) {
2091 assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice &&
2092 "Expected OpenMP host compilation.");
2093
2094 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2095 if (FD) {
2097 switch (FES) {
2099 Kind = SemaDiagnosticBuilder::K_Immediate;
2100 break;
2102 Kind = SemaDiagnosticBuilder::K_Deferred;
2103 break;
2107 Kind = SemaDiagnosticBuilder::K_Nop;
2108 break;
2109 }
2110 }
2111
2112 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2113}
2114
2117 if (LO.OpenMP <= 45) {
2119 return OMPC_DEFAULTMAP_scalar;
2120 return OMPC_DEFAULTMAP_aggregate;
2121 }
2123 return OMPC_DEFAULTMAP_pointer;
2125 return OMPC_DEFAULTMAP_scalar;
2126 return OMPC_DEFAULTMAP_aggregate;
2127}
2128
2129bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2130 unsigned OpenMPCaptureLevel) const {
2131 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2132
2133 ASTContext &Ctx = getASTContext();
2134 bool IsByRef = true;
2135
2136 // Find the directive that is associated with the provided scope.
2137 D = cast<ValueDecl>(D->getCanonicalDecl());
2138 QualType Ty = D->getType();
2139
2140 bool IsVariableUsedInMapClause = false;
2141 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2142 // This table summarizes how a given variable should be passed to the device
2143 // given its type and the clauses where it appears. This table is based on
2144 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2145 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2146 //
2147 // =========================================================================
2148 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2149 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2150 // =========================================================================
2151 // | scl | | | | - | | bycopy|
2152 // | scl | | - | x | - | - | bycopy|
2153 // | scl | | x | - | - | - | null |
2154 // | scl | x | | | - | | byref |
2155 // | scl | x | - | x | - | - | bycopy|
2156 // | scl | x | x | - | - | - | null |
2157 // | scl | | - | - | - | x | byref |
2158 // | scl | x | - | - | - | x | byref |
2159 //
2160 // | agg | n.a. | | | - | | byref |
2161 // | agg | n.a. | - | x | - | - | byref |
2162 // | agg | n.a. | x | - | - | - | null |
2163 // | agg | n.a. | - | - | - | x | byref |
2164 // | agg | n.a. | - | - | - | x[] | byref |
2165 //
2166 // | ptr | n.a. | | | - | | bycopy|
2167 // | ptr | n.a. | - | x | - | - | bycopy|
2168 // | ptr | n.a. | x | - | - | - | null |
2169 // | ptr | n.a. | - | - | - | x | byref |
2170 // | ptr | n.a. | - | - | - | x[] | bycopy|
2171 // | ptr | n.a. | - | - | x | | bycopy|
2172 // | ptr | n.a. | - | - | x | x | bycopy|
2173 // | ptr | n.a. | - | - | x | x[] | bycopy|
2174 // =========================================================================
2175 // Legend:
2176 // scl - scalar
2177 // ptr - pointer
2178 // agg - aggregate
2179 // x - applies
2180 // - - invalid in this combination
2181 // [] - mapped with an array section
2182 // byref - should be mapped by reference
2183 // byval - should be mapped by value
2184 // null - initialize a local variable to null on the device
2185 //
2186 // Observations:
2187 // - All scalar declarations that show up in a map clause have to be passed
2188 // by reference, because they may have been mapped in the enclosing data
2189 // environment.
2190 // - If the scalar value does not fit the size of uintptr, it has to be
2191 // passed by reference, regardless the result in the table above.
2192 // - For pointers mapped by value that have either an implicit map or an
2193 // array section, the runtime library may pass the NULL value to the
2194 // device instead of the value passed to it by the compiler.
2195
2196 if (Ty->isReferenceType())
2197 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2198
2199 // Locate map clauses and see if the variable being captured is referred to
2200 // in any of those clauses. Here we only care about variables, not fields,
2201 // because fields are part of aggregates.
2202 bool IsVariableAssociatedWithSection = false;
2203
2204 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2205 D, Level,
2206 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2208 MapExprComponents,
2209 OpenMPClauseKind WhereFoundClauseKind) {
2210 // Both map and has_device_addr clauses information influences how a
2211 // variable is captured. E.g. is_device_ptr does not require changing
2212 // the default behavior.
2213 if (WhereFoundClauseKind != OMPC_map &&
2214 WhereFoundClauseKind != OMPC_has_device_addr)
2215 return false;
2216
2217 auto EI = MapExprComponents.rbegin();
2218 auto EE = MapExprComponents.rend();
2219
2220 assert(EI != EE && "Invalid map expression!");
2221
2222 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2223 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2224
2225 ++EI;
2226 if (EI == EE)
2227 return false;
2228 auto Last = std::prev(EE);
2229 const auto *UO =
2230 dyn_cast<UnaryOperator>(Last->getAssociatedExpression());
2231 if ((UO && UO->getOpcode() == UO_Deref) ||
2232 isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) ||
2233 isa<ArraySectionExpr>(Last->getAssociatedExpression()) ||
2234 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2235 isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) {
2236 IsVariableAssociatedWithSection = true;
2237 // There is nothing more we need to know about this variable.
2238 return true;
2239 }
2240
2241 // Keep looking for more map info.
2242 return false;
2243 });
2244
2245 if (IsVariableUsedInMapClause) {
2246 // If variable is identified in a map clause it is always captured by
2247 // reference except if it is a pointer that is dereferenced somehow.
2248 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2249 } else {
2250 // By default, all the data that has a scalar type is mapped by copy
2251 // (except for reduction variables).
2252 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2253 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2254 !Ty->isAnyPointerType()) ||
2255 !Ty->isScalarType() ||
2256 DSAStack->isDefaultmapCapturedByRef(
2258 DSAStack->hasExplicitDSA(
2259 D,
2260 [](OpenMPClauseKind K, bool AppliedToPointee) {
2261 return K == OMPC_reduction && !AppliedToPointee;
2262 },
2263 Level);
2264 }
2265 }
2266
2267 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2268 IsByRef =
2269 ((IsVariableUsedInMapClause &&
2270 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2271 OMPD_target) ||
2272 !(DSAStack->hasExplicitDSA(
2273 D,
2274 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2275 return K == OMPC_firstprivate ||
2276 (K == OMPC_reduction && AppliedToPointee);
2277 },
2278 Level, /*NotLastprivate=*/true) ||
2279 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2280 // If the variable is artificial and must be captured by value - try to
2281 // capture by value.
2282 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2283 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2284 // If the variable is implicitly firstprivate and scalar - capture by
2285 // copy
2286 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2287 DSAStack->getDefaultDSA() == DSA_private) &&
2288 !DSAStack->hasExplicitDSA(
2289 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2290 Level) &&
2291 !DSAStack->isLoopControlVariable(D, Level).first);
2292 }
2293
2294 // When passing data by copy, we need to make sure it fits the uintptr size
2295 // and alignment, because the runtime library only deals with uintptr types.
2296 // If it does not fit the uintptr size, we need to pass the data by reference
2297 // instead.
2298 if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) >
2300 Ctx.getAlignOfGlobalVarInChars(Ty, dyn_cast<VarDecl>(D)) >
2301 Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2302 IsByRef = true;
2303 }
2304
2305 return IsByRef;
2306}
2307
2308unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2309 assert(getLangOpts().OpenMP);
2310 return DSAStack->getNestingLevel();
2311}
2312
2314 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2315 DSAStack->isUntiedRegion();
2316}
2317
2319 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2320 !DSAStack->isClauseParsingMode()) ||
2321 DSAStack->hasDirective(
2323 SourceLocation) -> bool {
2325 },
2326 false);
2327}
2328
2330 // Only rebuild for Field.
2331 if (!dyn_cast<FieldDecl>(D))
2332 return false;
2333 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2334 D,
2335 [](OpenMPClauseKind C, bool AppliedToPointee,
2336 DefaultDataSharingAttributes DefaultAttr) {
2337 return isOpenMPPrivate(C) && !AppliedToPointee &&
2338 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2339 },
2340 [](OpenMPDirectiveKind) { return true; },
2341 DSAStack->isClauseParsingMode());
2342 if (DVarPrivate.CKind != OMPC_unknown)
2343 return true;
2344 return false;
2345}
2346
2348 Expr *CaptureExpr, bool WithInit,
2349 DeclContext *CurContext,
2350 bool AsExpression);
2351
2353 unsigned StopAt) {
2354 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2355 D = getCanonicalDecl(D);
2356
2357 auto *VD = dyn_cast<VarDecl>(D);
2358 // Do not capture constexpr variables.
2359 if (VD && VD->isConstexpr())
2360 return nullptr;
2361
2362 // If we want to determine whether the variable should be captured from the
2363 // perspective of the current capturing scope, and we've already left all the
2364 // capturing scopes of the top directive on the stack, check from the
2365 // perspective of its parent directive (if any) instead.
2366 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2367 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2368
2369 // If we are attempting to capture a global variable in a directive with
2370 // 'target' we return true so that this global is also mapped to the device.
2371 //
2372 if (VD && !VD->hasLocalStorage() &&
2374 SemaRef.getCurLambda())) {
2376 DSAStackTy::DSAVarData DVarTop =
2377 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2378 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2379 return VD;
2380 // If the declaration is enclosed in a 'declare target' directive,
2381 // then it should not be captured.
2382 //
2383 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2384 return nullptr;
2385 CapturedRegionScopeInfo *CSI = nullptr;
2386 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2387 llvm::reverse(SemaRef.FunctionScopes),
2388 CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2389 : 0)) {
2390 if (!isa<CapturingScopeInfo>(FSI))
2391 return nullptr;
2392 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2393 if (RSI->CapRegionKind == CR_OpenMP) {
2394 CSI = RSI;
2395 break;
2396 }
2397 }
2398 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2401 DSAStack->getDirective(CSI->OpenMPLevel));
2402 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2403 return VD;
2404 }
2406 // Try to mark variable as declare target if it is used in capturing
2407 // regions.
2408 if (getLangOpts().OpenMP <= 45 &&
2409 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2411 return nullptr;
2412 }
2413 }
2414
2415 if (CheckScopeInfo) {
2416 bool OpenMPFound = false;
2417 for (unsigned I = StopAt + 1; I > 0; --I) {
2419 if (!isa<CapturingScopeInfo>(FSI))
2420 return nullptr;
2421 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2422 if (RSI->CapRegionKind == CR_OpenMP) {
2423 OpenMPFound = true;
2424 break;
2425 }
2426 }
2427 if (!OpenMPFound)
2428 return nullptr;
2429 }
2430
2431 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2432 (!DSAStack->isClauseParsingMode() ||
2433 DSAStack->getParentDirective() != OMPD_unknown)) {
2434 auto &&Info = DSAStack->isLoopControlVariable(D);
2435 if (Info.first ||
2436 (VD && VD->hasLocalStorage() &&
2437 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2438 (VD && DSAStack->isForceVarCapturing()))
2439 return VD ? VD : Info.second;
2440 DSAStackTy::DSAVarData DVarTop =
2441 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2442 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2443 (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee))
2444 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2445 // Threadprivate variables must not be captured.
2446 if (isOpenMPThreadPrivate(DVarTop.CKind))
2447 return nullptr;
2448 // The variable is not private or it is the variable in the directive with
2449 // default(none) clause and not used in any clause.
2450 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2451 D,
2452 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2453 return isOpenMPPrivate(C) && !AppliedToPointee;
2454 },
2455 [](OpenMPDirectiveKind) { return true; },
2456 DSAStack->isClauseParsingMode());
2457 // Global shared must not be captured.
2458 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2459 ((DSAStack->getDefaultDSA() != DSA_none &&
2460 DSAStack->getDefaultDSA() != DSA_private &&
2461 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2462 DVarTop.CKind == OMPC_shared))
2463 return nullptr;
2464 auto *FD = dyn_cast<FieldDecl>(D);
2465 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2466 !DVarPrivate.PrivateCopy) {
2467 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2468 D,
2469 [](OpenMPClauseKind C, bool AppliedToPointee,
2470 DefaultDataSharingAttributes DefaultAttr) {
2471 return isOpenMPPrivate(C) && !AppliedToPointee &&
2472 (DefaultAttr == DSA_firstprivate ||
2473 DefaultAttr == DSA_private);
2474 },
2475 [](OpenMPDirectiveKind) { return true; },
2476 DSAStack->isClauseParsingMode());
2477 if (DVarPrivate.CKind == OMPC_unknown)
2478 return nullptr;
2479
2480 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2481 if (VD)
2482 return VD;
2484 return nullptr;
2487 /*IsImplicit=*/true);
2488 const CXXScopeSpec CS = CXXScopeSpec();
2490 ThisExpr, /*IsArrow=*/true, SourceLocation(),
2493 /*HadMultipleCandidates=*/false, DeclarationNameInfo(), FD->getType(),
2496 SemaRef, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2497 SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2498 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2500 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2501 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2502 return VD;
2503 }
2504 if (DVarPrivate.CKind != OMPC_unknown ||
2505 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2506 DSAStack->getDefaultDSA() == DSA_private ||
2507 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2508 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2509 }
2510 return nullptr;
2511}
2512
2513void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2514 unsigned Level) const {
2515 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2516}
2517
2519 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2520 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2521 DSAStack->loopInit();
2522}
2523
2525 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2526 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2527 DSAStack->resetPossibleLoopCounter();
2528 DSAStack->loopStart();
2529 }
2530}
2531
2533 unsigned CapLevel) const {
2534 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2535 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2536 (!DSAStack->isClauseParsingMode() ||
2537 DSAStack->getParentDirective() != OMPD_unknown)) {
2538 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2539 D,
2540 [](OpenMPClauseKind C, bool AppliedToPointee,
2541 DefaultDataSharingAttributes DefaultAttr) {
2542 return isOpenMPPrivate(C) && !AppliedToPointee &&
2543 DefaultAttr == DSA_private;
2544 },
2545 [](OpenMPDirectiveKind) { return true; },
2546 DSAStack->isClauseParsingMode());
2547 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2548 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2549 !DSAStack->isLoopControlVariable(D).first)
2550 return OMPC_private;
2551 }
2552 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2553 bool IsTriviallyCopyable =
2555 getASTContext()) &&
2556 !D->getType()
2560 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2562 getOpenMPCaptureRegions(CaptureRegions, DKind);
2563 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2564 (IsTriviallyCopyable ||
2565 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2566 if (DSAStack->hasExplicitDSA(
2567 D,
2568 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2569 Level, /*NotLastprivate=*/true))
2570 return OMPC_firstprivate;
2571 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2572 if (DVar.CKind != OMPC_shared &&
2573 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2574 DSAStack->addImplicitTaskFirstprivate(Level, D);
2575 return OMPC_firstprivate;
2576 }
2577 }
2578 }
2579 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2580 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2581 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2582 DSAStack->resetPossibleLoopCounter(D);
2583 DSAStack->loopStart();
2584 return OMPC_private;
2585 }
2586 if ((DSAStack->getPossiblyLoopCunter() == D->getCanonicalDecl() ||
2587 DSAStack->isLoopControlVariable(D).first) &&
2588 !DSAStack->hasExplicitDSA(
2589 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2590 Level) &&
2591 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2592 return OMPC_private;
2593 }
2594 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2595 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2596 DSAStack->isForceVarCapturing() &&
2597 !DSAStack->hasExplicitDSA(
2598 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2599 Level))
2600 return OMPC_private;
2601 }
2602 // User-defined allocators are private since they must be defined in the
2603 // context of target region.
2604 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2605 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2606 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2607 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2608 return OMPC_private;
2609 return (DSAStack->hasExplicitDSA(
2610 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2611 Level) ||
2612 (DSAStack->isClauseParsingMode() &&
2613 DSAStack->getClauseParsingMode() == OMPC_private) ||
2614 // Consider taskgroup reduction descriptor variable a private
2615 // to avoid possible capture in the region.
2616 (DSAStack->hasExplicitDirective(
2617 [](OpenMPDirectiveKind K) {
2618 return K == OMPD_taskgroup ||
2619 ((isOpenMPParallelDirective(K) ||
2620 isOpenMPWorksharingDirective(K)) &&
2621 !isOpenMPSimdDirective(K));
2622 },
2623 Level) &&
2624 DSAStack->isTaskgroupReductionRef(D, Level)))
2625 ? OMPC_private
2626 : OMPC_unknown;
2627}
2628
2630 unsigned Level) {
2631 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2632 D = getCanonicalDecl(D);
2633 OpenMPClauseKind OMPC = OMPC_unknown;
2634 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2635 const unsigned NewLevel = I - 1;
2636 if (DSAStack->hasExplicitDSA(
2637 D,
2638 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2639 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2640 OMPC = K;
2641 return true;
2642 }
2643 return false;
2644 },
2645 NewLevel))
2646 break;
2647 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2648 D, NewLevel,
2650 OpenMPClauseKind) { return true; })) {
2651 OMPC = OMPC_map;
2652 break;
2653 }
2654 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2655 NewLevel)) {
2656 OMPC = OMPC_map;
2657 if (DSAStack->mustBeFirstprivateAtLevel(
2659 OMPC = OMPC_firstprivate;
2660 break;
2661 }
2662 }
2663 if (OMPC != OMPC_unknown)
2664 FD->addAttr(
2665 OMPCaptureKindAttr::CreateImplicit(getASTContext(), unsigned(OMPC)));
2666}
2667
2669 unsigned CaptureLevel) const {
2670 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2671 // Return true if the current level is no longer enclosed in a target region.
2672
2674 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2675 const auto *VD = dyn_cast<VarDecl>(D);
2676 return VD && !VD->hasLocalStorage() &&
2677 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2678 Level) &&
2679 Regions[CaptureLevel] != OMPD_task;
2680}
2681
2683 unsigned CaptureLevel) const {
2684 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2685 // Return true if the current level is no longer enclosed in a target region.
2686
2687 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2688 if (!VD->hasLocalStorage()) {
2690 return true;
2691 DSAStackTy::DSAVarData TopDVar =
2692 DSAStack->getTopDSA(D, /*FromParent=*/false);
2693 unsigned NumLevels =
2694 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2695 if (Level == 0)
2696 // non-file scope static variale with default(firstprivate)
2697 // should be gloabal captured.
2698 return (NumLevels == CaptureLevel + 1 &&
2699 (TopDVar.CKind != OMPC_shared ||
2700 DSAStack->getDefaultDSA() == DSA_firstprivate));
2701 do {
2702 --Level;
2703 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2704 if (DVar.CKind != OMPC_shared)
2705 return true;
2706 } while (Level > 0);
2707 }
2708 }
2709 return true;
2710}
2711
2712void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2713
2715 OMPTraitInfo &TI) {
2716 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2717}
2718
2721 "Not in OpenMP declare variant scope!");
2722
2723 OMPDeclareVariantScopes.pop_back();
2724}
2725
2727 const FunctionDecl *Callee,
2728 SourceLocation Loc) {
2729 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2730 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2731 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2732 // Ignore host functions during device analyzis.
2733 if (getLangOpts().OpenMPIsTargetDevice &&
2734 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2735 return;
2736 // Ignore nohost functions during host analyzis.
2737 if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2738 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2739 return;
2740 const FunctionDecl *FD = Callee->getMostRecentDecl();
2741 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2742 if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2743 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2744 // Diagnose host function called during device codegen.
2745 StringRef HostDevTy =
2746 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2747 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2748 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2749 diag::note_omp_marked_device_type_here)
2750 << HostDevTy;
2751 return;
2752 }
2753 if (!getLangOpts().OpenMPIsTargetDevice &&
2754 !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2755 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2756 // In OpenMP 5.2 or later, if the function has a host variant then allow
2757 // that to be called instead
2758 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2759 for (OMPDeclareVariantAttr *A :
2760 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2761 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2762 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2763 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2764 OMPDeclareTargetDeclAttr::getDeviceType(
2765 VariantFD->getMostRecentDecl());
2766 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2767 return true;
2768 }
2769 return false;
2770 };
2771 if (getLangOpts().OpenMP >= 52 &&
2772 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2773 return;
2774 // Diagnose nohost function called during host codegen.
2775 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2776 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2777 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2778 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2779 diag::note_omp_marked_device_type_here)
2780 << NoHostDevTy;
2781 }
2782}
2783
2785 const DeclarationNameInfo &DirName,
2786 Scope *CurScope, SourceLocation Loc) {
2787 DSAStack->push(DKind, DirName, CurScope, Loc);
2790}
2791
2793 DSAStack->setClauseParsingMode(K);
2794}
2795
2797 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2799}
2800
2801static std::pair<ValueDecl *, bool>
2802getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2803 SourceRange &ERange, bool AllowArraySection = false,
2804 StringRef DiagType = "");
2805
2806/// Check consistency of the reduction clauses.
2807static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2808 ArrayRef<OMPClause *> Clauses) {
2809 bool InscanFound = false;
2810 SourceLocation InscanLoc;
2811 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2812 // A reduction clause without the inscan reduction-modifier may not appear on
2813 // a construct on which a reduction clause with the inscan reduction-modifier
2814 // appears.
2815 for (OMPClause *C : Clauses) {
2816 if (C->getClauseKind() != OMPC_reduction)
2817 continue;
2818 auto *RC = cast<OMPReductionClause>(C);
2819 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2820 InscanFound = true;
2821 InscanLoc = RC->getModifierLoc();
2822 continue;
2823 }
2824 if (RC->getModifier() == OMPC_REDUCTION_task) {
2825 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2826 // A reduction clause with the task reduction-modifier may only appear on
2827 // a parallel construct, a worksharing construct or a combined or
2828 // composite construct for which any of the aforementioned constructs is a
2829 // constituent construct and simd or loop are not constituent constructs.
2830 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2831 if (!(isOpenMPParallelDirective(CurDir) ||
2833 isOpenMPSimdDirective(CurDir))
2834 S.Diag(RC->getModifierLoc(),
2835 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2836 continue;
2837 }
2838 }
2839 if (InscanFound) {
2840 for (OMPClause *C : Clauses) {
2841 if (C->getClauseKind() != OMPC_reduction)
2842 continue;
2843 auto *RC = cast<OMPReductionClause>(C);
2844 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2845 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2846 ? RC->getBeginLoc()
2847 : RC->getModifierLoc(),
2848 diag::err_omp_inscan_reduction_expected);
2849 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2850 continue;
2851 }
2852 for (Expr *Ref : RC->varlists()) {
2853 assert(Ref && "NULL expr in OpenMP nontemporal clause.");
2854 SourceLocation ELoc;
2855 SourceRange ERange;
2856 Expr *SimpleRefExpr = Ref;
2857 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2858 /*AllowArraySection=*/true);
2859 ValueDecl *D = Res.first;
2860 if (!D)
2861 continue;
2862 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2863 S.Diag(Ref->getExprLoc(),
2864 diag::err_omp_reduction_not_inclusive_exclusive)
2865 << Ref->getSourceRange();
2866 }
2867 }
2868 }
2869 }
2870}
2871
2872static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2873 ArrayRef<OMPClause *> Clauses);
2874static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2875 bool WithInit);
2876
2877static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2878 const ValueDecl *D,
2879 const DSAStackTy::DSAVarData &DVar,
2880 bool IsLoopIterVar = false);
2881
2883 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2884 // A variable of class type (or array thereof) that appears in a lastprivate
2885 // clause requires an accessible, unambiguous default constructor for the
2886 // class type, unless the list item is also specified in a firstprivate
2887 // clause.
2888 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2889 for (OMPClause *C : D->clauses()) {
2890 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
2891 SmallVector<Expr *, 8> PrivateCopies;
2892 for (Expr *DE : Clause->varlists()) {
2893 if (DE->isValueDependent() || DE->isTypeDependent()) {
2894 PrivateCopies.push_back(nullptr);
2895 continue;
2896 }
2897 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2898 auto *VD = cast<VarDecl>(DRE->getDecl());
2900 const DSAStackTy::DSAVarData DVar =
2901 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2902 if (DVar.CKind == OMPC_lastprivate) {
2903 // Generate helper private variable and initialize it with the
2904 // default value. The address of the original variable is replaced
2905 // by the address of the new private variable in CodeGen. This new
2906 // variable is not added to IdResolver, so the code in the OpenMP
2907 // region uses original variable for proper diagnostics.
2908 VarDecl *VDPrivate = buildVarDecl(
2909 SemaRef, DE->getExprLoc(), Type.getUnqualifiedType(),
2910 VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2912 if (VDPrivate->isInvalidDecl()) {
2913 PrivateCopies.push_back(nullptr);
2914 continue;
2915 }
2916 PrivateCopies.push_back(buildDeclRefExpr(
2917 SemaRef, VDPrivate, DE->getType(), DE->getExprLoc()));
2918 } else {
2919 // The variable is also a firstprivate, so initialization sequence
2920 // for private copy is generated already.
2921 PrivateCopies.push_back(nullptr);
2922 }
2923 }
2924 Clause->setPrivateCopies(PrivateCopies);
2925 continue;
2926 }
2927 // Finalize nontemporal clause by handling private copies, if any.
2928 if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
2929 SmallVector<Expr *, 8> PrivateRefs;
2930 for (Expr *RefExpr : Clause->varlists()) {
2931 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2932 SourceLocation ELoc;
2933 SourceRange ERange;
2934 Expr *SimpleRefExpr = RefExpr;
2935 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
2936 if (Res.second)
2937 // It will be analyzed later.
2938 PrivateRefs.push_back(RefExpr);
2939 ValueDecl *D = Res.first;
2940 if (!D)
2941 continue;
2942
2943 const DSAStackTy::DSAVarData DVar =
2944 DSAStack->getTopDSA(D, /*FromParent=*/false);
2945 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2946 : SimpleRefExpr);
2947 }
2948 Clause->setPrivateRefs(PrivateRefs);
2949 continue;
2950 }
2951 if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
2952 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2953 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2954 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
2955 if (!DRE)
2956 continue;
2957 ValueDecl *VD = DRE->getDecl();
2958 if (!VD || !isa<VarDecl>(VD))
2959 continue;
2960 DSAStackTy::DSAVarData DVar =
2961 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2962 // OpenMP [2.12.5, target Construct]
2963 // Memory allocators that appear in a uses_allocators clause cannot
2964 // appear in other data-sharing attribute clauses or data-mapping
2965 // attribute clauses in the same construct.
2966 Expr *MapExpr = nullptr;
2967 if (DVar.RefExpr ||
2968 DSAStack->checkMappableExprComponentListsForDecl(
2969 VD, /*CurrentRegionOnly=*/true,
2970 [VD, &MapExpr](
2972 MapExprComponents,
2974 auto MI = MapExprComponents.rbegin();
2975 auto ME = MapExprComponents.rend();
2976 if (MI != ME &&
2977 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2978 VD->getCanonicalDecl()) {
2979 MapExpr = MI->getAssociatedExpression();
2980 return true;
2981 }
2982 return false;
2983 })) {
2984 Diag(D.Allocator->getExprLoc(),
2985 diag::err_omp_allocator_used_in_clauses)
2986 << D.Allocator->getSourceRange();
2987 if (DVar.RefExpr)
2989 else
2990 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2991 << MapExpr->getSourceRange();
2992 }
2993 }
2994 continue;
2995 }
2996 }
2997 // Check allocate clauses.
2999 checkAllocateClauses(SemaRef, DSAStack, D->clauses());
3000 checkReductionClauses(SemaRef, DSAStack, D->clauses());
3001 }
3002
3003 DSAStack->pop();
3006}
3007
3009 Expr *NumIterations, Sema &SemaRef,
3010 Scope *S, DSAStackTy *Stack);
3011
3012namespace {
3013
3014class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3015private:
3016 Sema &SemaRef;
3017
3018public:
3019 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3020 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3021 NamedDecl *ND = Candidate.getCorrectionDecl();
3022 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3023 return VD->hasGlobalStorage() &&
3024 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3025 SemaRef.getCurScope());
3026 }
3027 return false;
3028 }
3029
3030 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3031 return std::make_unique<VarDeclFilterCCC>(*this);
3032 }
3033};
3034
3035class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3036private:
3037 Sema &SemaRef;
3038
3039public:
3040 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3041 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3042 NamedDecl *ND = Candidate.getCorrectionDecl();
3043 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3044 isa<FunctionDecl>(ND))) {
3045 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3046 SemaRef.getCurScope());
3047 }
3048 return false;
3049 }
3050
3051 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3052 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3053 }
3054};
3055
3056} // namespace
3057
3059 CXXScopeSpec &ScopeSpec,
3060 const DeclarationNameInfo &Id,
3061 OpenMPDirectiveKind Kind) {
3062 ASTContext &Context = getASTContext();
3064 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
3065
3066 if (Lookup.isAmbiguous())
3067 return ExprError();
3068
3069 VarDecl *VD;
3070 if (!Lookup.isSingleResult()) {
3071 VarDeclFilterCCC CCC(SemaRef);
3072 if (TypoCorrection Corrected =
3073 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
3076 Corrected,
3077 SemaRef.PDiag(Lookup.empty() ? diag::err_undeclared_var_use_suggest
3078 : diag::err_omp_expected_var_arg_suggest)
3079 << Id.getName());
3080 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3081 } else {
3082 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3083 : diag::err_omp_expected_var_arg)
3084 << Id.getName();
3085 return ExprError();
3086 }
3087 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3088 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3089 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3090 return ExprError();
3091 }
3092 Lookup.suppressDiagnostics();
3093
3094 // OpenMP [2.9.2, Syntax, C/C++]
3095 // Variables must be file-scope, namespace-scope, or static block-scope.
3096 if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
3097 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3098 << getOpenMPDirectiveName(Kind) << !VD->isStaticLocal();
3099 bool IsDecl =
3101 Diag(VD->getLocation(),
3102 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3103 << VD;
3104 return ExprError();
3105 }
3106
3107 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3108 NamedDecl *ND = CanonicalVD;
3109 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3110 // A threadprivate directive for file-scope variables must appear outside
3111 // any definition or declaration.
3112 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3114 Diag(Id.getLoc(), diag::err_omp_var_scope)
3115 << getOpenMPDirectiveName(Kind) << VD;
3116 bool IsDecl =
3118 Diag(VD->getLocation(),
3119 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3120 << VD;
3121 return ExprError();
3122 }
3123 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3124 // A threadprivate directive for static class member variables must appear
3125 // in the class definition, in the same scope in which the member
3126 // variables are declared.
3127 if (CanonicalVD->isStaticDataMember() &&
3128 !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) {
3129 Diag(Id.getLoc(), diag::err_omp_var_scope)
3130 << getOpenMPDirectiveName(Kind) << VD;
3131 bool IsDecl =
3133 Diag(VD->getLocation(),
3134 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3135 << VD;
3136 return ExprError();
3137 }
3138 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3139 // A threadprivate directive for namespace-scope variables must appear
3140 // outside any definition or declaration other than the namespace
3141 // definition itself.
3142 if (CanonicalVD->getDeclContext()->isNamespace() &&
3145 CanonicalVD->getDeclContext()))) {
3146 Diag(Id.getLoc(), diag::err_omp_var_scope)
3147 << getOpenMPDirectiveName(Kind) << VD;
3148 bool IsDecl =
3150 Diag(VD->getLocation(),
3151 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3152 << VD;
3153 return ExprError();
3154 }
3155 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3156 // A threadprivate directive for static block-scope variables must appear
3157 // in the scope of the variable and not in a nested scope.
3158 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3160 Diag(Id.getLoc(), diag::err_omp_var_scope)
3161 << getOpenMPDirectiveName(Kind) << VD;
3162 bool IsDecl =
3164 Diag(VD->getLocation(),
3165 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3166 << VD;
3167 return ExprError();
3168 }
3169
3170 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3171 // A threadprivate directive must lexically precede all references to any
3172 // of the variables in its list.
3173 if (Kind == OMPD_threadprivate && VD->isUsed() &&
3174 !DSAStack->isThreadPrivate(VD)) {
3175 Diag(Id.getLoc(), diag::err_omp_var_used)
3176 << getOpenMPDirectiveName(Kind) << VD;
3177 return ExprError();
3178 }
3179
3180 QualType ExprType = VD->getType().getNonReferenceType();
3182 SourceLocation(), VD,
3183 /*RefersToEnclosingVariableOrCapture=*/false,
3184 Id.getLoc(), ExprType, VK_LValue);
3185}
3186
3189 ArrayRef<Expr *> VarList) {
3190 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3193 }
3194 return nullptr;
3195}
3196
3197namespace {
3198class LocalVarRefChecker final
3199 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3200 Sema &SemaRef;
3201
3202public:
3203 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3204 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3205 if (VD->hasLocalStorage()) {
3206 SemaRef.Diag(E->getBeginLoc(),
3207 diag::err_omp_local_var_in_threadprivate_init)
3208 << E->getSourceRange();
3209 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3210 << VD << VD->getSourceRange();
3211 return true;
3212 }
3213 }
3214 return false;
3215 }
3216 bool VisitStmt(const Stmt *S) {
3217 for (const Stmt *Child : S->children()) {
3218 if (Child && Visit(Child))
3219 return true;
3220 }
3221 return false;
3222 }
3223 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3224};
3225} // namespace
3226
3229 ArrayRef<Expr *> VarList) {
3230 ASTContext &Context = getASTContext();
3232 for (Expr *RefExpr : VarList) {
3233 auto *DE = cast<DeclRefExpr>(RefExpr);
3234 auto *VD = cast<VarDecl>(DE->getDecl());
3235 SourceLocation ILoc = DE->getExprLoc();
3236
3237 // Mark variable as used.
3238 VD->setReferenced();
3239 VD->markUsed(Context);
3240
3241 QualType QType = VD->getType();
3242 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3243 // It will be analyzed later.
3244 Vars.push_back(DE);
3245 continue;
3246 }
3247
3248 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3249 // A threadprivate variable must not have an incomplete type.
3251 ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) {
3252 continue;
3253 }
3254
3255 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3256 // A threadprivate variable must not have a reference type.
3257 if (VD->getType()->isReferenceType()) {
3258 Diag(ILoc, diag::err_omp_ref_type_arg)
3259 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
3260 bool IsDecl =
3262 Diag(VD->getLocation(),
3263 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3264 << VD;
3265 continue;
3266 }
3267
3268 // Check if this is a TLS variable. If TLS is not being supported, produce
3269 // the corresponding diagnostic.
3270 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3271 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3272 getLangOpts().OpenMPUseTLS &&
3273 getASTContext().getTargetInfo().isTLSSupported())) ||
3274 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3275 !VD->isLocalVarDecl())) {
3276 Diag(ILoc, diag::err_omp_var_thread_local)
3277 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3278 bool IsDecl =
3280 Diag(VD->getLocation(),
3281 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3282 << VD;
3283 continue;
3284 }
3285
3286 // Check if initial value of threadprivate variable reference variable with
3287 // local storage (it is not supported by runtime).
3288 if (const Expr *Init = VD->getAnyInitializer()) {
3289 LocalVarRefChecker Checker(SemaRef);
3290 if (Checker.Visit(Init))
3291 continue;
3292 }
3293
3294 Vars.push_back(RefExpr);
3295 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3296 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3297 Context, SourceRange(Loc, Loc)));
3298 if (ASTMutationListener *ML = Context.getASTMutationListener())
3299 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3300 }
3301 OMPThreadPrivateDecl *D = nullptr;
3302 if (!Vars.empty()) {
3304 Loc, Vars);
3305 D->setAccess(AS_public);
3306 }
3307 return D;
3308}
3309
3310static OMPAllocateDeclAttr::AllocatorTypeTy
3311getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3312 if (!Allocator)
3313 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3314 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3315 Allocator->isInstantiationDependent() ||
3316 Allocator->containsUnexpandedParameterPack())
3317 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3318 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3319 llvm::FoldingSetNodeID AEId;
3320 const Expr *AE = Allocator->IgnoreParenImpCasts();
3321 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3322 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3323 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3324 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3325 llvm::FoldingSetNodeID DAEId;
3326 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3327 /*Canonical=*/true);
3328 if (AEId == DAEId) {
3329 AllocatorKindRes = AllocatorKind;
3330 break;
3331 }
3332 }
3333 return AllocatorKindRes;
3334}
3335
3337 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3338 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3339 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3340 return false;
3341 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3342 Expr *PrevAllocator = A->getAllocator();
3343 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3344 getAllocatorKind(S, Stack, PrevAllocator);
3345 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3346 if (AllocatorsMatch &&
3347 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3348 Allocator && PrevAllocator) {
3349 const Expr *AE = Allocator->IgnoreParenImpCasts();
3350 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3351 llvm::FoldingSetNodeID AEId, PAEId;
3352 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3353 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3354 AllocatorsMatch = AEId == PAEId;
3355 }
3356 if (!AllocatorsMatch) {
3357 SmallString<256> AllocatorBuffer;
3358 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3359 if (Allocator)
3360 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3361 SmallString<256> PrevAllocatorBuffer;
3362 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3363 if (PrevAllocator)
3364 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3365 S.getPrintingPolicy());
3366
3367 SourceLocation AllocatorLoc =
3368 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3369 SourceRange AllocatorRange =
3370 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3371 SourceLocation PrevAllocatorLoc =
3372 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3373 SourceRange PrevAllocatorRange =
3374 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3375 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3376 << (Allocator ? 1 : 0) << AllocatorStream.str()
3377 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3378 << AllocatorRange;
3379 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3380 << PrevAllocatorRange;
3381 return true;
3382 }
3383 return false;
3384}
3385
3386static void
3388 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3389 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3390 if (VD->hasAttr<OMPAllocateDeclAttr>())
3391 return;
3392 if (Alignment &&
3393 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3394 Alignment->isInstantiationDependent() ||
3395 Alignment->containsUnexpandedParameterPack()))
3396 // Apply later when we have a usable value.
3397 return;
3398 if (Allocator &&
3399 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3400 Allocator->isInstantiationDependent() ||
3401 Allocator->containsUnexpandedParameterPack()))
3402 return;
3403 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3404 Allocator, Alignment, SR);
3405 VD->addAttr(A);
3407 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3408}
3409
3412 DeclContext *Owner) {
3413 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3414 Expr *Alignment = nullptr;
3415 Expr *Allocator = nullptr;
3416 if (Clauses.empty()) {
3417 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3418 // allocate directives that appear in a target region must specify an
3419 // allocator clause unless a requires directive with the dynamic_allocators
3420 // clause is present in the same compilation unit.
3421 if (getLangOpts().OpenMPIsTargetDevice &&
3422 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3423 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3424 } else {
3425 for (const OMPClause *C : Clauses)
3426 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3427 Allocator = AC->getAllocator();
3428 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3429 Alignment = AC->getAlignment();
3430 else
3431 llvm_unreachable("Unexpected clause on allocate directive");
3432 }
3433 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3434 getAllocatorKind(SemaRef, DSAStack, Allocator);
3436 for (Expr *RefExpr : VarList) {
3437 auto *DE = cast<DeclRefExpr>(RefExpr);
3438 auto *VD = cast<VarDecl>(DE->getDecl());
3439
3440 // Check if this is a TLS variable or global register.
3441 if (VD->getTLSKind() != VarDecl::TLS_None ||
3442 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3443 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3444 !VD->isLocalVarDecl()))
3445 continue;
3446
3447 // If the used several times in the allocate directive, the same allocator
3448 // must be used.
3450 AllocatorKind, Allocator))
3451 continue;
3452
3453 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3454 // If a list item has a static storage type, the allocator expression in the
3455 // allocator clause must be a constant expression that evaluates to one of
3456 // the predefined memory allocator values.
3457 if (Allocator && VD->hasGlobalStorage()) {
3458 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3459 Diag(Allocator->getExprLoc(),
3460 diag::err_omp_expected_predefined_allocator)
3461 << Allocator->getSourceRange();
3462 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3464 Diag(VD->getLocation(),
3465 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3466 << VD;
3467 continue;
3468 }
3469 }
3470
3471 Vars.push_back(RefExpr);
3472 applyOMPAllocateAttribute(SemaRef, VD, AllocatorKind, Allocator, Alignment,
3473 DE->getSourceRange());
3474 }
3475 if (Vars.empty())
3476 return nullptr;
3477 if (!Owner)
3478 Owner = SemaRef.getCurLexicalContext();
3479 auto *D = OMPAllocateDecl::Create(getASTContext(), Owner, Loc, Vars, Clauses);
3480 D->setAccess(AS_public);
3481 Owner->addDecl(D);
3483}
3484
3487 ArrayRef<OMPClause *> ClauseList) {
3488 OMPRequiresDecl *D = nullptr;
3490 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3491 } else {
3492 D = CheckOMPRequiresDecl(Loc, ClauseList);
3493 if (D) {
3495 DSAStack->addRequiresDecl(D);
3496 }
3497 }
3499}
3500
3502 OpenMPDirectiveKind DKind,
3503 ArrayRef<std::string> Assumptions,
3504 bool SkippedClauses) {
3505 if (!SkippedClauses && Assumptions.empty())
3506 Diag(Loc, diag::err_omp_no_clause_for_directive)
3507 << llvm::omp::getAllAssumeClauseOptions()
3508 << llvm::omp::getOpenMPDirectiveName(DKind);
3509
3510 auto *AA =
3511 OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc);
3512 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3513 OMPAssumeScoped.push_back(AA);
3514 return;
3515 }
3516
3517 // Global assumes without assumption clauses are ignored.
3518 if (Assumptions.empty())
3519 return;
3520
3521 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3522 "Unexpected omp assumption directive!");
3523 OMPAssumeGlobal.push_back(AA);
3524
3525 // The OMPAssumeGlobal scope above will take care of new declarations but
3526 // we also want to apply the assumption to existing ones, e.g., to
3527 // declarations in included headers. To this end, we traverse all existing
3528 // declaration contexts and annotate function declarations here.
3529 SmallVector<DeclContext *, 8> DeclContexts;
3530 auto *Ctx = SemaRef.CurContext;
3531 while (Ctx->getLexicalParent())
3532 Ctx = Ctx->getLexicalParent();
3533 DeclContexts.push_back(Ctx);
3534 while (!DeclContexts.empty()) {
3535 DeclContext *DC = DeclContexts.pop_back_val();
3536 for (auto *SubDC : DC->decls()) {
3537 if (SubDC->isInvalidDecl())
3538 continue;
3539 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3540 DeclContexts.push_back(CTD->getTemplatedDecl());
3541 llvm::append_range(DeclContexts, CTD->specializations());
3542 continue;
3543 }
3544 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3545 DeclContexts.push_back(DC);
3546 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3547 F->addAttr(AA);
3548 continue;
3549 }
3550 }
3551 }
3552}
3553
3555 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3556 OMPAssumeScoped.pop_back();
3557}
3558
3561 ArrayRef<OMPClause *> ClauseList) {
3562 /// For target specific clauses, the requires directive cannot be
3563 /// specified after the handling of any of the target regions in the
3564 /// current compilation unit.
3565 ArrayRef<SourceLocation> TargetLocations =
3566 DSAStack->getEncounteredTargetLocs();
3567 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3568 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3569 for (const OMPClause *CNew : ClauseList) {
3570 // Check if any of the requires clauses affect target regions.
3571 if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3572 isa<OMPUnifiedAddressClause>(CNew) ||
3573 isa<OMPReverseOffloadClause>(CNew) ||
3574 isa<OMPDynamicAllocatorsClause>(CNew)) {
3575 Diag(Loc, diag::err_omp_directive_before_requires)
3576 << "target" << getOpenMPClauseName(CNew->getClauseKind());
3577 for (SourceLocation TargetLoc : TargetLocations) {
3578 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3579 << "target";
3580 }
3581 } else if (!AtomicLoc.isInvalid() &&
3582 isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3583 Diag(Loc, diag::err_omp_directive_before_requires)
3584 << "atomic" << getOpenMPClauseName(CNew->getClauseKind());
3585 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3586 << "atomic";
3587 }
3588 }
3589 }
3590
3591 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3593 getASTContext(), SemaRef.getCurLexicalContext(), Loc, ClauseList);
3594 return nullptr;
3595}
3596
3597static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3598 const ValueDecl *D,
3599 const DSAStackTy::DSAVarData &DVar,
3600 bool IsLoopIterVar) {
3601 if (DVar.RefExpr) {
3602 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3603 << getOpenMPClauseName(DVar.CKind);
3604 return;
3605 }
3606 enum {
3607 PDSA_StaticMemberShared,
3608 PDSA_StaticLocalVarShared,
3609 PDSA_LoopIterVarPrivate,
3610 PDSA_LoopIterVarLinear,
3611 PDSA_LoopIterVarLastprivate,
3612 PDSA_ConstVarShared,
3613 PDSA_GlobalVarShared,
3614 PDSA_TaskVarFirstprivate,
3615 PDSA_LocalVarPrivate,
3616 PDSA_Implicit
3617 } Reason = PDSA_Implicit;
3618 bool ReportHint = false;
3619 auto ReportLoc = D->getLocation();
3620 auto *VD = dyn_cast<VarDecl>(D);
3621 if (IsLoopIterVar) {
3622 if (DVar.CKind == OMPC_private)
3623 Reason = PDSA_LoopIterVarPrivate;
3624 else if (DVar.CKind == OMPC_lastprivate)
3625 Reason = PDSA_LoopIterVarLastprivate;
3626 else
3627 Reason = PDSA_LoopIterVarLinear;
3628 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3629 DVar.CKind == OMPC_firstprivate) {
3630 Reason = PDSA_TaskVarFirstprivate;
3631 ReportLoc = DVar.ImplicitDSALoc;
3632 } else if (VD && VD->isStaticLocal())
3633 Reason = PDSA_StaticLocalVarShared;
3634 else if (VD && VD->isStaticDataMember())
3635 Reason = PDSA_StaticMemberShared;
3636 else if (VD && VD->isFileVarDecl())
3637 Reason = PDSA_GlobalVarShared;
3638 else if (D->getType().isConstant(SemaRef.getASTContext()))
3639 Reason = PDSA_ConstVarShared;
3640 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3641 ReportHint = true;
3642 Reason = PDSA_LocalVarPrivate;
3643 }
3644 if (Reason != PDSA_Implicit) {
3645 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3646 << Reason << ReportHint
3647 << getOpenMPDirectiveName(Stack->getCurrentDirective());
3648 } else if (DVar.ImplicitDSALoc.isValid()) {
3649 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3650 << getOpenMPClauseName(DVar.CKind);
3651 }
3652}
3653
3656 bool IsAggregateOrDeclareTarget) {
3658 switch (M) {
3659 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3660 Kind = OMPC_MAP_alloc;
3661 break;
3662 case OMPC_DEFAULTMAP_MODIFIER_to:
3663 Kind = OMPC_MAP_to;
3664 break;
3665 case OMPC_DEFAULTMAP_MODIFIER_from:
3666 Kind = OMPC_MAP_from;
3667 break;
3668 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3669 Kind = OMPC_MAP_tofrom;
3670 break;
3671 case OMPC_DEFAULTMAP_MODIFIER_present:
3672 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3673 // If implicit-behavior is present, each variable referenced in the
3674 // construct in the category specified by variable-category is treated as if
3675 // it had been listed in a map clause with the map-type of alloc and
3676 // map-type-modifier of present.
3677 Kind = OMPC_MAP_alloc;
3678 break;
3679 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3681 llvm_unreachable("Unexpected defaultmap implicit behavior");
3682 case OMPC_DEFAULTMAP_MODIFIER_none:
3683 case OMPC_DEFAULTMAP_MODIFIER_default:
3685 // IsAggregateOrDeclareTarget could be true if:
3686 // 1. the implicit behavior for aggregate is tofrom
3687 // 2. it's a declare target link
3688 if (IsAggregateOrDeclareTarget) {
3689 Kind = OMPC_MAP_tofrom;
3690 break;
3691 }
3692 llvm_unreachable("Unexpected defaultmap implicit behavior");
3693 }
3694 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3695 return Kind;
3696}
3697
3698namespace {
3699class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3700 DSAStackTy *Stack;
3701 Sema &SemaRef;
3702 bool ErrorFound = false;
3703 bool TryCaptureCXXThisMembers = false;
3704 CapturedStmt *CS = nullptr;
3705 const static unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3706 llvm::SmallVector<Expr *, 4> ImplicitFirstprivate;
3707 llvm::SmallVector<Expr *, 4> ImplicitPrivate;
3708 llvm::SmallVector<Expr *, 4> ImplicitMap[DefaultmapKindNum][OMPC_MAP_delete];
3710 ImplicitMapModifier[DefaultmapKindNum];
3711 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3712 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3713
3714 void VisitSubCaptures(OMPExecutableDirective *S) {
3715 // Check implicitly captured variables.
3716 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3717 return;
3718 if (S->getDirectiveKind() == OMPD_atomic ||
3719 S->getDirectiveKind() == OMPD_critical ||
3720 S->getDirectiveKind() == OMPD_section ||
3721 S->getDirectiveKind() == OMPD_master ||
3722 S->getDirectiveKind() == OMPD_masked ||
3723 S->getDirectiveKind() == OMPD_scope ||
3724 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3725 Visit(S->getAssociatedStmt());
3726 return;
3727 }
3728 visitSubCaptures(S->getInnermostCapturedStmt());
3729 // Try to capture inner this->member references to generate correct mappings
3730 // and diagnostics.
3731 if (TryCaptureCXXThisMembers ||
3732 (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
3733 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3734 [](const CapturedStmt::Capture &C) {
3735 return C.capturesThis();
3736 }))) {
3737 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3738 TryCaptureCXXThisMembers = true;
3739 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3740 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3741 }
3742 // In tasks firstprivates are not captured anymore, need to analyze them
3743 // explicitly.
3744 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3745 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3746 for (OMPClause *C : S->clauses())
3747 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3748 for (Expr *Ref : FC->varlists())
3749 Visit(Ref);
3750 }
3751 }
3752 }
3753
3754public:
3755 void VisitDeclRefExpr(DeclRefExpr *E) {
3756 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3759 return;
3760 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3761 // Check the datasharing rules for the expressions in the clauses.
3762 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3763 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3764 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3765 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3766 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3767 Visit(CED->getInit());
3768 return;
3769 }
3770 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3771 // Do not analyze internal variables and do not enclose them into
3772 // implicit clauses.
3773 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3774 return;
3775 VD = VD->getCanonicalDecl();
3776 // Skip internally declared variables.
3777 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3778 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3779 !Stack->isImplicitTaskFirstprivate(VD))
3780 return;
3781 // Skip allocators in uses_allocators clauses.
3782 if (Stack->isUsesAllocatorsDecl(VD))
3783 return;
3784
3785 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3786 // Check if the variable has explicit DSA set and stop analysis if it so.
3787 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3788 return;
3789
3790 // Skip internally declared static variables.
3791 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3792 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3793 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3794 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3795 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3796 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3797 !Stack->isImplicitTaskFirstprivate(VD))
3798 return;
3799
3800 SourceLocation ELoc = E->getExprLoc();
3801 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3802 // The default(none) clause requires that each variable that is referenced
3803 // in the construct, and does not have a predetermined data-sharing
3804 // attribute, must have its data-sharing attribute explicitly determined
3805 // by being listed in a data-sharing attribute clause.
3806 if (DVar.CKind == OMPC_unknown &&
3807 (Stack->getDefaultDSA() == DSA_none ||
3808 Stack->getDefaultDSA() == DSA_private ||
3809 Stack->getDefaultDSA() == DSA_firstprivate) &&
3810 isImplicitOrExplicitTaskingRegion(DKind) &&
3811 VarsWithInheritedDSA.count(VD) == 0) {
3812 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3813 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3814 Stack->getDefaultDSA() == DSA_private)) {
3815 DSAStackTy::DSAVarData DVar =
3816 Stack->getImplicitDSA(VD, /*FromParent=*/false);
3817 InheritedDSA = DVar.CKind == OMPC_unknown;
3818 }
3819 if (InheritedDSA)
3820 VarsWithInheritedDSA[VD] = E;
3821 if (Stack->getDefaultDSA() == DSA_none)
3822 return;
3823 }
3824
3825 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3826 // If implicit-behavior is none, each variable referenced in the
3827 // construct that does not have a predetermined data-sharing attribute
3828 // and does not appear in a to or link clause on a declare target
3829 // directive must be listed in a data-mapping attribute clause, a
3830 // data-sharing attribute clause (including a data-sharing attribute
3831 // clause on a combined construct where target. is one of the
3832 // constituent constructs), or an is_device_ptr clause.
3833 OpenMPDefaultmapClauseKind ClauseKind =
3835 if (SemaRef.getLangOpts().OpenMP >= 50) {
3836 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3837 OMPC_DEFAULTMAP_MODIFIER_none;
3838 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3839 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3840 // Only check for data-mapping attribute and is_device_ptr here
3841 // since we have already make sure that the declaration does not
3842 // have a data-sharing attribute above
3843 if (!Stack->checkMappableExprComponentListsForDecl(
3844 VD, /*CurrentRegionOnly=*/true,
3846 MapExprComponents,
3848 auto MI = MapExprComponents.rbegin();
3849 auto ME = MapExprComponents.rend();
3850 return MI != ME && MI->getAssociatedDeclaration() == VD;
3851 })) {
3852 VarsWithInheritedDSA[VD] = E;
3853 return;
3854 }
3855 }
3856 }
3857 if (SemaRef.getLangOpts().OpenMP > 50) {
3858 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3859 OMPC_DEFAULTMAP_MODIFIER_present;
3860 if (IsModifierPresent) {
3861 if (!llvm::is_contained(ImplicitMapModifier[ClauseKind],
3862 OMPC_MAP_MODIFIER_present)) {
3863 ImplicitMapModifier[ClauseKind].push_back(
3864 OMPC_MAP_MODIFIER_present);
3865 }
3866 }
3867 }
3868
3870 !Stack->isLoopControlVariable(VD).first) {
3871 if (!Stack->checkMappableExprComponentListsForDecl(
3872 VD, /*CurrentRegionOnly=*/true,
3874 StackComponents,
3876 if (SemaRef.LangOpts.OpenMP >= 50)
3877 return !StackComponents.empty();
3878 // Variable is used if it has been marked as an array, array
3879 // section, array shaping or the variable iself.
3880 return StackComponents.size() == 1 ||
3881 llvm::all_of(
3882 llvm::drop_begin(llvm::reverse(StackComponents)),
3883 [](const OMPClauseMappableExprCommon::
3884 MappableComponent &MC) {
3885 return MC.getAssociatedDeclaration() ==
3886 nullptr &&
3887 (isa<ArraySectionExpr>(
3888 MC.getAssociatedExpression()) ||
3889 isa<OMPArrayShapingExpr>(
3890 MC.getAssociatedExpression()) ||
3891 isa<ArraySubscriptExpr>(
3892 MC.getAssociatedExpression()));
3893 });
3894 })) {
3895 bool IsFirstprivate = false;
3896 // By default lambdas are captured as firstprivates.
3897 if (const auto *RD =
3899 IsFirstprivate = RD->isLambda();
3900 IsFirstprivate =
3901 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3902 if (IsFirstprivate) {
3903 ImplicitFirstprivate.emplace_back(E);
3904 } else {
3906 Stack->getDefaultmapModifier(ClauseKind);
3908 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3909 ImplicitMap[ClauseKind][Kind].emplace_back(E);
3910 }
3911 return;
3912 }
3913 }
3914
3915 // OpenMP [2.9.3.6, Restrictions, p.2]
3916 // A list item that appears in a reduction clause of the innermost
3917 // enclosing worksharing or parallel construct may not be accessed in an
3918 // explicit task.
3919 DVar = Stack->hasInnermostDSA(
3920 VD,
3921 [](OpenMPClauseKind C, bool AppliedToPointee) {
3922 return C == OMPC_reduction && !AppliedToPointee;
3923 },
3924 [](OpenMPDirectiveKind K) {
3925 return isOpenMPParallelDirective(K) ||
3927 },
3928 /*FromParent=*/true);
3929 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3930 ErrorFound = true;
3931 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3932 reportOriginalDsa(SemaRef, Stack, VD, DVar);
3933 return;
3934 }
3935
3936 // Define implicit data-sharing attributes for task.
3937 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
3938 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
3939 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3940 DVar.CKind == OMPC_firstprivate) ||
3941 (Stack->getDefaultDSA() == DSA_private &&
3942 DVar.CKind == OMPC_private)) &&
3943 !DVar.RefExpr)) &&
3944 !Stack->isLoopControlVariable(VD).first) {
3945 if (Stack->getDefaultDSA() == DSA_private)
3946 ImplicitPrivate.push_back(E);
3947 else
3948 ImplicitFirstprivate.push_back(E);
3949 return;
3950 }
3951
3952 // Store implicitly used globals with declare target link for parent
3953 // target.
3954 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
3955 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3956 Stack->addToParentTargetRegionLinkGlobals(E);
3957 return;
3958 }
3959 }
3960 }
3961 void VisitMemberExpr(MemberExpr *E) {
3962 if (E->isTypeDependent() || E->isValueDependent() ||
3964 return;
3965 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
3966 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3967 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
3968 if (!FD)
3969 return;
3970 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
3971 // Check if the variable has explicit DSA set and stop analysis if it
3972 // so.
3973 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
3974 return;
3975
3977 !Stack->isLoopControlVariable(FD).first &&
3978 !Stack->checkMappableExprComponentListsForDecl(
3979 FD, /*CurrentRegionOnly=*/true,
3981 StackComponents,
3983 return isa<CXXThisExpr>(
3984 cast<MemberExpr>(
3985 StackComponents.back().getAssociatedExpression())
3986 ->getBase()
3987 ->IgnoreParens());
3988 })) {
3989 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
3990 // A bit-field cannot appear in a map clause.
3991 //
3992 if (FD->isBitField())
3993 return;
3994
3995 // Check to see if the member expression is referencing a class that
3996 // has already been explicitly mapped
3997 if (Stack->isClassPreviouslyMapped(TE->getType()))
3998 return;
3999
4001 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4002 OpenMPDefaultmapClauseKind ClauseKind =
4005 Modifier, /*IsAggregateOrDeclareTarget*/ true);
4006 ImplicitMap[ClauseKind][Kind].emplace_back(E);
4007 return;
4008 }
4009
4010 SourceLocation ELoc = E->getExprLoc();
4011 // OpenMP [2.9.3.6, Restrictions, p.2]
4012 // A list item that appears in a reduction clause of the innermost
4013 // enclosing worksharing or parallel construct may not be accessed in
4014 // an explicit task.
4015 DVar = Stack->hasInnermostDSA(
4016 FD,
4017 [](OpenMPClauseKind C, bool AppliedToPointee) {
4018 return C == OMPC_reduction && !AppliedToPointee;
4019 },
4020 [](OpenMPDirectiveKind K) {
4021 return isOpenMPParallelDirective(K) ||
4023 },
4024 /*FromParent=*/true);
4025 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4026 ErrorFound = true;
4027 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4028 reportOriginalDsa(SemaRef, Stack, FD, DVar);
4029 return;
4030 }
4031
4032 // Define implicit data-sharing attributes for task.
4033 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4034 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4035 !Stack->isLoopControlVariable(FD).first) {
4036 // Check if there is a captured expression for the current field in the
4037 // region. Do not mark it as firstprivate unless there is no captured
4038 // expression.
4039 // TODO: try to make it firstprivate.
4040 if (DVar.CKind != OMPC_unknown)
4041 ImplicitFirstprivate.push_back(E);
4042 }
4043 return;
4044 }
4047 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4048 Stack->getCurrentDirective(),
4049 /*NoDiagnose=*/true))
4050 return;
4051 const auto *VD = cast<ValueDecl>(
4052 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4053 if (!Stack->checkMappableExprComponentListsForDecl(
4054 VD, /*CurrentRegionOnly=*/true,
4055 [&CurComponents](
4057 StackComponents,
4059 auto CCI = CurComponents.rbegin();
4060 auto CCE = CurComponents.rend();
4061 for (const auto &SC : llvm::reverse(StackComponents)) {
4062 // Do both expressions have the same kind?
4063 if (CCI->getAssociatedExpression()->getStmtClass() !=
4064 SC.getAssociatedExpression()->getStmtClass())
4065 if (!((isa<ArraySectionExpr>(
4066 SC.getAssociatedExpression()) ||
4067 isa<OMPArrayShapingExpr>(
4068 SC.getAssociatedExpression())) &&
4069 isa<ArraySubscriptExpr>(
4070 CCI->getAssociatedExpression())))
4071 return false;
4072
4073 const Decl *CCD = CCI->getAssociatedDeclaration();
4074 const Decl *SCD = SC.getAssociatedDeclaration();
4075 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4076 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4077 if (SCD != CCD)
4078 return false;
4079 std::advance(CCI, 1);
4080 if (CCI == CCE)
4081 break;
4082 }
4083 return true;
4084 })) {
4085 Visit(E->getBase());
4086 }
4087 } else if (!TryCaptureCXXThisMembers) {
4088 Visit(E->getBase());
4089 }
4090 }
4091 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4092 for (OMPClause *C : S->clauses()) {
4093 // Skip analysis of arguments of private clauses for task|target
4094 // directives.
4095 if (isa_and_nonnull<OMPPrivateClause>(C))
4096 continue;
4097 // Skip analysis of arguments of implicitly defined firstprivate clause
4098 // for task|target directives.
4099 // Skip analysis of arguments of implicitly defined map clause for target
4100 // directives.
4101 if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
4102 C->isImplicit() &&
4103 !isOpenMPTaskingDirective(Stack->getCurrentDirective()))) {
4104 for (Stmt *CC : C->children()) {
4105 if (CC)
4106 Visit(CC);
4107 }
4108 }
4109 }
4110 // Check implicitly captured variables.
4111 VisitSubCaptures(S);
4112 }
4113
4114 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) {
4115 // Loop transformation directives do not introduce data sharing
4116 VisitStmt(S);
4117 }
4118
4119 void VisitCallExpr(CallExpr *S) {
4120 for (Stmt *C : S->arguments()) {
4121 if (C) {
4122 // Check implicitly captured variables in the task-based directives to
4123 // check if they must be firstprivatized.
4124 Visit(C);
4125 }
4126 }
4127 if (Expr *Callee = S->getCallee()) {
4128 auto *CI = Callee->IgnoreParenImpCasts();
4129 if (auto *CE = dyn_cast<MemberExpr>(CI))
4130 Visit(CE->getBase());
4131 else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4132 Visit(CE);
4133 }
4134 }
4135 void VisitStmt(Stmt *S) {
4136 for (Stmt *C : S->children()) {
4137 if (C) {
4138 // Check implicitly captured variables in the task-based directives to
4139 // check if they must be firstprivatized.
4140 Visit(C);
4141 }
4142 }
4143 }
4144
4145 void visitSubCaptures(CapturedStmt *S) {
4146 for (const CapturedStmt::Capture &Cap : S->captures()) {
4147 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4148 continue;
4149 VarDecl *VD = Cap.getCapturedVar();
4150 // Do not try to map the variable if it or its sub-component was mapped
4151 // already.
4152 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
4153 Stack->checkMappableExprComponentListsForDecl(
4154 VD, /*CurrentRegionOnly=*/true,
4156 OpenMPClauseKind) { return true; }))
4157 continue;
4159 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4160 Cap.getLocation(), /*RefersToCapture=*/true);
4161 Visit(DRE);
4162 }
4163 }
4164 bool isErrorFound() const { return ErrorFound; }
4165 ArrayRef<Expr *> getImplicitFirstprivate() const {
4166 return ImplicitFirstprivate;
4167 }
4168 ArrayRef<Expr *> getImplicitPrivate() const { return ImplicitPrivate; }
4170 OpenMPMapClauseKind MK) const {
4171 return ImplicitMap[DK][MK];
4172 }
4174 getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind) const {
4175 return ImplicitMapModifier[Kind];
4176 }
4177 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4178 return VarsWithInheritedDSA;
4179 }
4180
4181 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4182 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4183 // Process declare target link variables for the target directives.
4184 if (isOpenMPTargetExecutionDirective(S->getCurrentDirective())) {
4185 for (DeclRefExpr *E : Stack->getLinkGlobals())
4186 Visit(E);
4187 }
4188 }
4189};
4190} // namespace
4191
4192static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4193 OpenMPDirectiveKind DKind,
4194 bool ScopeEntry) {
4197 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4198 if (isOpenMPTeamsDirective(DKind))
4199 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4200 if (isOpenMPParallelDirective(DKind))
4201 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4203 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4204 if (isOpenMPSimdDirective(DKind))
4205 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4206 Stack->handleConstructTrait(Traits, ScopeEntry);
4207}
4208
4210 Scope *CurScope) {
4211 ASTContext &Context = getASTContext();
4212 switch (DKind) {
4213 case OMPD_parallel:
4214 case OMPD_parallel_for:
4215 case OMPD_parallel_for_simd:
4216 case OMPD_parallel_sections:
4217 case OMPD_parallel_master:
4218 case OMPD_parallel_masked:
4219 case OMPD_parallel_loop:
4220 case OMPD_teams:
4221 case OMPD_teams_distribute:
4222 case OMPD_teams_distribute_simd: {
4223 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4224 QualType KmpInt32PtrTy =
4225 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4227 std::make_pair(".global_tid.", KmpInt32PtrTy),
4228 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4229 std::make_pair(StringRef(), QualType()) // __context with shared vars
4230 };
4231 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4232 CR_OpenMP, Params);
4233 break;
4234 }
4235 case OMPD_target_teams:
4236 case OMPD_target_parallel:
4237 case OMPD_target_parallel_for:
4238 case OMPD_target_parallel_for_simd:
4239 case OMPD_target_parallel_loop:
4240 case OMPD_target_teams_distribute:
4241 case OMPD_target_teams_distribute_simd: {
4242 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4243 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4244 QualType KmpInt32PtrTy =
4245 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4246 QualType Args[] = {VoidPtrTy};
4248 EPI.Variadic = true;
4249 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4251 std::make_pair(".global_tid.", KmpInt32Ty),
4252 std::make_pair(".part_id.", KmpInt32PtrTy),
4253 std::make_pair(".privates.", VoidPtrTy),
4254 std::make_pair(
4255 ".copy_fn.",
4256 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4257 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4258 std::make_pair(StringRef(), QualType()) // __context with shared vars
4259 };
4260 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4261 CR_OpenMP, Params,
4262 /*OpenMPCaptureLevel=*/0);
4263 // Mark this captured region as inlined, because we don't use outlined
4264 // function directly.
4266 AlwaysInlineAttr::CreateImplicit(
4267 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4269 if (getLangOpts().OpenMPIsTargetDevice)
4270 ParamsTarget.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4271 ParamsTarget.push_back(
4272 std::make_pair(StringRef(), QualType())); // __context with shared vars;
4273 // Start a captured region for 'target' with no implicit parameters.
4274 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4275 CR_OpenMP, ParamsTarget,
4276 /*OpenMPCaptureLevel=*/1);
4277 SemaOpenMP::CapturedParamNameType ParamsTeamsOrParallel[] = {
4278 std::make_pair(".global_tid.", KmpInt32PtrTy),
4279 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4280 std::make_pair(StringRef(), QualType()) // __context with shared vars
4281 };
4282 // Start a captured region for 'teams' or 'parallel'. Both regions have
4283 // the same implicit parameters.
4284 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4285 CR_OpenMP, ParamsTeamsOrParallel,
4286 /*OpenMPCaptureLevel=*/2);
4287 break;
4288 }
4289 case OMPD_target:
4290 case OMPD_target_simd: {
4291 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4292 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4293 QualType KmpInt32PtrTy =
4294 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4295 QualType Args[] = {VoidPtrTy};
4297 EPI.Variadic = true;
4298 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4300 std::make_pair(".global_tid.", KmpInt32Ty),
4301 std::make_pair(".part_id.", KmpInt32PtrTy),
4302 std::make_pair(".privates.", VoidPtrTy),
4303 std::make_pair(
4304 ".copy_fn.",
4305 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4306 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4307 std::make_pair(StringRef(), QualType()) // __context with shared vars
4308 };
4309 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4310 CR_OpenMP, Params,
4311 /*OpenMPCaptureLevel=*/0);
4312 // Mark this captured region as inlined, because we don't use outlined
4313 // function directly.
4315 AlwaysInlineAttr::CreateImplicit(
4316 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4318 if (getLangOpts().OpenMPIsTargetDevice)
4319 ParamsTarget.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4320 ParamsTarget.push_back(
4321 std::make_pair(StringRef(), QualType())); // __context with shared vars;
4322 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4323 CR_OpenMP, ParamsTarget,
4324 /*OpenMPCaptureLevel=*/1);
4325 break;
4326 }
4327 case OMPD_atomic:
4328 case OMPD_critical:
4329 case OMPD_section:
4330 case OMPD_master:
4331 case OMPD_masked:
4332 case OMPD_tile:
4333 case OMPD_unroll:
4334 break;
4335 case OMPD_loop:
4336 // TODO: 'loop' may require additional parameters depending on the binding.
4337 // Treat similar to OMPD_simd/OMPD_for for now.
4338 case OMPD_simd:
4339 case OMPD_for:
4340 case OMPD_for_simd:
4341 case OMPD_sections:
4342 case OMPD_single:
4343 case OMPD_taskgroup:
4344 case OMPD_distribute:
4345 case OMPD_distribute_simd:
4346 case OMPD_ordered:
4347 case OMPD_scope:
4348 case OMPD_target_data:
4349 case OMPD_dispatch: {
4351 std::make_pair(StringRef(), QualType()) // __context with shared vars
4352 };
4353 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4354 CR_OpenMP, Params);
4355 break;
4356 }
4357 case OMPD_task: {
4358 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4359 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4360 QualType KmpInt32PtrTy =
4361 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4362 QualType Args[] = {VoidPtrTy};
4364 EPI.Variadic = true;
4365 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4367 std::make_pair(".global_tid.", KmpInt32Ty),
4368 std::make_pair(".part_id.", KmpInt32PtrTy),
4369 std::make_pair(".privates.", VoidPtrTy),
4370 std::make_pair(
4371 ".copy_fn.",
4372 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4373 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4374 std::make_pair(StringRef(), QualType()) // __context with shared vars
4375 };
4376 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4377 CR_OpenMP, Params);
4378 // Mark this captured region as inlined, because we don't use outlined
4379 // function directly.
4381 AlwaysInlineAttr::CreateImplicit(
4382 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4383 break;
4384 }
4385 case OMPD_taskloop:
4386 case OMPD_taskloop_simd:
4387 case OMPD_master_taskloop:
4388 case OMPD_masked_taskloop:
4389 case OMPD_masked_taskloop_simd:
4390 case OMPD_master_taskloop_simd: {
4391 QualType KmpInt32Ty =
4392 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4393 .withConst();
4394 QualType KmpUInt64Ty =
4395 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4396 .withConst();
4397 QualType KmpInt64Ty =
4398 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4399 .withConst();
4400 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4401 QualType KmpInt32PtrTy =
4402 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4403 QualType Args[] = {VoidPtrTy};
4405 EPI.Variadic = true;
4406 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4408 std::make_pair(".global_tid.", KmpInt32Ty),
4409 std::make_pair(".part_id.", KmpInt32PtrTy),
4410 std::make_pair(".privates.", VoidPtrTy),
4411 std::make_pair(
4412 ".copy_fn.",
4413 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4414 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4415 std::make_pair(".lb.", KmpUInt64Ty),
4416 std::make_pair(".ub.", KmpUInt64Ty),
4417 std::make_pair(".st.", KmpInt64Ty),
4418 std::make_pair(".liter.", KmpInt32Ty),
4419 std::make_pair(".reductions.", VoidPtrTy),
4420 std::make_pair(StringRef(), QualType()) // __context with shared vars
4421 };
4422 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4423 CR_OpenMP, Params);
4424 // Mark this captured region as inlined, because we don't use outlined
4425 // function directly.
4427 AlwaysInlineAttr::CreateImplicit(
4428 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4429 break;
4430 }
4431 case OMPD_parallel_masked_taskloop:
4432 case OMPD_parallel_masked_taskloop_simd:
4433 case OMPD_parallel_master_taskloop:
4434 case OMPD_parallel_master_taskloop_simd: {
4435 QualType KmpInt32Ty =
4436 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4437 .withConst();
4438 QualType KmpUInt64Ty =
4439 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4440 .withConst();
4441 QualType KmpInt64Ty =
4442 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4443 .withConst();
4444 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4445 QualType KmpInt32PtrTy =
4446 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4447 SemaOpenMP::CapturedParamNameType ParamsParallel[] = {
4448 std::make_pair(".global_tid.", KmpInt32PtrTy),
4449 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4450 std::make_pair(StringRef(), QualType()) // __context with shared vars
4451 };
4452 // Start a captured region for 'parallel'.
4453 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4454 CR_OpenMP, ParamsParallel,
4455 /*OpenMPCaptureLevel=*/0);
4456 QualType Args[] = {VoidPtrTy};
4458 EPI.Variadic = true;
4459 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4461 std::make_pair(".global_tid.", KmpInt32Ty),
4462 std::make_pair(".part_id.", KmpInt32PtrTy),
4463 std::make_pair(".privates.", VoidPtrTy),
4464 std::make_pair(
4465 ".copy_fn.",
4466 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4467 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4468 std::make_pair(".lb.", KmpUInt64Ty),
4469 std::make_pair(".ub.", KmpUInt64Ty),
4470 std::make_pair(".st.", KmpInt64Ty),
4471 std::make_pair(".liter.", KmpInt32Ty),
4472 std::make_pair(".reductions.", VoidPtrTy),
4473 std::make_pair(StringRef(), QualType()) // __context with shared vars
4474 };
4475 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4476 CR_OpenMP, Params,
4477 /*OpenMPCaptureLevel=*/1);
4478 // Mark this captured region as inlined, because we don't use outlined
4479 // function directly.
4481 AlwaysInlineAttr::CreateImplicit(
4482 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4483 break;
4484 }
4485 case OMPD_distribute_parallel_for_simd:
4486 case OMPD_distribute_parallel_for: {
4487 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4488 QualType KmpInt32PtrTy =
4489 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4491 std::make_pair(".global_tid.", KmpInt32PtrTy),
4492 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4493 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4494 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4495 std::make_pair(StringRef(), QualType()) // __context with shared vars
4496 };
4497 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4498 CR_OpenMP, Params);
4499 break;
4500 }
4501 // For 'target teams loop', collect all captured regions so codegen can
4502 // later decide the best IR to emit given the associated loop-nest.
4503 case OMPD_target_teams_loop:
4504 case OMPD_target_teams_distribute_parallel_for:
4505 case OMPD_target_teams_distribute_parallel_for_simd: {
4506 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4507 QualType KmpInt32PtrTy =
4508 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4509 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4510
4511 QualType Args[] = {VoidPtrTy};
4513 EPI.Variadic = true;
4514 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4516 std::make_pair(".global_tid.", KmpInt32Ty),
4517 std::make_pair(".part_id.", KmpInt32PtrTy),
4518 std::make_pair(".privates.", VoidPtrTy),
4519 std::make_pair(
4520 ".copy_fn.",
4521 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4522 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4523 std::make_pair(StringRef(), QualType()) // __context with shared vars
4524 };
4525 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4526 CR_OpenMP, Params,
4527 /*OpenMPCaptureLevel=*/0);
4528 // Mark this captured region as inlined, because we don't use outlined
4529 // function directly.
4531 AlwaysInlineAttr::CreateImplicit(
4532 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4534 if (getLangOpts().OpenMPIsTargetDevice)
4535 ParamsTarget.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4536 ParamsTarget.push_back(
4537 std::make_pair(StringRef(), QualType())); // __context with shared vars;
4538 // Start a captured region for 'target' with no implicit parameters.
4539 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4540 CR_OpenMP, ParamsTarget,
4541 /*OpenMPCaptureLevel=*/1);
4542
4543 SemaOpenMP::CapturedParamNameType ParamsTeams[] = {
4544 std::make_pair(".global_tid.", KmpInt32PtrTy),
4545 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4546 std::make_pair(StringRef(), QualType()) // __context with shared vars
4547 };
4548 // Start a captured region for 'target' with no implicit parameters.
4549 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4550 CR_OpenMP, ParamsTeams,
4551 /*OpenMPCaptureLevel=*/2);
4552
4553 SemaOpenMP::CapturedParamNameType ParamsParallel[] = {
4554 std::make_pair(".global_tid.", KmpInt32PtrTy),
4555 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4556 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4557 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4558 std::make_pair(StringRef(), QualType()) // __context with shared vars
4559 };
4560 // Start a captured region for 'teams' or 'parallel'. Both regions have
4561 // the same implicit parameters.
4562 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4563 CR_OpenMP, ParamsParallel,
4564 /*OpenMPCaptureLevel=*/3);
4565 break;
4566 }
4567
4568 case OMPD_teams_loop:
4569 case OMPD_teams_distribute_parallel_for:
4570 case OMPD_teams_distribute_parallel_for_simd: {
4571 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4572 QualType KmpInt32PtrTy =
4573 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4574
4575 SemaOpenMP::CapturedParamNameType ParamsTeams[] = {
4576 std::make_pair(".global_tid.", KmpInt32PtrTy),
4577 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4578 std::make_pair(StringRef(), QualType()) // __context with shared vars
4579 };
4580 // Start a captured region for 'target' with no implicit parameters.
4581 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4582 CR_OpenMP, ParamsTeams,
4583 /*OpenMPCaptureLevel=*/0);
4584
4585 SemaOpenMP::CapturedParamNameType ParamsParallel[] = {
4586 std::make_pair(".global_tid.", KmpInt32PtrTy),
4587 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4588 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4589 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4590 std::make_pair(StringRef(), QualType()) // __context with shared vars
4591 };
4592 // Start a captured region for 'teams' or 'parallel'. Both regions have
4593 // the same implicit parameters.
4594 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4595 CR_OpenMP, ParamsParallel,
4596 /*OpenMPCaptureLevel=*/1);
4597 break;
4598 }
4599 case OMPD_target_update:
4600 case OMPD_target_enter_data:
4601 case OMPD_target_exit_data: {
4602 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4603 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4604 QualType KmpInt32PtrTy =
4605 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4606 QualType Args[] = {VoidPtrTy};
4608 EPI.Variadic = true;
4609 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4611 std::make_pair(".global_tid.", KmpInt32Ty),
4612 std::make_pair(".part_id.", KmpInt32PtrTy),
4613 std::make_pair(".privates.", VoidPtrTy),
4614 std::make_pair(
4615 ".copy_fn.",
4616 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4617 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4618 std::make_pair(StringRef(), QualType()) // __context with shared vars
4619 };
4620 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4621 CR_OpenMP, Params);
4622 // Mark this captured region as inlined, because we don't use outlined
4623 // function directly.
4625 AlwaysInlineAttr::CreateImplicit(
4626 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4627 break;
4628 }
4629 case OMPD_threadprivate:
4630 case OMPD_allocate:
4631 case OMPD_taskyield:
4632 case OMPD_error:
4633 case OMPD_barrier:
4634 case OMPD_taskwait:
4635 case OMPD_cancellation_point:
4636 case OMPD_cancel:
4637 case OMPD_flush:
4638 case OMPD_depobj:
4639 case OMPD_scan:
4640 case OMPD_declare_reduction:
4641 case OMPD_declare_mapper:
4642 case OMPD_declare_simd:
4643 case OMPD_declare_target:
4644 case OMPD_end_declare_target:
4645 case OMPD_requires:
4646 case OMPD_declare_variant:
4647 case OMPD_begin_declare_variant:
4648 case OMPD_end_declare_variant:
4649 case OMPD_metadirective:
4650 llvm_unreachable("OpenMP Directive is not allowed");
4651 case OMPD_unknown:
4652 default:
4653 llvm_unreachable("Unknown OpenMP directive");
4654 }
4655 DSAStack->setContext(SemaRef.CurContext);
4656 handleDeclareVariantConstructTrait(DSAStack, DKind, /* ScopeEntry */ true);
4657}
4658
4659int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4660 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4661}
4662
4665 getOpenMPCaptureRegions(CaptureRegions, DKind);
4666 return CaptureRegions.size();
4667}
4668
4670 Expr *CaptureExpr, bool WithInit,
4671 DeclContext *CurContext,
4672 bool AsExpression) {
4673 assert(CaptureExpr);
4674 ASTContext &C = S.getASTContext();
4675 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4676 QualType Ty = Init->getType();
4677 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4678 if (S.getLangOpts().CPlusPlus) {
4679 Ty = C.getLValueReferenceType(Ty);
4680 } else {
4681 Ty = C.getPointerType(Ty);
4682 ExprResult Res =
4683 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4684 if (!Res.isUsable())
4685 return nullptr;
4686 Init = Res.get();
4687 }
4688 WithInit = true;
4689 }
4690 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4691 CaptureExpr->getBeginLoc());
4692 if (!WithInit)
4693 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4694 CurContext->addHiddenDecl(CED);
4696 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4697 return CED;
4698}
4699
4700static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4701 bool WithInit) {
4703 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4704 CD = cast<OMPCapturedExprDecl>(VD);
4705 else
4706 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4707 S.CurContext,
4708 /*AsExpression=*/false);
4709 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4710 CaptureExpr->getExprLoc());
4711}
4712
4713static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4714 StringRef Name) {
4715 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4716 if (!Ref) {
4718 S, &S.getASTContext().Idents.get(Name), CaptureExpr,
4719 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4720 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4721 CaptureExpr->getExprLoc());
4722 }
4723 ExprResult Res = Ref;
4724 if (!S.getLangOpts().CPlusPlus &&
4725 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4726 Ref->getType()->isPointerType()) {
4727 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4728 if (!Res.isUsable())
4729 return ExprError();
4730 }
4731 return S.DefaultLvalueConversion(Res.get());
4732}
4733
4734namespace {
4735// OpenMP directives parsed in this section are represented as a
4736// CapturedStatement with an associated statement. If a syntax error
4737// is detected during the parsing of the associated statement, the
4738// compiler must abort processing and close the CapturedStatement.
4739//
4740// Combined directives such as 'target parallel' have more than one
4741// nested CapturedStatements. This RAII ensures that we unwind out
4742// of all the nested CapturedStatements when an error is found.
4743class CaptureRegionUnwinderRAII {
4744private:
4745 Sema &S;
4746 bool &ErrorFound;
4747 OpenMPDirectiveKind DKind = OMPD_unknown;
4748
4749public:
4750 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4751 OpenMPDirectiveKind DKind)
4752 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4753 ~CaptureRegionUnwinderRAII() {
4754 if (ErrorFound) {
4755 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4756 while (--ThisCaptureLevel >= 0)
4758 }
4759 }
4760};
4761} // namespace
4762
4764 // Capture variables captured by reference in lambdas for target-based
4765 // directives.
4767 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4769 DSAStack->getCurrentDirective()))) {
4770 QualType Type = V->getType();
4771 if (const auto *RD = Type.getCanonicalType()
4772 .getNonReferenceType()
4773 ->getAsCXXRecordDecl()) {
4774 bool SavedForceCaptureByReferenceInTargetExecutable =
4775 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4776 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4777 /*V=*/true);
4778 if (RD->isLambda()) {
4779 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4780 FieldDecl *ThisCapture;
4781 RD->getCaptureFields(Captures, ThisCapture);
4782 for (const LambdaCapture &LC : RD->captures()) {
4783 if (LC.getCaptureKind() == LCK_ByRef) {
4784 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4785 DeclContext *VDC = VD->getDeclContext();
4786 if (!VDC->Encloses(SemaRef.CurContext))
4787 continue;
4788 SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
4789 } else if (LC.getCaptureKind() == LCK_This) {
4791 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4792 ThisTy, ThisCapture->getType()))
4793 SemaRef.CheckCXXThisCapture(LC.getLocation());
4794 }
4795 }
4796 }
4797 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4798 SavedForceCaptureByReferenceInTargetExecutable);
4799 }
4800 }
4801}
4802
4804 const ArrayRef<OMPClause *> Clauses) {
4805 const OMPOrderedClause *Ordered = nullptr;
4806 const OMPOrderClause *Order = nullptr;
4807
4808 for (const OMPClause *Clause : Clauses) {
4809 if (Clause->getClauseKind() == OMPC_ordered)
4810 Ordered = cast<OMPOrderedClause>(Clause);
4811 else if (Clause->getClauseKind() == OMPC_order) {
4812 Order = cast<OMPOrderClause>(Clause);
4813 if (Order->getKind() != OMPC_ORDER_concurrent)
4814 Order = nullptr;
4815 }
4816 if (Ordered && Order)
4817 break;
4818 }
4819
4820 if (Ordered && Order) {
4821 S.Diag(Order->getKindKwLoc(),
4822 diag::err_omp_simple_clause_incompatible_with_ordered)
4823 << getOpenMPClauseName(OMPC_order)
4824 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4825 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4826 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4827 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4828 return true;
4829 }
4830 return false;
4831}
4832
4834 ArrayRef<OMPClause *> Clauses) {
4836 /* ScopeEntry */ false);
4837 if (DSAStack->getCurrentDirective() == OMPD_atomic ||
4838 DSAStack->getCurrentDirective() == OMPD_critical ||
4839 DSAStack->getCurrentDirective() == OMPD_section ||
4840 DSAStack->getCurrentDirective() == OMPD_master ||
4841 DSAStack->getCurrentDirective() == OMPD_masked)
4842 return S;
4843
4844 bool ErrorFound = false;
4845 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4846 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4847 if (!S.isUsable()) {
4848 ErrorFound = true;
4849 return StmtError();
4850 }
4851
4853 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4854 OMPOrderedClause *OC = nullptr;
4855 OMPScheduleClause *SC = nullptr;
4858 // This is required for proper codegen.
4859 for (OMPClause *Clause : Clauses) {
4860 if (!getLangOpts().OpenMPSimd &&
4861 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4862 DSAStack->getCurrentDirective() == OMPD_target) &&
4863 Clause->getClauseKind() == OMPC_in_reduction) {
4864 // Capture taskgroup task_reduction descriptors inside the tasking regions
4865 // with the corresponding in_reduction items.
4866 auto *IRC = cast<OMPInReductionClause>(Clause);
4867 for (Expr *E : IRC->taskgroup_descriptors())
4868 if (E)
4870 }
4871 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4872 Clause->getClauseKind() == OMPC_copyprivate ||
4873 (getLangOpts().OpenMPUseTLS &&
4874 getASTContext().getTargetInfo().isTLSSupported() &&
4875 Clause->getClauseKind() == OMPC_copyin)) {
4876 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4877 // Mark all variables in private list clauses as used in inner region.
4878 for (Stmt *VarRef : Clause->children()) {
4879 if (auto *E = cast_or_null<Expr>(VarRef)) {
4881 }
4882 }
4883 DSAStack->setForceVarCapturing(/*V=*/false);
4885 DSAStack->getCurrentDirective())) {
4886 assert(CaptureRegions.empty() &&
4887 "No captured regions in loop transformation directives.");
4888 } else if (CaptureRegions.size() > 1 ||
4889 CaptureRegions.back() != OMPD_unknown) {
4890 if (auto *C = OMPClauseWithPreInit::get(Clause))
4891 PICs.push_back(C);
4892 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4893 if (Expr *E = C->getPostUpdateExpr())
4895 }
4896 }
4897 if (Clause->getClauseKind() == OMPC_schedule)
4898 SC = cast<OMPScheduleClause>(Clause);
4899 else if (Clause->getClauseKind() == OMPC_ordered)
4900 OC = cast<OMPOrderedClause>(Clause);
4901 else if (Clause->getClauseKind() == OMPC_linear)
4902 LCs.push_back(cast<OMPLinearClause>(Clause));
4903 }
4904 // Capture allocator expressions if used.
4905 for (Expr *E : DSAStack->getInnerAllocators())
4907 // OpenMP, 2.7.1 Loop Construct, Restrictions
4908 // The nonmonotonic modifier cannot be specified if an ordered clause is
4909 // specified.
4910 if (SC &&
4911 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4913 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4914 OC) {
4915 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4918 diag::err_omp_simple_clause_incompatible_with_ordered)
4919 << getOpenMPClauseName(OMPC_schedule)
4920 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4921 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4922 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4923 ErrorFound = true;
4924 }
4925 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4926 // If an order(concurrent) clause is present, an ordered clause may not appear
4927 // on the same directive.
4928 if (checkOrderedOrderSpecified(SemaRef, Clauses))
4929 ErrorFound = true;
4930 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4931 for (const OMPLinearClause *C : LCs) {
4932 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4933 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4934 }
4935 ErrorFound = true;
4936 }
4937 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4938 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4939 OC->getNumForLoops()) {
4940 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4941 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
4942 ErrorFound = true;
4943 }
4944 if (ErrorFound) {
4945 return StmtError();
4946 }
4947 StmtResult SR = S;
4948 unsigned CompletedRegions = 0;
4949 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4950 // Mark all variables in private list clauses as used in inner region.
4951 // Required for proper codegen of combined directives.
4952 // TODO: add processing for other clauses.
4953 if (ThisCaptureRegion != OMPD_unknown) {
4954 for (const clang::OMPClauseWithPreInit *C : PICs) {
4955 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4956 // Find the particular capture region for the clause if the
4957 // directive is a combined one with multiple capture regions.
4958 // If the directive is not a combined one, the capture region
4959 // associated with the clause is OMPD_unknown and is generated
4960 // only once.
4961 if (CaptureRegion == ThisCaptureRegion ||
4962 CaptureRegion == OMPD_unknown) {
4963 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4964 for (Decl *D : DS->decls())
4966 cast<VarDecl>(D));
4967 }
4968 }
4969 }
4970 }
4971 if (ThisCaptureRegion == OMPD_target) {
4972 // Capture allocator traits in the target region. They are used implicitly
4973 // and, thus, are not captured by default.
4974 for (OMPClause *C : Clauses) {
4975 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4976 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4977 ++I) {
4978 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4979 if (Expr *E = D.AllocatorTraits)
4981 }
4982 continue;
4983 }
4984 }
4985 }
4986 if (ThisCaptureRegion == OMPD_parallel) {
4987 // Capture temp arrays for inscan reductions and locals in aligned
4988 // clauses.
4989 for (OMPClause *C : Clauses) {
4990 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4991 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4992 continue;
4993 for (Expr *E : RC->copy_array_temps())
4994 if (E)
4996 }
4997 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4998 for (Expr *E : AC->varlists())
5000 }
5001 }
5002 }
5003 if (++CompletedRegions == CaptureRegions.size())
5004 DSAStack->setBodyComplete();
5006 }
5007 return SR;
5008}
5009
5010static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
5011 OpenMPDirectiveKind CancelRegion,
5012 SourceLocation StartLoc) {
5013 // CancelRegion is only needed for cancel and cancellation_point.
5014 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
5015 return false;
5016
5017 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
5018 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
5019 return false;
5020
5021 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
5022 << getOpenMPDirectiveName(CancelRegion);
5023 return true;
5024}
5025
5026static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
5027 OpenMPDirectiveKind CurrentRegion,
5028 const DeclarationNameInfo &CurrentName,
5029 OpenMPDirectiveKind CancelRegion,
5030 OpenMPBindClauseKind BindKind,
5031 SourceLocation StartLoc) {
5032 if (Stack->getCurScope()) {
5033 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
5034 OpenMPDirectiveKind OffendingRegion = ParentRegion;
5035 bool NestingProhibited = false;
5036 bool CloseNesting = true;
5037 bool OrphanSeen = false;
5038 enum {
5039 NoRecommend,
5040 ShouldBeInParallelRegion,
5041 ShouldBeInOrderedRegion,
5042 ShouldBeInTargetRegion,
5043 ShouldBeInTeamsRegion,
5044 ShouldBeInLoopSimdRegion,
5045 } Recommend = NoRecommend;
5046 if (SemaRef.LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() &&
5047 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop &&
5048 CurrentRegion != OMPD_parallel &&
5049 !isOpenMPCombinedParallelADirective(CurrentRegion)) {
5050 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
5051 << getOpenMPDirectiveName(CurrentRegion);
5052 return true;
5053 }
5054 if (isOpenMPSimdDirective(ParentRegion) &&
5055 ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
5056 (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
5057 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
5058 CurrentRegion != OMPD_scan))) {
5059 // OpenMP [2.16, Nesting of Regions]
5060 // OpenMP constructs may not be nested inside a simd region.
5061 // OpenMP [2.8.1,simd Construct, Restrictions]
5062 // An ordered construct with the simd clause is the only OpenMP
5063 // construct that can appear in the simd region.
5064 // Allowing a SIMD construct nested in another SIMD construct is an
5065 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
5066 // message.
5067 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
5068 // The only OpenMP constructs that can be encountered during execution of
5069 // a simd region are the atomic construct, the loop construct, the simd
5070 // construct and the ordered construct with the simd clause.
5071 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
5072 ? diag::err_omp_prohibited_region_simd
5073 : diag::warn_omp_nesting_simd)
5074 << (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0);
5075 return CurrentRegion != OMPD_simd;
5076 }
5077 if (ParentRegion == OMPD_atomic) {
5078 // OpenMP [2.16, Nesting of Regions]
5079 // OpenMP constructs may not be nested inside an atomic region.
5080 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
5081 return true;
5082 }
5083 if (CurrentRegion == OMPD_section) {
5084 // OpenMP [2.7.2, sections Construct, Restrictions]
5085 // Orphaned section directives are prohibited. That is, the section
5086 // directives must appear within the sections construct and must not be
5087 // encountered elsewhere in the sections region.
5088 if (ParentRegion != OMPD_sections &&
5089 ParentRegion != OMPD_parallel_sections) {
5090 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
5091 << (ParentRegion != OMPD_unknown)
5092 << getOpenMPDirectiveName(ParentRegion);
5093 return true;
5094 }
5095 return false;
5096 }
5097 // Allow some constructs (except teams and cancellation constructs) to be
5098 // orphaned (they could be used in functions, called from OpenMP regions
5099 // with the required preconditions).
5100 if (ParentRegion == OMPD_unknown &&
5101 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
5102 CurrentRegion != OMPD_cancellation_point &&
5103 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5104 return false;
5105 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
5106 // for a detailed explanation
5107 if (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop &&
5108 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
5109 (isOpenMPWorksharingDirective(ParentRegion) ||
5110 ParentRegion == OMPD_loop)) {
5111 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
5112 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5113 << true << getOpenMPDirectiveName(ParentRegion) << ErrorMsgNumber
5114 << getOpenMPDirectiveName(CurrentRegion);
5115 return true;
5116 }
5117 if (CurrentRegion == OMPD_cancellation_point ||
5118 CurrentRegion == OMPD_cancel) {
5119 // OpenMP [2.16, Nesting of Regions]
5120 // A cancellation point construct for which construct-type-clause is
5121 // taskgroup must be nested inside a task construct. A cancellation
5122 // point construct for which construct-type-clause is not taskgroup must
5123 // be closely nested inside an OpenMP construct that matches the type
5124 // specified in construct-type-clause.
5125 // A cancel construct for which construct-type-clause is taskgroup must be
5126 // nested inside a task construct. A cancel construct for which
5127 // construct-type-clause is not taskgroup must be closely nested inside an
5128 // OpenMP construct that matches the type specified in
5129 // construct-type-clause.
5130 NestingProhibited =
5131 !((CancelRegion == OMPD_parallel &&
5132 (ParentRegion == OMPD_parallel ||
5133 ParentRegion == OMPD_target_parallel)) ||
5134 (CancelRegion == OMPD_for &&
5135 (ParentRegion == OMPD_for || ParentRegion == OMPD_parallel_for ||
5136 ParentRegion == OMPD_target_parallel_for ||
5137 ParentRegion == OMPD_distribute_parallel_for ||
5138 ParentRegion == OMPD_teams_distribute_parallel_for ||
5139 ParentRegion == OMPD_target_teams_distribute_parallel_for)) ||
5140 (CancelRegion == OMPD_taskgroup &&
5141 (ParentRegion == OMPD_task ||
5142 (SemaRef.getLangOpts().OpenMP >= 50 &&
5143 (ParentRegion == OMPD_taskloop ||
5144 ParentRegion == OMPD_master_taskloop ||
5145 ParentRegion == OMPD_masked_taskloop ||
5146 ParentRegion == OMPD_parallel_masked_taskloop ||
5147 ParentRegion == OMPD_parallel_master_taskloop)))) ||
5148 (CancelRegion == OMPD_sections &&
5149 (ParentRegion == OMPD_section || ParentRegion == OMPD_sections ||
5150 ParentRegion == OMPD_parallel_sections)));
5151 OrphanSeen = ParentRegion == OMPD_unknown;
5152 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5153 // OpenMP 5.1 [2.22, Nesting of Regions]
5154 // A masked region may not be closely nested inside a worksharing, loop,
5155 // atomic, task, or taskloop region.
5156 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5157 isOpenMPGenericLoopDirective(ParentRegion) ||
5158 isOpenMPTaskingDirective(ParentRegion);
5159 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5160 // OpenMP [2.16, Nesting of Regions]
5161 // A critical region may not be nested (closely or otherwise) inside a
5162 // critical region with the same name. Note that this restriction is not
5163 // sufficient to prevent deadlock.
5164 SourceLocation PreviousCriticalLoc;
5165 bool DeadLock = Stack->hasDirective(
5166 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5167 const DeclarationNameInfo &DNI,
5168 SourceLocation Loc) {
5169 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5170 PreviousCriticalLoc = Loc;
5171 return true;
5172 }
5173 return false;
5174 },
5175 false /* skip top directive */);
5176 if (DeadLock) {
5177 SemaRef.Diag(StartLoc,
5178 diag::err_omp_prohibited_region_critical_same_name)
5179 << CurrentName.getName();
5180 if (PreviousCriticalLoc.isValid())
5181 SemaRef.Diag(PreviousCriticalLoc,
5182 diag::note_omp_previous_critical_region);
5183 return true;
5184 }
5185 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5186 // OpenMP 5.1 [2.22, Nesting of Regions]
5187 // A scope region may not be closely nested inside a worksharing, loop,
5188 // task, taskloop, critical, ordered, atomic, or masked region.
5189 // OpenMP 5.1 [2.22, Nesting of Regions]
5190 // A barrier region may not be closely nested inside a worksharing, loop,
5191 // task, taskloop, critical, ordered, atomic, or masked region.
5192 NestingProhibited =
5193 isOpenMPWorksharingDirective(ParentRegion) ||
5194 isOpenMPGenericLoopDirective(ParentRegion) ||
5195 isOpenMPTaskingDirective(ParentRegion) ||
5196 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5197 ParentRegion == OMPD_parallel_master ||
5198 ParentRegion == OMPD_parallel_masked ||
5199 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5200 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
5201 !isOpenMPParallelDirective(CurrentRegion) &&
5202 !isOpenMPTeamsDirective(CurrentRegion)) {
5203 // OpenMP 5.1 [2.22, Nesting of Regions]
5204 // A loop region that binds to a parallel region or a worksharing region
5205 // may not be closely nested inside a worksharing, loop, task, taskloop,
5206 // critical, ordered, atomic, or masked region.
5207 NestingProhibited =
5208 isOpenMPWorksharingDirective(ParentRegion) ||
5209 isOpenMPGenericLoopDirective(ParentRegion) ||
5210 isOpenMPTaskingDirective(ParentRegion) ||
5211 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5212 ParentRegion == OMPD_parallel_master ||
5213 ParentRegion == OMPD_parallel_masked ||
5214 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5215 Recommend = ShouldBeInParallelRegion;
5216 } else if (CurrentRegion == OMPD_ordered) {
5217 // OpenMP [2.16, Nesting of Regions]
5218 // An ordered region may not be closely nested inside a critical,
5219 // atomic, or explicit task region.
5220 // An ordered region must be closely nested inside a loop region (or
5221 // parallel loop region) with an ordered clause.
5222 // OpenMP [2.8.1,simd Construct, Restrictions]
5223 // An ordered construct with the simd clause is the only OpenMP construct
5224 // that can appear in the simd region.
5225 NestingProhibited = ParentRegion == OMPD_critical ||
5226 isOpenMPTaskingDirective(ParentRegion) ||
5227 !(isOpenMPSimdDirective(ParentRegion) ||
5228 Stack->isParentOrderedRegion());
5229 Recommend = ShouldBeInOrderedRegion;
5230 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
5231 // OpenMP [2.16, Nesting of Regions]
5232 // If specified, a teams construct must be contained within a target
5233 // construct.
5234 NestingProhibited =
5235 (SemaRef.LangOpts.OpenMP <= 45 && ParentRegion != OMPD_target) ||
5236 (SemaRef.LangOpts.OpenMP >= 50 && ParentRegion != OMPD_unknown &&
5237 ParentRegion != OMPD_target);
5238 OrphanSeen = ParentRegion == OMPD_unknown;
5239 Recommend = ShouldBeInTargetRegion;
5240 } else if (CurrentRegion == OMPD_scan) {
5241 // OpenMP [2.16, Nesting of Regions]
5242 // If specified, a teams construct must be contained within a target
5243 // construct.
5244 NestingProhibited =
5245 SemaRef.LangOpts.OpenMP < 50 ||
5246 (ParentRegion != OMPD_simd && ParentRegion != OMPD_for &&
5247 ParentRegion != OMPD_for_simd && ParentRegion != OMPD_parallel_for &&
5248 ParentRegion != OMPD_parallel_for_simd);
5249 OrphanSeen = ParentRegion == OMPD_unknown;
5250 Recommend = ShouldBeInLoopSimdRegion;
5251 }
5252 if (!NestingProhibited &&
5253 !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5254 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5255 (ParentRegion == OMPD_teams || ParentRegion == OMPD_target_teams)) {
5256 // OpenMP [5.1, 2.22, Nesting of Regions]
5257 // distribute, distribute simd, distribute parallel worksharing-loop,
5258 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5259 // including any parallel regions arising from combined constructs,
5260 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5261 // only OpenMP regions that may be strictly nested inside the teams
5262 // region.
5263 //
5264 // As an extension, we permit atomic within teams as well.
5265 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5266 !isOpenMPDistributeDirective(CurrentRegion) &&
5267 CurrentRegion != OMPD_loop &&
5268 !(SemaRef.getLangOpts().OpenMPExtensions &&
5269 CurrentRegion == OMPD_atomic);
5270 Recommend = ShouldBeInParallelRegion;
5271 }
5272 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5273 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5274 // If the bind clause is present on the loop construct and binding is
5275 // teams then the corresponding loop region must be strictly nested inside
5276 // a teams region.
5277 NestingProhibited = BindKind == OMPC_BIND_teams &&
5278 ParentRegion != OMPD_teams &&
5279 ParentRegion != OMPD_target_teams;
5280 Recommend = ShouldBeInTeamsRegion;
5281 }
5282 if (!NestingProhibited &&
5283 isOpenMPNestingDistributeDirective(CurrentRegion)) {
5284 // OpenMP 4.5 [2.17 Nesting of Regions]
5285 // The region associated with the distribute construct must be strictly
5286 // nested inside a teams region
5287 NestingProhibited =
5288 (ParentRegion != OMPD_teams && ParentRegion != OMPD_target_teams);
5289 Recommend = ShouldBeInTeamsRegion;
5290 }
5291 if (!NestingProhibited &&
5292 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5293 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5294 // OpenMP 4.5 [2.17 Nesting of Regions]
5295 // If a target, target update, target data, target enter data, or
5296 // target exit data construct is encountered during execution of a
5297 // target region, the behavior is unspecified.
5298 NestingProhibited = Stack->hasDirective(
5299 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5302 OffendingRegion = K;
5303 return true;
5304 }
5305 return false;
5306 },
5307 false /* don't skip top directive */);
5308 CloseNesting = false;
5309 }
5310 if (NestingProhibited) {
5311 if (OrphanSeen) {
5312 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5313 << getOpenMPDirectiveName(CurrentRegion) << Recommend;
5314 } else {
5315 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5316 << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
5317 << Recommend << getOpenMPDirectiveName(CurrentRegion);
5318 }
5319 return true;
5320 }
5321 }
5322 return false;
5323}
5324
5327 unsigned operator()(argument_type DK) { return unsigned(DK); }
5328};
5330 ArrayRef<OMPClause *> Clauses,
5331 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5332 bool ErrorFound = false;
5333 unsigned NamedModifiersNumber = 0;
5334 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5335 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5336 SmallVector<SourceLocation, 4> NameModifierLoc;
5337 for (const OMPClause *C : Clauses) {
5338 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5339 // At most one if clause without a directive-name-modifier can appear on
5340 // the directive.
5341 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5342 if (FoundNameModifiers[CurNM]) {
5343 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5344 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
5345 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
5346 ErrorFound = true;
5347 } else if (CurNM != OMPD_unknown) {
5348 NameModifierLoc.push_back(IC->getNameModifierLoc());
5349 ++NamedModifiersNumber;
5350 }
5351 FoundNameModifiers[CurNM] = IC;
5352 if (CurNM == OMPD_unknown)
5353 continue;
5354 // Check if the specified name modifier is allowed for the current
5355 // directive.
5356 // At most one if clause with the particular directive-name-modifier can
5357 // appear on the directive.
5358 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5359 S.Diag(IC->getNameModifierLoc(),
5360 diag::err_omp_wrong_if_directive_name_modifier)
5361 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
5362 ErrorFound = true;
5363 }
5364 }
5365 }
5366 // If any if clause on the directive includes a directive-name-modifier then
5367 // all if clauses on the directive must include a directive-name-modifier.
5368 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5369 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5370 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5371 diag::err_omp_no_more_if_clause);
5372 } else {
5373 std::string Values;
5374 std::string Sep(", ");
5375 unsigned AllowedCnt = 0;
5376 unsigned TotalAllowedNum =
5377 AllowedNameModifiers.size() - NamedModifiersNumber;
5378 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5379 ++Cnt) {
5380 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5381 if (!FoundNameModifiers[NM]) {
5382 Values += "'";
5383 Values += getOpenMPDirectiveName(NM);
5384 Values += "'";
5385 if (AllowedCnt + 2 == TotalAllowedNum)
5386 Values += " or ";
5387 else if (AllowedCnt + 1 != TotalAllowedNum)
5388 Values += Sep;
5389 ++AllowedCnt;
5390 }
5391 }
5392 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5393 diag::err_omp_unnamed_if_clause)
5394 << (TotalAllowedNum > 1) << Values;
5395 }
5396 for (SourceLocation Loc : NameModifierLoc) {
5397 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5398 }
5399 ErrorFound = true;
5400 }
5401 return ErrorFound;
5402}
5403
5404static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5405 SourceLocation &ELoc,
5406 SourceRange &ERange,
5407 bool AllowArraySection,
5408 StringRef DiagType) {
5409 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5411 return std::make_pair(nullptr, true);
5412
5413 // OpenMP [3.1, C/C++]
5414 // A list item is a variable name.
5415 // OpenMP [2.9.3.3, Restrictions, p.1]
5416 // A variable that is part of another variable (as an array or
5417 // structure element) cannot appear in a private clause.
5418 RefExpr = RefExpr->IgnoreParens();
5419 enum {
5420 NoArrayExpr = -1,
5421 ArraySubscript = 0,
5422 OMPArraySection = 1
5423 } IsArrayExpr = NoArrayExpr;
5424 if (AllowArraySection) {
5425 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5426 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5427 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5428 Base = TempASE->getBase()->IgnoreParenImpCasts();
5429 RefExpr = Base;
5430 IsArrayExpr = ArraySubscript;
5431 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5432 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5433 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Base))
5434 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5435 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5436 Base = TempASE->getBase()->IgnoreParenImpCasts();
5437 RefExpr = Base;
5438 IsArrayExpr = OMPArraySection;
5439 }
5440 }
5441 ELoc = RefExpr->getExprLoc();
5442 ERange = RefExpr->getSourceRange();
5443 RefExpr = RefExpr->IgnoreParenImpCasts();
5444 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5445 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5446 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5447 (S.getCurrentThisType().isNull() || !ME ||
5448 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5449 !isa<FieldDecl>(ME->getMemberDecl()))) {
5450 if (IsArrayExpr != NoArrayExpr) {
5451 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5452 << IsArrayExpr << ERange;
5453 } else if (!DiagType.empty()) {
5454 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5455 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5456 : 0;
5457 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5458 << DiagSelect << DiagType << ERange;
5459 } else {
5460 S.Diag(ELoc,
5461 AllowArraySection
5462 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5463 : diag::err_omp_expected_var_name_member_expr)
5464 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5465 }
5466 return std::make_pair(nullptr, false);
5467 }
5468 return std::make_pair(
5469 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5470}
5471
5472namespace {
5473/// Checks if the allocator is used in uses_allocators clause to be allowed in
5474/// target regions.
5475class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5476 DSAStackTy *S = nullptr;
5477
5478public:
5479 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5480 return S->isUsesAllocatorsDecl(E->getDecl())
5481 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5482 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5483 }
5484 bool VisitStmt(const Stmt *S) {
5485 for (const Stmt *Child : S->children()) {
5486 if (Child && Visit(Child))
5487 return true;
5488 }
5489 return false;
5490 }
5491 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5492};
5493} // namespace
5494
5495static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5496 ArrayRef<OMPClause *> Clauses) {
5497 assert(!S.CurContext->isDependentContext() &&
5498 "Expected non-dependent context.");
5499 auto AllocateRange =
5500 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5501 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5502 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5503 return isOpenMPPrivate(C->getClauseKind());
5504 });
5505 for (OMPClause *Cl : PrivateRange) {
5507 if (Cl->getClauseKind() == OMPC_private) {
5508 auto *PC = cast<OMPPrivateClause>(Cl);
5509 I = PC->private_copies().begin();
5510 It = PC->varlist_begin();
5511 Et = PC->varlist_end();
5512 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5513 auto *PC = cast<OMPFirstprivateClause>(Cl);
5514 I = PC->private_copies().begin();
5515 It = PC->varlist_begin();
5516 Et = PC->varlist_end();
5517 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5518 auto *PC = cast<OMPLastprivateClause>(Cl);
5519 I = PC->private_copies().begin();
5520 It = PC->varlist_begin();
5521 Et = PC->varlist_end();
5522 } else if (Cl->getClauseKind() == OMPC_linear) {
5523 auto *PC = cast<OMPLinearClause>(Cl);
5524 I = PC->privates().begin();
5525 It = PC->varlist_begin();
5526 Et = PC->varlist_end();
5527 } else if (Cl->getClauseKind() == OMPC_reduction) {
5528 auto *PC = cast<OMPReductionClause>(Cl);
5529 I = PC->privates().begin();
5530 It = PC->varlist_begin();
5531 Et = PC->varlist_end();
5532 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5533 auto *PC = cast<OMPTaskReductionClause>(Cl);
5534 I = PC->privates().begin();
5535 It = PC->varlist_begin();
5536 Et = PC->varlist_end();
5537 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5538 auto *PC = cast<OMPInReductionClause>(Cl);
5539 I = PC->privates().begin();
5540 It = PC->varlist_begin();
5541 Et = PC->varlist_end();
5542 } else {
5543 llvm_unreachable("Expected private clause.");
5544 }
5545 for (Expr *E : llvm::make_range(It, Et)) {
5546 if (!*I) {
5547 ++I;
5548 continue;
5549 }
5550 SourceLocation ELoc;
5551 SourceRange ERange;
5552 Expr *SimpleRefExpr = E;
5553 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5554 /*AllowArraySection=*/true);
5555 DeclToCopy.try_emplace(Res.first,
5556 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5557 ++I;
5558 }
5559 }
5560 for (OMPClause *C : AllocateRange) {
5561 auto *AC = cast<OMPAllocateClause>(C);
5562 if (S.getLangOpts().OpenMP >= 50 &&
5563 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5564 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5565 AC->getAllocator()) {
5566 Expr *Allocator = AC->getAllocator();
5567 // OpenMP, 2.12.5 target Construct
5568 // Memory allocators that do not appear in a uses_allocators clause cannot
5569 // appear as an allocator in an allocate clause or be used in the target
5570 // region unless a requires directive with the dynamic_allocators clause
5571 // is present in the same compilation unit.
5572 AllocatorChecker Checker(Stack);
5573 if (Checker.Visit(Allocator))
5574 S.Diag(Allocator->getExprLoc(),
5575 diag::err_omp_allocator_not_in_uses_allocators)
5576 << Allocator->getSourceRange();
5577 }
5578 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5579 getAllocatorKind(S, Stack, AC->getAllocator());
5580 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5581 // For task, taskloop or target directives, allocation requests to memory
5582 // allocators with the trait access set to thread result in unspecified
5583 // behavior.
5584 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5585 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5586 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5587 S.Diag(AC->getAllocator()->getExprLoc(),
5588 diag::warn_omp_allocate_thread_on_task_target_directive)
5589 << getOpenMPDirectiveName(Stack->getCurrentDirective());
5590 }
5591 for (Expr *E : AC->varlists()) {
5592 SourceLocation ELoc;
5593 SourceRange ERange;
5594 Expr *SimpleRefExpr = E;
5595 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5596 ValueDecl *VD = Res.first;
5597 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5598 if (!isOpenMPPrivate(Data.CKind)) {
5599 S.Diag(E->getExprLoc(),
5600 diag::err_omp_expected_private_copy_for_allocate);
5601 continue;
5602 }
5603 VarDecl *PrivateVD = DeclToCopy[VD];
5604 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5605 AllocatorKind, AC->getAllocator()))
5606 continue;
5607 // Placeholder until allocate clause supports align modifier.
5608 Expr *Alignment = nullptr;
5609 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5610 Alignment, E->getSourceRange());
5611 }
5612 }
5613}
5614
5615namespace {
5616/// Rewrite statements and expressions for Sema \p Actions CurContext.
5617///
5618/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5619/// context. DeclRefExpr used inside the new context are changed to refer to the
5620/// captured variable instead.
5621class CaptureVars : public TreeTransform<CaptureVars> {
5622 using BaseTransform = TreeTransform<CaptureVars>;
5623
5624public:
5625 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5626
5627 bool AlwaysRebuild() { return true; }
5628};
5629} // namespace
5630
5631static VarDecl *precomputeExpr(Sema &Actions,
5632 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5633 StringRef Name) {
5634 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5635 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5636 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5637 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5638 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5639 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5640 BodyStmts.push_back(NewDeclStmt);
5641 return NewVar;
5642}
5643
5644/// Create a closure that computes the number of iterations of a loop.
5645///
5646/// \param Actions The Sema object.
5647/// \param LogicalTy Type for the logical iteration number.
5648/// \param Rel Comparison operator of the loop condition.
5649/// \param StartExpr Value of the loop counter at the first iteration.
5650/// \param StopExpr Expression the loop counter is compared against in the loop
5651/// condition. \param StepExpr Amount of increment after each iteration.
5652///
5653/// \return Closure (CapturedStmt) of the distance calculation.
5654static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5656 Expr *StartExpr, Expr *StopExpr,
5657 Expr *StepExpr) {
5658 ASTContext &Ctx = Actions.getASTContext();
5659 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5660
5661 // Captured regions currently don't support return values, we use an
5662 // out-parameter instead. All inputs are implicit captures.
5663 // TODO: Instead of capturing each DeclRefExpr occurring in
5664 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5665 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5666 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5667 {StringRef(), QualType()}};
5668 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5669
5670 Stmt *Body;
5671 {
5672 Sema::CompoundScopeRAII CompoundScope(Actions);
5673 CapturedDecl *CS = cast<CapturedDecl>(Actions.CurContext);
5674
5675 // Get the LValue expression for the result.
5676 ImplicitParamDecl *DistParam = CS->getParam(0);
5677 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5678 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5679
5680 SmallVector<Stmt *, 4> BodyStmts;
5681
5682 // Capture all referenced variable references.
5683 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5684 // CapturedStmt, we could compute them before and capture the result, to be
5685 // used jointly with the LoopVar function.
5686 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5687 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5688 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5689 auto BuildVarRef = [&](VarDecl *VD) {
5690 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5691 };
5692
5694 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5696 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5697 Expr *Dist;
5698 if (Rel == BO_NE) {
5699 // When using a != comparison, the increment can be +1 or -1. This can be
5700 // dynamic at runtime, so we need to check for the direction.
5701 Expr *IsNegStep = AssertSuccess(
5702 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5703
5704 // Positive increment.
5705 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5706 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5707 ForwardRange = AssertSuccess(
5708 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5709 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5710 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5711
5712 // Negative increment.
5713 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5714 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5715 BackwardRange = AssertSuccess(
5716 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5717 Expr *NegIncAmount = AssertSuccess(
5718 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5719 Expr *BackwardDist = AssertSuccess(
5720 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5721
5722 // Use the appropriate case.
5723 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5724 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5725 } else {
5726 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5727 "Expected one of these relational operators");
5728
5729 // We can derive the direction from any other comparison operator. It is
5730 // non well-formed OpenMP if Step increments/decrements in the other
5731 // directions. Whether at least the first iteration passes the loop
5732 // condition.
5733 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5734 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5735
5736 // Compute the range between first and last counter value.
5737 Expr *Range;
5738 if (Rel == BO_GE || Rel == BO_GT)
5739 Range = AssertSuccess(Actions.BuildBinOp(
5740 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5741 else
5742 Range = AssertSuccess(Actions.BuildBinOp(
5743 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5744
5745 // Ensure unsigned range space.
5746 Range =
5747 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5748
5749 if (Rel == BO_LE || Rel == BO_GE) {
5750 // Add one to the range if the relational operator is inclusive.
5751 Range =
5752 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5753 }
5754
5755 // Divide by the absolute step amount. If the range is not a multiple of
5756 // the step size, rounding-up the effective upper bound ensures that the
5757 // last iteration is included.
5758 // Note that the rounding-up may cause an overflow in a temporry that
5759 // could be avoided, but would have occurred in a C-style for-loop as
5760 // well.
5761 Expr *Divisor = BuildVarRef(NewStep);
5762 if (Rel == BO_GE || Rel == BO_GT)
5763 Divisor =
5764 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5765 Expr *DivisorMinusOne =
5766 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5767 Expr *RangeRoundUp = AssertSuccess(
5768 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5769 Dist = AssertSuccess(
5770 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5771
5772 // If there is not at least one iteration, the range contains garbage. Fix
5773 // to zero in this case.
5774 Dist = AssertSuccess(
5775 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5776 }
5777
5778 // Assign the result to the out-parameter.
5779 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5780 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5781 BodyStmts.push_back(ResultAssign);
5782
5783 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5784 }
5785
5786 return cast<CapturedStmt>(
5787 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5788}
5789
5790/// Create a closure that computes the loop variable from the logical iteration
5791/// number.
5792///
5793/// \param Actions The Sema object.
5794/// \param LoopVarTy Type for the loop variable used for result value.
5795/// \param LogicalTy Type for the logical iteration number.
5796/// \param StartExpr Value of the loop counter at the first iteration.
5797/// \param Step Amount of increment after each iteration.
5798/// \param Deref Whether the loop variable is a dereference of the loop
5799/// counter variable.
5800///
5801/// \return Closure (CapturedStmt) of the loop value calculation.
5802static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5803 QualType LogicalTy,
5804 DeclRefExpr *StartExpr, Expr *Step,
5805 bool Deref) {
5806 ASTContext &Ctx = Actions.getASTContext();
5807
5808 // Pass the result as an out-parameter. Passing as return value would require
5809 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5810 // invoke a copy constructor.
5811 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5812 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5813 {"Logical", LogicalTy},
5814 {StringRef(), QualType()}};
5815 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5816
5817 // Capture the initial iterator which represents the LoopVar value at the
5818 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5819 // it in every iteration, capture it by value before it is modified.
5820 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5821 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5823 (void)Invalid;
5824 assert(!Invalid && "Expecting capture-by-value to work.");
5825
5826 Expr *Body;
5827 {
5828 Sema::CompoundScopeRAII CompoundScope(Actions);
5829 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5830
5831 ImplicitParamDecl *TargetParam = CS->getParam(0);
5832 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5833 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5834 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5835 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5836 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5837
5838 // Capture the Start expression.
5839 CaptureVars Recap(Actions);
5840 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5841 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5842
5843 Expr *Skip = AssertSuccess(
5844 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5845 // TODO: Explicitly cast to the iterator's difference_type instead of
5846 // relying on implicit conversion.
5847 Expr *Advanced =
5848 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5849
5850 if (Deref) {
5851 // For range-based for-loops convert the loop counter value to a concrete
5852 // loop variable value by dereferencing the iterator.
5853 Advanced =
5854 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5855 }
5856
5857 // Assign the result to the output parameter.
5858 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5859 BO_Assign, TargetRef, Advanced));
5860 }
5861 return cast<CapturedStmt>(
5862 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5863}
5864
5866 ASTContext &Ctx = getASTContext();
5867
5868 // Extract the common elements of ForStmt and CXXForRangeStmt:
5869 // Loop variable, repeat condition, increment
5870 Expr *Cond, *Inc;
5871 VarDecl *LIVDecl, *LUVDecl;
5872 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5873 Stmt *Init = For->getInit();
5874 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5875 // For statement declares loop variable.
5876 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5877 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5878 // For statement reuses variable.
5879 assert(LCAssign->getOpcode() == BO_Assign &&
5880 "init part must be a loop variable assignment");
5881 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5882 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5883 } else
5884 llvm_unreachable("Cannot determine loop variable");
5885 LUVDecl = LIVDecl;
5886
5887 Cond = For->getCond();
5888 Inc = For->getInc();
5889 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5890 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5891 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5892 LUVDecl = RangeFor->getLoopVariable();
5893
5894 Cond = RangeFor->getCond();
5895 Inc = RangeFor->getInc();
5896 } else
5897 llvm_unreachable("unhandled kind of loop");
5898
5899 QualType CounterTy = LIVDecl->getType();
5900 QualType LVTy = LUVDecl->getType();
5901
5902 // Analyze the loop condition.
5903 Expr *LHS, *RHS;
5904 BinaryOperator::Opcode CondRel;
5905 Cond = Cond->IgnoreImplicit();
5906 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5907 LHS = CondBinExpr->getLHS();
5908 RHS = CondBinExpr->getRHS();
5909 CondRel = CondBinExpr->getOpcode();
5910 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5911 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5912 LHS = CondCXXOp->getArg(0);
5913 RHS = CondCXXOp->getArg(1);
5914 switch (CondCXXOp->getOperator()) {
5915 case OO_ExclaimEqual:
5916 CondRel = BO_NE;
5917 break;
5918 case OO_Less:
5919 CondRel = BO_LT;
5920 break;
5921 case OO_LessEqual:
5922 CondRel = BO_LE;
5923 break;
5924 case OO_Greater:
5925 CondRel = BO_GT;
5926 break;
5927 case OO_GreaterEqual:
5928 CondRel = BO_GE;
5929 break;
5930 default:
5931 llvm_unreachable("unexpected iterator operator");
5932 }
5933 } else
5934 llvm_unreachable("unexpected loop condition");
5935
5936 // Normalize such that the loop counter is on the LHS.
5937 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5938 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5939 std::swap(LHS, RHS);
5940 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5941 }
5942 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5943
5944 // Decide the bit width for the logical iteration counter. By default use the
5945 // unsigned ptrdiff_t integer size (for iterators and pointers).
5946 // TODO: For iterators, use iterator::difference_type,
5947 // std::iterator_traits<>::difference_type or decltype(it - end).
5948 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5949 if (CounterTy->isIntegerType()) {
5950 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5951 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5952 }
5953
5954 // Analyze the loop increment.
5955 Expr *Step;
5956 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5957 int Direction;
5958 switch (IncUn->getOpcode()) {
5959 case UO_PreInc:
5960 case UO_PostInc:
5961 Direction = 1;
5962 break;
5963 case UO_PreDec:
5964 case UO_PostDec:
5965 Direction = -1;
5966 break;
5967 default:
5968 llvm_unreachable("unhandled unary increment operator");
5969 }
5971 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction), LogicalTy, {});
5972 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5973 if (IncBin->getOpcode() == BO_AddAssign) {
5974 Step = IncBin->getRHS();
5975 } else if (IncBin->getOpcode() == BO_SubAssign) {
5976 Step = AssertSuccess(
5977 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5978 } else
5979 llvm_unreachable("unhandled binary increment operator");
5980 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5981 switch (CondCXXOp->getOperator()) {
5982 case OO_PlusPlus:
5984 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5985 break;
5986 case OO_MinusMinus:
5988 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5989 break;
5990 case OO_PlusEqual:
5991 Step = CondCXXOp->getArg(1);
5992 break;
5993 case OO_MinusEqual:
5994 Step = AssertSuccess(
5995 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5996 break;
5997 default:
5998 llvm_unreachable("unhandled overloaded increment operator");
5999 }
6000 } else
6001 llvm_unreachable("unknown increment expression");
6002
6003 CapturedStmt *DistanceFunc =
6004 buildDistanceFunc(SemaRef, LogicalTy, CondRel, LHS, RHS, Step);
6005 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
6006 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
6007 DeclRefExpr *LVRef =
6008 SemaRef.BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue, {},
6009 nullptr, nullptr, {}, nullptr);
6010 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
6011 LoopVarFunc, LVRef);
6012}
6013
6015 // Handle a literal loop.
6016 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
6017 return ActOnOpenMPCanonicalLoop(AStmt);
6018
6019 // If not a literal loop, it must be the result of a loop transformation.
6020 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(AStmt);
6021 assert(
6023 "Loop transformation directive expected");
6024 return LoopTransform;
6025}
6026
6028 CXXScopeSpec &MapperIdScopeSpec,
6029 const DeclarationNameInfo &MapperId,
6030 QualType Type,
6031 Expr *UnresolvedMapper);
6032
6033/// Perform DFS through the structure/class data members trying to find
6034/// member(s) with user-defined 'default' mapper and generate implicit map
6035/// clauses for such members with the found 'default' mapper.
6036static void
6039 // Check for the deault mapper for data members.
6040 if (S.getLangOpts().OpenMP < 50)
6041 return;
6042 SmallVector<OMPClause *, 4> ImplicitMaps;
6043 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
6044 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
6045 if (!C)
6046 continue;
6047 SmallVector<Expr *, 4> SubExprs;
6048 auto *MI = C->mapperlist_begin();
6049 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
6050 ++I, ++MI) {
6051 // Expression is mapped using mapper - skip it.
6052 if (*MI)
6053 continue;
6054 Expr *E = *I;
6055 // Expression is dependent - skip it, build the mapper when it gets
6056 // instantiated.
6057 if (E->isTypeDependent() || E->isValueDependent() ||
6059 continue;
6060 // Array section - need to check for the mapping of the array section
6061 // element.
6062 QualType CanonType = E->getType().getCanonicalType();
6063 if (CanonType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
6064 const auto *OASE = cast<ArraySectionExpr>(E->IgnoreParenImpCasts());
6065 QualType BaseType =
6067 QualType ElemType;
6068 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6069 ElemType = ATy->getElementType();
6070 else
6071 ElemType = BaseType->getPointeeType();
6072 CanonType = ElemType;
6073 }
6074
6075 // DFS over data members in structures/classes.
6077 1, {CanonType, nullptr});
6078 llvm::DenseMap<const Type *, Expr *> Visited;
6080 1, {nullptr, 1});
6081 while (!Types.empty()) {
6082 QualType BaseType;
6083 FieldDecl *CurFD;
6084 std::tie(BaseType, CurFD) = Types.pop_back_val();
6085 while (ParentChain.back().second == 0)
6086 ParentChain.pop_back();
6087 --ParentChain.back().second;
6088 if (BaseType.isNull())
6089 continue;
6090 // Only structs/classes are allowed to have mappers.
6091 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6092 if (!RD)
6093 continue;
6094 auto It = Visited.find(BaseType.getTypePtr());
6095 if (It == Visited.end()) {
6096 // Try to find the associated user-defined mapper.
6097 CXXScopeSpec MapperIdScopeSpec;
6098 DeclarationNameInfo DefaultMapperId;
6100 &S.Context.Idents.get("default")));
6101 DefaultMapperId.setLoc(E->getExprLoc());
6103 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
6104 BaseType, /*UnresolvedMapper=*/nullptr);
6105 if (ER.isInvalid())
6106 continue;
6107 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
6108 }
6109 // Found default mapper.
6110 if (It->second) {
6111 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
6113 OE->setIsUnique(/*V=*/true);
6114 Expr *BaseExpr = OE;
6115 for (const auto &P : ParentChain) {
6116 if (P.first) {
6117 BaseExpr = S.BuildMemberExpr(
6118 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6120 DeclAccessPair::make(P.first, P.first->getAccess()),
6121 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6122 P.first->getType(), VK_LValue, OK_Ordinary);
6123 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
6124 }
6125 }
6126 if (CurFD)
6127 BaseExpr = S.BuildMemberExpr(
6128 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6130 DeclAccessPair::make(CurFD, CurFD->getAccess()),
6131 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6132 CurFD->getType(), VK_LValue, OK_Ordinary);
6133 SubExprs.push_back(BaseExpr);
6134 continue;
6135 }
6136 // Check for the "default" mapper for data members.
6137 bool FirstIter = true;
6138 for (FieldDecl *FD : RD->fields()) {
6139 if (!FD)
6140 continue;
6141 QualType FieldTy = FD->getType();
6142 if (FieldTy.isNull() ||
6143 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6144 continue;
6145 if (FirstIter) {
6146 FirstIter = false;
6147 ParentChain.emplace_back(CurFD, 1);
6148 } else {
6149 ++ParentChain.back().second;
6150 }
6151 Types.emplace_back(FieldTy, FD);
6152 }
6153 }
6154 }
6155 if (SubExprs.empty())
6156 continue;
6157 CXXScopeSpec MapperIdScopeSpec;
6158 DeclarationNameInfo MapperId;
6159 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
6160 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
6161 MapperIdScopeSpec, MapperId, C->getMapType(),
6162 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6163 SubExprs, OMPVarListLocTy()))
6164 Clauses.push_back(NewClause);
6165 }
6166}
6167
6168namespace {
6169/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
6170/// call in the associated loop-nest cannot be a 'parallel for'.
6171class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
6172 Sema &SemaRef;
6173
6174public:
6175 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
6176
6177 // Is there a nested OpenMP loop bind(parallel)
6178 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
6179 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
6180 if (const auto *C = D->getSingleClause<OMPBindClause>())
6181 if (C->getBindKind() == OMPC_BIND_parallel) {
6182 TeamsLoopCanBeParallelFor = false;
6183 // No need to continue visiting any more
6184 return;
6185 }
6186 }
6187 for (const Stmt *Child : D->children())
6188 if (Child)
6189 Visit(Child);
6190 }
6191
6192 void VisitCallExpr(const CallExpr *C) {
6193 // Function calls inhibit parallel loop translation of 'target teams loop'
6194 // unless the assume-no-nested-parallelism flag has been specified.
6195 // OpenMP API runtime library calls do not inhibit parallel loop
6196 // translation, regardless of the assume-no-nested-parallelism.
6197 if (C) {
6198 bool IsOpenMPAPI = false;
6199 auto *FD = dyn_cast_or_null<FunctionDecl>(C->getCalleeDecl());
6200 if (FD) {
6201 std::string Name = FD->getNameInfo().getAsString();
6202 IsOpenMPAPI = Name.find("omp_") == 0;
6203 }
6204 TeamsLoopCanBeParallelFor =
6205 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
6206 if (!TeamsLoopCanBeParallelFor)
6207 return;
6208 }
6209 for (const Stmt *Child : C->children())
6210 if (Child)
6211 Visit(Child);
6212 }
6213
6214 void VisitCapturedStmt(const CapturedStmt *S) {
6215 if (!S)
6216 return;
6217 Visit(S->getCapturedDecl()->getBody());
6218 }
6219
6220 void VisitStmt(const Stmt *S) {
6221 if (!S)
6222 return;
6223 for (const Stmt *Child : S->children())
6224 if (Child)
6225 Visit(Child);
6226 }
6227 explicit TeamsLoopChecker(Sema &SemaRef)
6228 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
6229
6230private:
6231 bool TeamsLoopCanBeParallelFor;
6232};
6233} // namespace
6234
6235static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
6236 TeamsLoopChecker Checker(SemaRef);
6237 Checker.Visit(AStmt);
6238 return Checker.teamsLoopCanBeParallelFor();
6239}
6240
6241bool SemaOpenMP::mapLoopConstruct(
6242 llvm::SmallVector<OMPClause *> &ClausesWithoutBind,
6244 OpenMPDirectiveKind &Kind, OpenMPDirectiveKind &PrevMappedDirective,
6245 SourceLocation StartLoc, SourceLocation EndLoc,
6246 const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion) {
6247
6248 bool UseClausesWithoutBind = false;
6249
6250 // Restricting to "#pragma omp loop bind"
6251 if (getLangOpts().OpenMP >= 50 && Kind == OMPD_loop) {
6252
6253 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
6254
6255 if (BindKind == OMPC_BIND_unknown) {
6256 // Setting the enclosing teams or parallel construct for the loop
6257 // directive without bind clause.
6258 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6259
6260 if (ParentDirective == OMPD_unknown) {
6261 Diag(DSAStack->getDefaultDSALocation(),
6262 diag::err_omp_bind_required_on_loop);
6263 } else if (ParentDirective == OMPD_parallel ||
6264 ParentDirective == OMPD_target_parallel) {
6265 BindKind = OMPC_BIND_parallel;
6266 } else if (ParentDirective == OMPD_teams ||
6267 ParentDirective == OMPD_target_teams) {
6268 BindKind = OMPC_BIND_teams;
6269 }
6270 } else {
6271 // bind clause is present in loop directive. When the loop directive is
6272 // changed to a new directive the bind clause is not used. So, we should
6273 // set flag indicating to only use the clauses that aren't the
6274 // bind clause.
6275 UseClausesWithoutBind = true;
6276 }
6277
6278 for (OMPClause *C : Clauses) {
6279 // Spec restriction : bind(teams) and reduction not permitted.
6280 if (BindKind == OMPC_BIND_teams &&
6281 C->getClauseKind() == llvm::omp::Clause::OMPC_reduction)
6282 Diag(DSAStack->getDefaultDSALocation(),
6283 diag::err_omp_loop_reduction_clause);
6284
6285 // A new Vector ClausesWithoutBind, which does not contain the bind
6286 // clause, for passing to new directive.
6287 if (C->getClauseKind() != llvm::omp::Clause::OMPC_bind)
6288 ClausesWithoutBind.push_back(C);
6289 }
6290
6291 switch (BindKind) {
6292 case OMPC_BIND_parallel:
6293 Kind = OMPD_for;
6294 DSAStack->setCurrentDirective(OMPD_for);
6295 DSAStack->setMappedDirective(OMPD_loop);
6296 PrevMappedDirective = OMPD_loop;
6297 break;
6298 case OMPC_BIND_teams:
6299 Kind = OMPD_distribute;
6300 DSAStack->setCurrentDirective(OMPD_distribute);
6301 DSAStack->setMappedDirective(OMPD_loop);
6302 PrevMappedDirective = OMPD_loop;
6303 break;
6304 case OMPC_BIND_thread:
6305 Kind = OMPD_simd;
6306 DSAStack->setCurrentDirective(OMPD_simd);
6307 DSAStack->setMappedDirective(OMPD_loop);
6308 PrevMappedDirective = OMPD_loop;
6309 break;
6310 case OMPC_BIND_unknown:
6311 break;
6312 }
6313 } else if (PrevMappedDirective == OMPD_loop) {
6314 /// An initial pass after recognizing all the statements is done in the
6315 /// Parser when the directive OMPD_loop is mapped to OMPD_for,
6316 /// OMPD_distribute or OMPD_simd. A second transform pass with call from
6317 /// clang::TreeTransform::TransformOMPExecutableDirective() is done
6318 /// with the Directive as one of the above mapped directive without
6319 /// the bind clause. Then "PrevMappedDirective" stored in the
6320 /// OMPExecutableDirective is accessed and hence this else statement.
6321
6322 DSAStack->setMappedDirective(OMPD_loop);
6323 }
6324
6325 return UseClausesWithoutBind;
6326}
6327
6329 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6330 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6331 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc,
6332 OpenMPDirectiveKind PrevMappedDirective) {
6333 StmtResult Res = StmtError();
6335 llvm::SmallVector<OMPClause *> ClausesWithoutBind;
6336 bool UseClausesWithoutBind = false;
6337
6338 if (const OMPBindClause *BC =
6339 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6340 BindKind = BC->getBindKind();
6341
6342 // Variable used to note down the DirectiveKind because mapLoopConstruct may
6343 // change "Kind" variable, due to mapping of "omp loop" to other directives.
6344 OpenMPDirectiveKind DK = Kind;
6345 if (Kind == OMPD_loop || PrevMappedDirective == OMPD_loop) {
6346 UseClausesWithoutBind = mapLoopConstruct(
6347 ClausesWithoutBind, Clauses, BindKind, Kind, PrevMappedDirective,
6348 StartLoc, EndLoc, DirName, CancelRegion);
6349 DK = OMPD_loop;
6350 }
6351
6352 // First check CancelRegion which is then used in checkNestingOfRegions.
6353 if (checkCancelRegion(SemaRef, Kind, CancelRegion, StartLoc) ||
6354 checkNestingOfRegions(SemaRef, DSAStack, DK, DirName, CancelRegion,
6355 BindKind, StartLoc)) {
6356 return StmtError();
6357 }
6358
6359 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6362 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6363
6364 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6365 VarsWithInheritedDSAType VarsWithInheritedDSA;
6366 bool ErrorFound = false;
6367 if (getLangOpts().OpenMP >= 50 && UseClausesWithoutBind) {
6368 ClausesWithImplicit.append(ClausesWithoutBind.begin(),
6369 ClausesWithoutBind.end());
6370 } else {
6371 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6372 }
6373 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6374 Kind != OMPD_atomic && Kind != OMPD_critical && Kind != OMPD_section &&
6375 Kind != OMPD_master && Kind != OMPD_masked &&
6377 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6378
6379 // Check default data sharing attributes for referenced variables.
6380 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(AStmt));
6381 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6382 Stmt *S = AStmt;
6383 while (--ThisCaptureLevel >= 0)
6384 S = cast<CapturedStmt>(S)->getCapturedStmt();
6385 DSAChecker.Visit(S);
6387 !isOpenMPTaskingDirective(Kind)) {
6388 // Visit subcaptures to generate implicit clauses for captured vars.
6389 auto *CS = cast<CapturedStmt>(AStmt);
6391 getOpenMPCaptureRegions(CaptureRegions, Kind);
6392 // Ignore outer tasking regions for target directives.
6393 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6394 CS = cast<CapturedStmt>(CS->getCapturedStmt());
6395 DSAChecker.visitSubCaptures(CS);
6396 }
6397 if (DSAChecker.isErrorFound())
6398 return StmtError();
6399 // Generate list of implicitly defined firstprivate variables.
6400 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6401
6402 SmallVector<Expr *, 4> ImplicitFirstprivates(
6403 DSAChecker.getImplicitFirstprivate().begin(),
6404 DSAChecker.getImplicitFirstprivate().end());
6405 SmallVector<Expr *, 4> ImplicitPrivates(
6406 DSAChecker.getImplicitPrivate().begin(),
6407 DSAChecker.getImplicitPrivate().end());
6408 const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
6409 SmallVector<Expr *, 4> ImplicitMaps[DefaultmapKindNum][OMPC_MAP_delete];
6411 ImplicitMapModifiers[DefaultmapKindNum];
6413 ImplicitMapModifiersLoc[DefaultmapKindNum];
6414 // Get the original location of present modifier from Defaultmap clause.
6415 SourceLocation PresentModifierLocs[DefaultmapKindNum];
6416 for (OMPClause *C : Clauses) {
6417 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6418 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6419 PresentModifierLocs[DMC->getDefaultmapKind()] =
6420 DMC->getDefaultmapModifierLoc();
6421 }
6422 for (unsigned VC = 0; VC < DefaultmapKindNum; ++VC) {
6423 auto Kind = static_cast<OpenMPDefaultmapClauseKind>(VC);
6424 for (unsigned I = 0; I < OMPC_MAP_delete; ++I) {
6425 ArrayRef<Expr *> ImplicitMap = DSAChecker.getImplicitMap(
6426 Kind, static_cast<OpenMPMapClauseKind>(I));
6427 ImplicitMaps[VC][I].append(ImplicitMap.begin(), ImplicitMap.end());
6428 }
6429 ArrayRef<OpenMPMapModifierKind> ImplicitModifier =
6430 DSAChecker.getImplicitMapModifier(Kind);
6431 ImplicitMapModifiers[VC].append(ImplicitModifier.begin(),
6432 ImplicitModifier.end());
6433 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[VC]),
6434 ImplicitModifier.size(), PresentModifierLocs[VC]);
6435 }
6436 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6437 for (OMPClause *C : Clauses) {
6438 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6439 for (Expr *E : IRC->taskgroup_descriptors())
6440 if (E)
6441 ImplicitFirstprivates.emplace_back(E);
6442 }
6443 // OpenMP 5.0, 2.10.1 task Construct
6444 // [detach clause]... The event-handle will be considered as if it was
6445 // specified on a firstprivate clause.
6446 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6447 ImplicitFirstprivates.push_back(DC->getEventHandler());
6448 }
6449 if (!ImplicitFirstprivates.empty()) {
6451 ImplicitFirstprivates, SourceLocation(), SourceLocation(),
6452 SourceLocation())) {
6453 ClausesWithImplicit.push_back(Implicit);
6454 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6455 ImplicitFirstprivates.size();
6456 } else {
6457 ErrorFound = true;
6458 }
6459 }
6460 if (!ImplicitPrivates.empty()) {
6461 if (OMPClause *Implicit =
6462 ActOnOpenMPPrivateClause(ImplicitPrivates, SourceLocation(),
6464 ClausesWithImplicit.push_back(Implicit);
6465 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6466 ImplicitPrivates.size();
6467 } else {
6468 ErrorFound = true;
6469 }
6470 }
6471 // OpenMP 5.0 [2.19.7]
6472 // If a list item appears in a reduction, lastprivate or linear
6473 // clause on a combined target construct then it is treated as
6474 // if it also appears in a map clause with a map-type of tofrom
6475 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6477 SmallVector<Expr *, 4> ImplicitExprs;
6478 for (OMPClause *C : Clauses) {
6479 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6480 for (Expr *E : RC->varlists())
6481 if (!isa<DeclRefExpr>(E->IgnoreParenImpCasts()))
6482 ImplicitExprs.emplace_back(E);
6483 }
6484 if (!ImplicitExprs.empty()) {
6485 ArrayRef<Expr *> Exprs = ImplicitExprs;
6486 CXXScopeSpec MapperIdScopeSpec;
6487 DeclarationNameInfo MapperId;
6490 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6491 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6492 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6493 ClausesWithImplicit.emplace_back(Implicit);
6494 }
6495 }
6496 for (unsigned I = 0, E = DefaultmapKindNum; I < E; ++I) {
6497 int ClauseKindCnt = -1;
6498 for (ArrayRef<Expr *> ImplicitMap : ImplicitMaps[I]) {
6499 ++ClauseKindCnt;
6500 if (ImplicitMap.empty())
6501 continue;
6502 CXXScopeSpec MapperIdScopeSpec;
6503 DeclarationNameInfo MapperId;
6504 auto Kind = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6506 nullptr, ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I],
6507 MapperIdScopeSpec, MapperId, Kind, /*IsMapTypeImplicit=*/true,
6508 SourceLocation(), SourceLocation(), ImplicitMap,
6509 OMPVarListLocTy())) {
6510 ClausesWithImplicit.emplace_back(Implicit);
6511 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6512 ImplicitMap.size();
6513 } else {
6514 ErrorFound = true;
6515 }
6516 }
6517 }
6518 // Build expressions for implicit maps of data members with 'default'
6519 // mappers.
6520 if (getLangOpts().OpenMP >= 50)
6522 ClausesWithImplicit);
6523 }
6524
6525 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6526 switch (Kind) {
6527 case OMPD_parallel:
6528 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6529 EndLoc);
6530 AllowedNameModifiers.push_back(OMPD_parallel);
6531 break;
6532 case OMPD_simd:
6533 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6534 VarsWithInheritedDSA);
6535 if (getLangOpts().OpenMP >= 50)
6536 AllowedNameModifiers.push_back(OMPD_simd);
6537 break;
6538 case OMPD_tile:
6539 Res =
6540 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6541 break;
6542 case OMPD_unroll:
6543 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6544 EndLoc);
6545 break;
6546 case OMPD_for:
6547 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6548 VarsWithInheritedDSA);
6549 break;
6550 case OMPD_for_simd:
6551 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6552 EndLoc, VarsWithInheritedDSA);
6553 if (getLangOpts().OpenMP >= 50)
6554 AllowedNameModifiers.push_back(OMPD_simd);
6555 break;
6556 case OMPD_sections:
6557 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6558 EndLoc);
6559 break;
6560 case OMPD_section:
6561 assert(ClausesWithImplicit.empty() &&
6562 "No clauses are allowed for 'omp section' directive");
6563 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6564 break;
6565 case OMPD_single:
6566 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6567 EndLoc);
6568 break;
6569 case OMPD_master:
6570 assert(ClausesWithImplicit.empty() &&
6571 "No clauses are allowed for 'omp master' directive");
6572 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6573 break;
6574 case OMPD_masked:
6575 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6576 EndLoc);
6577 break;
6578 case OMPD_critical:
6579 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6580 StartLoc, EndLoc);
6581 break;
6582 case OMPD_parallel_for:
6583 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6584 EndLoc, VarsWithInheritedDSA);
6585 AllowedNameModifiers.push_back(OMPD_parallel);
6586 break;
6587 case OMPD_parallel_for_simd:
6589 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6590 AllowedNameModifiers.push_back(OMPD_parallel);
6591 if (getLangOpts().OpenMP >= 50)
6592 AllowedNameModifiers.push_back(OMPD_simd);
6593 break;
6594 case OMPD_scope:
6595 Res =
6596 ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6597 break;
6598 case OMPD_parallel_master:
6599 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6600 StartLoc, EndLoc);
6601 AllowedNameModifiers.push_back(OMPD_parallel);
6602 break;
6603 case OMPD_parallel_masked:
6604 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6605 StartLoc, EndLoc);
6606 AllowedNameModifiers.push_back(OMPD_parallel);
6607 break;
6608 case OMPD_parallel_sections:
6609 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6610 StartLoc, EndLoc);
6611 AllowedNameModifiers.push_back(OMPD_parallel);
6612 break;
6613 case OMPD_task:
6614 Res =
6615 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6616 AllowedNameModifiers.push_back(OMPD_task);
6617 break;
6618 case OMPD_taskyield:
6619 assert(ClausesWithImplicit.empty() &&
6620 "No clauses are allowed for 'omp taskyield' directive");
6621 assert(AStmt == nullptr &&
6622 "No associated statement allowed for 'omp taskyield' directive");
6623 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6624 break;
6625 case OMPD_error:
6626 assert(AStmt == nullptr &&
6627 "No associated statement allowed for 'omp error' directive");
6628 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6629 break;
6630 case OMPD_barrier:
6631 assert(ClausesWithImplicit.empty() &&
6632 "No clauses are allowed for 'omp barrier' directive");
6633 assert(AStmt == nullptr &&
6634 "No associated statement allowed for 'omp barrier' directive");
6635 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6636 break;
6637 case OMPD_taskwait:
6638 assert(AStmt == nullptr &&
6639 "No associated statement allowed for 'omp taskwait' directive");
6640 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6641 break;
6642 case OMPD_taskgroup:
6643 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6644 EndLoc);
6645 break;
6646 case OMPD_flush:
6647 assert(AStmt == nullptr &&
6648 "No associated statement allowed for 'omp flush' directive");
6649 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6650 break;
6651 case OMPD_depobj:
6652 assert(AStmt == nullptr &&
6653 "No associated statement allowed for 'omp depobj' directive");
6654 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6655 break;
6656 case OMPD_scan:
6657 assert(AStmt == nullptr &&
6658 "No associated statement allowed for 'omp scan' directive");
6659 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6660 break;
6661 case OMPD_ordered:
6662 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6663 EndLoc);
6664 break;
6665 case OMPD_atomic:
6666 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6667 EndLoc);
6668 break;
6669 case OMPD_teams:
6670 Res =
6671 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6672 break;
6673 case OMPD_target:
6674 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6675 EndLoc);
6676 AllowedNameModifiers.push_back(OMPD_target);
6677 break;
6678 case OMPD_target_parallel:
6679 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6680 StartLoc, EndLoc);
6681 AllowedNameModifiers.push_back(OMPD_target);
6682 AllowedNameModifiers.push_back(OMPD_parallel);
6683 break;
6684 case OMPD_target_parallel_for:
6686 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6687 AllowedNameModifiers.push_back(OMPD_target);
6688 AllowedNameModifiers.push_back(OMPD_parallel);
6689 break;
6690 case OMPD_cancellation_point:
6691 assert(ClausesWithImplicit.empty() &&
6692 "No clauses are allowed for 'omp cancellation point' directive");
6693 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6694 "cancellation point' directive");
6695 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6696 break;
6697 case OMPD_cancel:
6698 assert(AStmt == nullptr &&
6699 "No associated statement allowed for 'omp cancel' directive");
6700 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6701 CancelRegion);
6702 AllowedNameModifiers.push_back(OMPD_cancel);
6703 break;
6704 case OMPD_target_data:
6705 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6706 EndLoc);
6707 AllowedNameModifiers.push_back(OMPD_target_data);
6708 break;
6709 case OMPD_target_enter_data:
6710 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6711 EndLoc, AStmt);
6712 AllowedNameModifiers.push_back(OMPD_target_enter_data);
6713 break;
6714 case OMPD_target_exit_data:
6715 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6716 EndLoc, AStmt);
6717 AllowedNameModifiers.push_back(OMPD_target_exit_data);
6718 break;
6719 case OMPD_taskloop:
6720 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6721 EndLoc, VarsWithInheritedDSA);
6722 AllowedNameModifiers.push_back(OMPD_taskloop);
6723 break;
6724 case OMPD_taskloop_simd:
6725 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6726 EndLoc, VarsWithInheritedDSA);
6727 AllowedNameModifiers.push_back(OMPD_taskloop);
6728 if (getLangOpts().OpenMP >= 50)
6729 AllowedNameModifiers.push_back(OMPD_simd);
6730 break;
6731 case OMPD_master_taskloop:
6733 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6734 AllowedNameModifiers.push_back(OMPD_taskloop);
6735 break;
6736 case OMPD_masked_taskloop:
6738 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6739 AllowedNameModifiers.push_back(OMPD_taskloop);
6740 break;
6741 case OMPD_master_taskloop_simd:
6743 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6744 AllowedNameModifiers.push_back(OMPD_taskloop);
6745 if (getLangOpts().OpenMP >= 50)
6746 AllowedNameModifiers.push_back(OMPD_simd);
6747 break;
6748 case OMPD_masked_taskloop_simd:
6750 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6751 if (getLangOpts().OpenMP >= 51) {
6752 AllowedNameModifiers.push_back(OMPD_taskloop);
6753 AllowedNameModifiers.push_back(OMPD_simd);
6754 }
6755 break;
6756 case OMPD_parallel_master_taskloop:
6758 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6759 AllowedNameModifiers.push_back(OMPD_taskloop);
6760 AllowedNameModifiers.push_back(OMPD_parallel);
6761 break;
6762 case OMPD_parallel_masked_taskloop:
6764 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6765 if (getLangOpts().OpenMP >= 51) {
6766 AllowedNameModifiers.push_back(OMPD_taskloop);
6767 AllowedNameModifiers.push_back(OMPD_parallel);
6768 }
6769 break;
6770 case OMPD_parallel_master_taskloop_simd:
6772 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6773 AllowedNameModifiers.push_back(OMPD_taskloop);
6774 AllowedNameModifiers.push_back(OMPD_parallel);
6775 if (getLangOpts().OpenMP >= 50)
6776 AllowedNameModifiers.push_back(OMPD_simd);
6777 break;
6778 case OMPD_parallel_masked_taskloop_simd:
6780 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6781 if (getLangOpts().OpenMP >= 51) {
6782 AllowedNameModifiers.push_back(OMPD_taskloop);
6783 AllowedNameModifiers.push_back(OMPD_parallel);
6784 AllowedNameModifiers.push_back(OMPD_simd);
6785 }
6786 break;
6787 case OMPD_distribute:
6788 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6789 EndLoc, VarsWithInheritedDSA);
6790 break;
6791 case OMPD_target_update:
6792 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6793 EndLoc, AStmt);
6794 AllowedNameModifiers.push_back(OMPD_target_update);
6795 break;
6796 case OMPD_distribute_parallel_for:
6798 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6799 AllowedNameModifiers.push_back(OMPD_parallel);
6800 break;
6801 case OMPD_distribute_parallel_for_simd:
6803 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6804 AllowedNameModifiers.push_back(OMPD_parallel);
6805 if (getLangOpts().OpenMP >= 50)
6806 AllowedNameModifiers.push_back(OMPD_simd);
6807 break;
6808 case OMPD_distribute_simd:
6810 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6811 if (getLangOpts().OpenMP >= 50)
6812 AllowedNameModifiers.push_back(OMPD_simd);
6813 break;
6814 case OMPD_target_parallel_for_simd:
6816 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6817 AllowedNameModifiers.push_back(OMPD_target);
6818 AllowedNameModifiers.push_back(OMPD_parallel);
6819 if (getLangOpts().OpenMP >= 50)
6820 AllowedNameModifiers.push_back(OMPD_simd);
6821 break;
6822 case OMPD_target_simd:
6823 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6824 EndLoc, VarsWithInheritedDSA);
6825 AllowedNameModifiers.push_back(OMPD_target);
6826 if (getLangOpts().OpenMP >= 50)
6827 AllowedNameModifiers.push_back(OMPD_simd);
6828 break;
6829 case OMPD_teams_distribute:
6831 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6832 break;
6833 case OMPD_teams_distribute_simd:
6835 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6836 if (getLangOpts().OpenMP >= 50)
6837 AllowedNameModifiers.push_back(OMPD_simd);
6838 break;
6839 case OMPD_teams_distribute_parallel_for_simd:
6841 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6842 AllowedNameModifiers.push_back(OMPD_parallel);
6843 if (getLangOpts().OpenMP >= 50)
6844 AllowedNameModifiers.push_back(OMPD_simd);
6845 break;
6846 case OMPD_teams_distribute_parallel_for:
6848 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6849 AllowedNameModifiers.push_back(OMPD_parallel);
6850 break;
6851 case OMPD_target_teams:
6852 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6853 EndLoc);
6854 AllowedNameModifiers.push_back(OMPD_target);
6855 break;
6856 case OMPD_target_teams_distribute:
6858 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6859 AllowedNameModifiers.push_back(OMPD_target);
6860 break;
6861 case OMPD_target_teams_distribute_parallel_for:
6863 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6864 AllowedNameModifiers.push_back(OMPD_target);
6865 AllowedNameModifiers.push_back(OMPD_parallel);
6866 break;
6867 case OMPD_target_teams_distribute_parallel_for_simd:
6869 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6870 AllowedNameModifiers.push_back(OMPD_target);
6871 AllowedNameModifiers.push_back(OMPD_parallel);
6872 if (getLangOpts().OpenMP >= 50)
6873 AllowedNameModifiers.push_back(OMPD_simd);
6874 break;
6875 case OMPD_target_teams_distribute_simd:
6877 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6878 AllowedNameModifiers.push_back(OMPD_target);
6879 if (getLangOpts().OpenMP >= 50)
6880 AllowedNameModifiers.push_back(OMPD_simd);
6881 break;
6882 case OMPD_interop:
6883 assert(AStmt == nullptr &&
6884 "No associated statement allowed for 'omp interop' directive");
6885 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6886 break;
6887 case OMPD_dispatch:
6888 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6889 EndLoc);
6890 break;
6891 case OMPD_loop:
6892 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6893 EndLoc, VarsWithInheritedDSA);
6894 break;
6895 case OMPD_teams_loop:
6897 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6898 break;
6899 case OMPD_target_teams_loop:
6901 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6902 AllowedNameModifiers.push_back(OMPD_target);
6903 break;
6904 case OMPD_parallel_loop:
6906 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6907 break;
6908 case OMPD_target_parallel_loop:
6910 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6911 break;
6912 case OMPD_declare_target:
6913 case OMPD_end_declare_target:
6914 case OMPD_threadprivate:
6915 case OMPD_allocate:
6916 case OMPD_declare_reduction:
6917 case OMPD_declare_mapper:
6918 case OMPD_declare_simd:
6919 case OMPD_requires:
6920 case OMPD_declare_variant:
6921 case OMPD_begin_declare_variant:
6922 case OMPD_end_declare_variant:
6923 llvm_unreachable("OpenMP Directive is not allowed");
6924 case OMPD_unknown:
6925 default:
6926 llvm_unreachable("Unknown OpenMP directive");
6927 }
6928
6929 ErrorFound = Res.isInvalid() || ErrorFound;
6930
6931 // Check variables in the clauses if default(none) or
6932 // default(firstprivate) was specified.
6933 if (DSAStack->getDefaultDSA() == DSA_none ||
6934 DSAStack->getDefaultDSA() == DSA_private ||
6935 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6936 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6937 for (OMPClause *C : Clauses) {
6938 switch (C->getClauseKind()) {
6939 case OMPC_num_threads:
6940 case OMPC_dist_schedule:
6941 // Do not analyse if no parent teams directive.
6942 if (isOpenMPTeamsDirective(Kind))
6943 break;
6944 continue;
6945 case OMPC_if:
6946 if (isOpenMPTeamsDirective(Kind) &&
6947 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6948 break;
6949 if (isOpenMPParallelDirective(Kind) &&
6951 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6952 break;
6953 continue;
6954 case OMPC_schedule:
6955 case OMPC_detach:
6956 break;
6957 case OMPC_grainsize:
6958 case OMPC_num_tasks:
6959 case OMPC_final:
6960 case OMPC_priority:
6961 case OMPC_novariants:
6962 case OMPC_nocontext:
6963 // Do not analyze if no parent parallel directive.
6964 if (isOpenMPParallelDirective(Kind))
6965 break;
6966 continue;
6967 case OMPC_ordered:
6968 case OMPC_device:
6969 case OMPC_num_teams:
6970 case OMPC_thread_limit:
6971 case OMPC_hint:
6972 case OMPC_collapse:
6973 case OMPC_safelen:
6974 case OMPC_simdlen:
6975 case OMPC_sizes:
6976 case OMPC_default:
6977 case OMPC_proc_bind:
6978 case OMPC_private:
6979 case OMPC_firstprivate:
6980 case OMPC_lastprivate:
6981 case OMPC_shared:
6982 case OMPC_reduction:
6983 case OMPC_task_reduction:
6984 case OMPC_in_reduction:
6985 case OMPC_linear:
6986 case OMPC_aligned:
6987 case OMPC_copyin:
6988 case OMPC_copyprivate:
6989 case OMPC_nowait:
6990 case OMPC_untied:
6991 case OMPC_mergeable:
6992 case OMPC_allocate:
6993 case OMPC_read:
6994 case OMPC_write:
6995 case OMPC_update:
6996 case OMPC_capture:
6997 case OMPC_compare:
6998 case OMPC_seq_cst:
6999 case OMPC_acq_rel:
7000 case OMPC_acquire:
7001 case OMPC_release:
7002 case OMPC_relaxed:
7003 case OMPC_depend:
7004 case OMPC_threads:
7005 case OMPC_simd:
7006 case OMPC_map:
7007 case OMPC_nogroup:
7008 case OMPC_defaultmap:
7009 case OMPC_to:
7010 case OMPC_from:
7011 case OMPC_use_device_ptr:
7012 case OMPC_use_device_addr:
7013 case OMPC_is_device_ptr:
7014 case OMPC_has_device_addr:
7015 case OMPC_nontemporal:
7016 case OMPC_order:
7017 case OMPC_destroy:
7018 case OMPC_inclusive:
7019 case OMPC_exclusive:
7020 case OMPC_uses_allocators:
7021 case OMPC_affinity:
7022 case OMPC_bind:
7023 case OMPC_filter:
7024 continue;
7025 case OMPC_allocator:
7026 case OMPC_flush:
7027 case OMPC_depobj:
7028 case OMPC_threadprivate:
7029 case OMPC_uniform:
7030 case OMPC_unknown:
7031 case OMPC_unified_address:
7032 case OMPC_unified_shared_memory:
7033 case OMPC_reverse_offload:
7034 case OMPC_dynamic_allocators:
7035 case OMPC_atomic_default_mem_order:
7036 case OMPC_device_type:
7037 case OMPC_match:
7038 case OMPC_when:
7039 case OMPC_at:
7040 case OMPC_severity:
7041 case OMPC_message:
7042 default:
7043 llvm_unreachable("Unexpected clause");
7044 }
7045 for (Stmt *CC : C->children()) {
7046 if (CC)
7047 DSAChecker.Visit(CC);
7048 }
7049 }
7050 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
7051 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
7052 }
7053 for (const auto &P : VarsWithInheritedDSA) {
7054 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
7055 continue;
7056 ErrorFound = true;
7057 if (DSAStack->getDefaultDSA() == DSA_none ||
7058 DSAStack->getDefaultDSA() == DSA_private ||
7059 DSAStack->getDefaultDSA() == DSA_firstprivate) {
7060 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
7061 << P.first << P.second->getSourceRange();
7062 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
7063 } else if (getLangOpts().OpenMP >= 50) {
7064 Diag(P.second->getExprLoc(),
7065 diag::err_omp_defaultmap_no_attr_for_variable)
7066 << P.first << P.second->getSourceRange();
7067 Diag(DSAStack->getDefaultDSALocation(),
7068 diag::note_omp_defaultmap_attr_none);
7069 }
7070 }
7071
7072 if (!AllowedNameModifiers.empty())
7073 ErrorFound = checkIfClauses(SemaRef, Kind, Clauses, AllowedNameModifiers) ||
7074 ErrorFound;
7075
7076 if (ErrorFound)
7077 return StmtError();
7078
7081 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
7082 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
7083 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
7084 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
7085 // Register target to DSA Stack.
7086 DSAStack->addTargetDirLocation(StartLoc);
7087 }
7088
7089 return Res;
7090}
7091
7093 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
7094 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
7095 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
7096 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
7097 assert(Aligneds.size() == Alignments.size());
7098 assert(Linears.size() == LinModifiers.size());
7099 assert(Linears.size() == Steps.size());
7100 if (!DG || DG.get().isNull())
7101 return DeclGroupPtrTy();
7102
7103 const int SimdId = 0;
7104 if (!DG.get().isSingleDecl()) {
7105 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7106 << SimdId;
7107 return DG;
7108 }
7109 Decl *ADecl = DG.get().getSingleDecl();
7110 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7111 ADecl = FTD->getTemplatedDecl();
7112
7113 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7114 if (!FD) {
7115 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
7116 return DeclGroupPtrTy();
7117 }
7118
7119 // OpenMP [2.8.2, declare simd construct, Description]
7120 // The parameter of the simdlen clause must be a constant positive integer
7121 // expression.
7122 ExprResult SL;
7123 if (Simdlen)
7124 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
7125 // OpenMP [2.8.2, declare simd construct, Description]
7126 // The special this pointer can be used as if was one of the arguments to the
7127 // function in any of the linear, aligned, or uniform clauses.
7128 // The uniform clause declares one or more arguments to have an invariant
7129 // value for all concurrent invocations of the function in the execution of a
7130 // single SIMD loop.
7131 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
7132 const Expr *UniformedLinearThis = nullptr;
7133 for (const Expr *E : Uniforms) {
7134 E = E->IgnoreParenImpCasts();
7135 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7136 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
7137 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7138 FD->getParamDecl(PVD->getFunctionScopeIndex())
7139 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
7140 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
7141 continue;
7142 }
7143 if (isa<CXXThisExpr>(E)) {
7144 UniformedLinearThis = E;
7145 continue;
7146 }
7147 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7148 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7149 }
7150 // OpenMP [2.8.2, declare simd construct, Description]
7151 // The aligned clause declares that the object to which each list item points
7152 // is aligned to the number of bytes expressed in the optional parameter of
7153 // the aligned clause.
7154 // The special this pointer can be used as if was one of the arguments to the
7155 // function in any of the linear, aligned, or uniform clauses.
7156 // The type of list items appearing in the aligned clause must be array,
7157 // pointer, reference to array, or reference to pointer.
7158 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
7159 const Expr *AlignedThis = nullptr;
7160 for (const Expr *E : Aligneds) {
7161 E = E->IgnoreParenImpCasts();
7162 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7163 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7164 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7165 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7166 FD->getParamDecl(PVD->getFunctionScopeIndex())
7167 ->getCanonicalDecl() == CanonPVD) {
7168 // OpenMP [2.8.1, simd construct, Restrictions]
7169 // A list-item cannot appear in more than one aligned clause.
7170 if (AlignedArgs.count(CanonPVD) > 0) {
7171 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
7172 << 1 << getOpenMPClauseName(OMPC_aligned)
7173 << E->getSourceRange();
7174 Diag(AlignedArgs[CanonPVD]->getExprLoc(),
7175 diag::note_omp_explicit_dsa)
7176 << getOpenMPClauseName(OMPC_aligned);
7177 continue;
7178 }
7179 AlignedArgs[CanonPVD] = E;
7180 QualType QTy = PVD->getType()
7181 .getNonReferenceType()
7182 .getUnqualifiedType()
7183 .getCanonicalType();
7184 const Type *Ty = QTy.getTypePtrOrNull();
7185 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
7186 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
7187 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
7188 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
7189 }
7190 continue;
7191 }
7192 }
7193 if (isa<CXXThisExpr>(E)) {
7194 if (AlignedThis) {
7195 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
7196 << 2 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange();
7197 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
7198 << getOpenMPClauseName(OMPC_aligned);
7199 }
7200 AlignedThis = E;
7201 continue;
7202 }
7203 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7204 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7205 }
7206 // The optional parameter of the aligned clause, alignment, must be a constant
7207 // positive integer expression. If no optional parameter is specified,
7208 // implementation-defined default alignments for SIMD instructions on the
7209 // target platforms are assumed.
7211 for (Expr *E : Alignments) {
7212 ExprResult Align;
7213 if (E)
7214 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
7215 NewAligns.push_back(Align.get());
7216 }
7217 // OpenMP [2.8.2, declare simd construct, Description]
7218 // The linear clause declares one or more list items to be private to a SIMD
7219 // lane and to have a linear relationship with respect to the iteration space
7220 // of a loop.
7221 // The special this pointer can be used as if was one of the arguments to the
7222 // function in any of the linear, aligned, or uniform clauses.
7223 // When a linear-step expression is specified in a linear clause it must be
7224 // either a constant integer expression or an integer-typed parameter that is
7225 // specified in a uniform clause on the directive.
7226 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7227 const bool IsUniformedThis = UniformedLinearThis != nullptr;
7228 auto MI = LinModifiers.begin();
7229 for (const Expr *E : Linears) {
7230 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
7231 ++MI;
7232 E = E->IgnoreParenImpCasts();
7233 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7234 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7235 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7236 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7237 FD->getParamDecl(PVD->getFunctionScopeIndex())
7238 ->getCanonicalDecl() == CanonPVD) {
7239 // OpenMP [2.15.3.7, linear Clause, Restrictions]
7240 // A list-item cannot appear in more than one linear clause.
7241 if (LinearArgs.count(CanonPVD) > 0) {
7242 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7243 << getOpenMPClauseName(OMPC_linear)
7244 << getOpenMPClauseName(OMPC_linear) << E->getSourceRange();
7245 Diag(LinearArgs[CanonPVD]->getExprLoc(),
7246 diag::note_omp_explicit_dsa)
7247 << getOpenMPClauseName(OMPC_linear);
7248 continue;
7249 }
7250 // Each argument can appear in at most one uniform or linear clause.
7251 if (UniformedArgs.count(CanonPVD) > 0) {
7252 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7253 << getOpenMPClauseName(OMPC_linear)
7254 << getOpenMPClauseName(OMPC_uniform) << E->getSourceRange();
7255 Diag(UniformedArgs[CanonPVD]->getExprLoc(),
7256 diag::note_omp_explicit_dsa)
7257 << getOpenMPClauseName(OMPC_uniform);
7258 continue;
7259 }
7260 LinearArgs[CanonPVD] = E;
7261 if (E->isValueDependent() || E->isTypeDependent() ||
7264 continue;
7265 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
7266 PVD->getOriginalType(),
7267 /*IsDeclareSimd=*/true);
7268 continue;
7269 }
7270 }
7271 if (isa<CXXThisExpr>(E)) {
7272 if (UniformedLinearThis) {
7273 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7274 << getOpenMPClauseName(OMPC_linear)
7275 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear)
7276 << E->getSourceRange();
7277 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
7278 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform
7279 : OMPC_linear);
7280 continue;
7281 }
7282 UniformedLinearThis = E;
7283 if (E->isValueDependent() || E->isTypeDependent() ||
7285 continue;
7286 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
7287 E->getType(), /*IsDeclareSimd=*/true);
7288 continue;
7289 }
7290 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7291 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7292 }
7293 Expr *Step = nullptr;
7294 Expr *NewStep = nullptr;
7295 SmallVector<Expr *, 4> NewSteps;
7296 for (Expr *E : Steps) {
7297 // Skip the same step expression, it was checked already.
7298 if (Step == E || !E) {
7299 NewSteps.push_back(E ? NewStep : nullptr);
7300 continue;
7301 }
7302 Step = E;
7303 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
7304 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7305 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7306 if (UniformedArgs.count(CanonPVD) == 0) {
7307 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
7308 << Step->getSourceRange();
7309 } else if (E->isValueDependent() || E->isTypeDependent() ||
7312 CanonPVD->getType()->hasIntegerRepresentation()) {
7313 NewSteps.push_back(Step);
7314 } else {
7315 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
7316 << Step->getSourceRange();
7317 }
7318 continue;
7319 }
7320 NewStep = Step;
7321 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
7322 !Step->isInstantiationDependent() &&
7324 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
7325 .get();
7326 if (NewStep)
7327 NewStep = SemaRef
7329 NewStep, /*FIXME*/ Sema::AllowFold)
7330 .get();
7331 }
7332 NewSteps.push_back(NewStep);
7333 }
7334 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7335 getASTContext(), BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
7336 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
7337 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
7338 const_cast<Expr **>(Linears.data()), Linears.size(),
7339 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
7340 NewSteps.data(), NewSteps.size(), SR);
7341 ADecl->addAttr(NewAttr);
7342 return DG;
7343}
7344
7345static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7346 QualType NewType) {
7347 assert(NewType->isFunctionProtoType() &&
7348 "Expected function type with prototype.");
7349 assert(FD->getType()->isFunctionNoProtoType() &&
7350 "Expected function with type with no prototype.");
7351 assert(FDWithProto->getType()->isFunctionProtoType() &&
7352 "Expected function with prototype.");
7353 // Synthesize parameters with the same types.
7354 FD->setType(NewType);
7356 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7357 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
7358 SourceLocation(), nullptr, P->getType(),
7359 /*TInfo=*/nullptr, SC_None, nullptr);
7360 Param->setScopeInfo(0, Params.size());
7361 Param->setImplicit();
7362 Params.push_back(Param);
7363 }
7364
7365 FD->setParams(Params);
7366}
7367
7369 if (D->isInvalidDecl())
7370 return;
7371 FunctionDecl *FD = nullptr;
7372 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7373 FD = UTemplDecl->getTemplatedDecl();
7374 else
7375 FD = cast<FunctionDecl>(D);
7376 assert(FD && "Expected a function declaration!");
7377
7378 // If we are instantiating templates we do *not* apply scoped assumptions but
7379 // only global ones. We apply scoped assumption to the template definition
7380 // though.
7382 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7383 FD->addAttr(AA);
7384 }
7385 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7386 FD->addAttr(AA);
7387}
7388
7389SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7390 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7391
7393 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7395 if (!D.getIdentifier())
7396 return;
7397
7398 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7399
7400 // Template specialization is an extension, check if we do it.
7401 bool IsTemplated = !TemplateParamLists.empty();
7402 if (IsTemplated &
7403 !DVScope.TI->isExtensionActive(
7404 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7405 return;
7406
7407 const IdentifierInfo *BaseII = D.getIdentifier();
7410 SemaRef.LookupParsedName(Lookup, S, &D.getCXXScopeSpec());
7411
7413 QualType FType = TInfo->getType();
7414
7415 bool IsConstexpr =
7417 bool IsConsteval =
7419
7420 for (auto *Candidate : Lookup) {
7421 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7422 FunctionDecl *UDecl = nullptr;
7423 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7424 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7425 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7426 UDecl = FTD->getTemplatedDecl();
7427 } else if (!IsTemplated)
7428 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7429 if (!UDecl)
7430 continue;
7431
7432 // Don't specialize constexpr/consteval functions with
7433 // non-constexpr/consteval functions.
7434 if (UDecl->isConstexpr() && !IsConstexpr)
7435 continue;
7436 if (UDecl->isConsteval() && !IsConsteval)
7437 continue;
7438
7439 QualType UDeclTy = UDecl->getType();
7440 if (!UDeclTy->isDependentType()) {
7442 FType, UDeclTy, /* OfBlockPointer */ false,
7443 /* Unqualified */ false, /* AllowCXX */ true);
7444 if (NewType.isNull())
7445 continue;
7446 }
7447
7448 // Found a base!
7449 Bases.push_back(UDecl);
7450 }
7451
7452 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7453 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7454 // If no base was found we create a declaration that we use as base.
7455 if (Bases.empty() && UseImplicitBase) {
7457 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7458 BaseD->setImplicit(true);
7459 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7460 Bases.push_back(BaseTemplD->getTemplatedDecl());
7461 else
7462 Bases.push_back(cast<FunctionDecl>(BaseD));
7463 }
7464
7465 std::string MangledName;
7466 MangledName += D.getIdentifier()->getName();
7467 MangledName += getOpenMPVariantManglingSeparatorStr();
7468 MangledName += DVScope.NameSuffix;
7469 IdentifierInfo &VariantII = getASTContext().Idents.get(MangledName);
7470
7471 VariantII.setMangledOpenMPVariantName(true);
7472 D.SetIdentifier(&VariantII, D.getBeginLoc());
7473}
7474
7477 // Do not mark function as is used to prevent its emission if this is the
7478 // only place where it is used.
7481
7482 FunctionDecl *FD = nullptr;
7483 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7484 FD = UTemplDecl->getTemplatedDecl();
7485 else
7486 FD = cast<FunctionDecl>(D);
7487 auto *VariantFuncRef = DeclRefExpr::Create(
7489 /* RefersToEnclosingVariableOrCapture */ false,
7490 /* NameLoc */ FD->getLocation(), FD->getType(),
7492
7493 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7494 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7495 getASTContext(), VariantFuncRef, DVScope.TI,
7496 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7497 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7498 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7499 for (FunctionDecl *BaseFD : Bases)
7500 BaseFD->addAttr(OMPDeclareVariantA);
7501}
7502
7504 SourceLocation LParenLoc,
7505 MultiExprArg ArgExprs,
7506 SourceLocation RParenLoc,
7507 Expr *ExecConfig) {
7508 // The common case is a regular call we do not want to specialize at all. Try
7509 // to make that case fast by bailing early.
7510 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7511 if (!CE)
7512 return Call;
7513
7514 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7515 if (!CalleeFnDecl)
7516 return Call;
7517
7518 if (getLangOpts().OpenMP >= 51 && CalleeFnDecl->getIdentifier() &&
7519 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7520 // checking for any calls inside an Order region
7522 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7523 }
7524
7525 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7526 return Call;
7527
7528 ASTContext &Context = getASTContext();
7529 std::function<void(StringRef)> DiagUnknownTrait = [this,
7530 CE](StringRef ISATrait) {
7531 // TODO Track the selector locations in a way that is accessible here to
7532 // improve the diagnostic location.
7533 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7534 << ISATrait;
7535 };
7536 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7538 DSAStack->getConstructTraits());
7539
7540 QualType CalleeFnType = CalleeFnDecl->getType();
7541
7544 while (CalleeFnDecl) {
7545 for (OMPDeclareVariantAttr *A :
7546 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7547 Expr *VariantRef = A->getVariantFuncRef();
7548
7549 VariantMatchInfo VMI;
7550 OMPTraitInfo &TI = A->getTraitInfo();
7551 TI.getAsVariantMatchInfo(Context, VMI);
7552 if (!isVariantApplicableInContext(VMI, OMPCtx,
7553 /* DeviceSetOnly */ false))
7554 continue;
7555
7556 VMIs.push_back(VMI);
7557 Exprs.push_back(VariantRef);
7558 }
7559
7560 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7561 }
7562
7563 ExprResult NewCall;
7564 do {
7565 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7566 if (BestIdx < 0)
7567 return Call;
7568 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7569 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7570
7571 {
7572 // Try to build a (member) call expression for the current best applicable
7573 // variant expression. We allow this to fail in which case we continue
7574 // with the next best variant expression. The fail case is part of the
7575 // implementation defined behavior in the OpenMP standard when it talks
7576 // about what differences in the function prototypes: "Any differences
7577 // that the specific OpenMP context requires in the prototype of the
7578 // variant from the base function prototype are implementation defined."
7579 // This wording is there to allow the specialized variant to have a
7580 // different type than the base function. This is intended and OK but if
7581 // we cannot create a call the difference is not in the "implementation
7582 // defined range" we allow.
7584
7585 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7586 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7587 BestExpr = MemberExpr::CreateImplicit(
7588 Context, MemberCall->getImplicitObjectArgument(),
7589 /* IsArrow */ false, SpecializedMethod, Context.BoundMemberTy,
7590 MemberCall->getValueKind(), MemberCall->getObjectKind());
7591 }
7592 NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs,
7593 RParenLoc, ExecConfig);
7594 if (NewCall.isUsable()) {
7595 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7596 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7598 CalleeFnType, NewCalleeFnDecl->getType(),
7599 /* OfBlockPointer */ false,
7600 /* Unqualified */ false, /* AllowCXX */ true);
7601 if (!NewType.isNull())
7602 break;
7603 // Don't use the call if the function type was not compatible.
7604 NewCall = nullptr;
7605 }
7606 }
7607 }
7608
7609 VMIs.erase(VMIs.begin() + BestIdx);
7610 Exprs.erase(Exprs.begin() + BestIdx);
7611 } while (!VMIs.empty());
7612
7613 if (!NewCall.isUsable())
7614 return Call;
7615 return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
7616}
7617
7618std::optional<std::pair<FunctionDecl *, Expr *>>
7620 Expr *VariantRef,
7621 OMPTraitInfo &TI,
7622 unsigned NumAppendArgs,
7623 SourceRange SR) {
7624 ASTContext &Context = getASTContext();
7625 if (!DG || DG.get().isNull())
7626 return std::nullopt;
7627
7628 const int VariantId = 1;
7629 // Must be applied only to single decl.
7630 if (!DG.get().isSingleDecl()) {
7631 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7632 << VariantId << SR;
7633 return std::nullopt;
7634 }
7635 Decl *ADecl = DG.get().getSingleDecl();
7636 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7637 ADecl = FTD->getTemplatedDecl();
7638
7639 // Decl must be a function.
7640 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7641 if (!FD) {
7642 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7643 << VariantId << SR;
7644 return std::nullopt;
7645 }
7646
7647 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7648 // The 'target' attribute needs to be separately checked because it does
7649 // not always signify a multiversion function declaration.
7650 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7651 };
7652 // OpenMP is not compatible with multiversion function attributes.
7653 if (HasMultiVersionAttributes(FD)) {
7654 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7655 << SR;
7656 return std::nullopt;
7657 }
7658
7659 // Allow #pragma omp declare variant only if the function is not used.
7660 if (FD->isUsed(false))
7661 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7662 << FD->getLocation();
7663
7664 // Check if the function was emitted already.
7665 const FunctionDecl *Definition;
7666 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7667 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7668 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7669 << FD->getLocation();
7670
7671 // The VariantRef must point to function.
7672 if (!VariantRef) {
7673 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7674 return std::nullopt;
7675 }
7676
7677 auto ShouldDelayChecks = [](Expr *&E, bool) {
7678 return E && (E->isTypeDependent() || E->isValueDependent() ||
7681 };
7682 // Do not check templates, wait until instantiation.
7683 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7684 TI.anyScoreOrCondition(ShouldDelayChecks))
7685 return std::make_pair(FD, VariantRef);
7686
7687 // Deal with non-constant score and user condition expressions.
7688 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7689 bool IsScore) -> bool {
7690 if (!E || E->isIntegerConstantExpr(getASTContext()))
7691 return false;
7692
7693 if (IsScore) {
7694 // We warn on non-constant scores and pretend they were not present.
7695 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7696 << E;
7697 E = nullptr;
7698 } else {
7699 // We could replace a non-constant user condition with "false" but we
7700 // will soon need to handle these anyway for the dynamic version of
7701 // OpenMP context selectors.
7702 Diag(E->getExprLoc(),
7703 diag::err_omp_declare_variant_user_condition_not_constant)
7704 << E;
7705 }
7706 return true;
7707 };
7708 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7709 return std::nullopt;
7710
7711 QualType AdjustedFnType = FD->getType();
7712 if (NumAppendArgs) {
7713 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7714 if (!PTy) {
7715 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7716 << SR;
7717 return std::nullopt;
7718 }
7719 // Adjust the function type to account for an extra omp_interop_t for each
7720 // specified in the append_args clause.
7721 const TypeDecl *TD = nullptr;
7722 LookupResult Result(SemaRef, &Context.Idents.get("omp_interop_t"),
7725 NamedDecl *ND = Result.getFoundDecl();
7726 TD = dyn_cast_or_null<TypeDecl>(ND);
7727 }
7728 if (!TD) {
7729 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7730 return std::nullopt;
7731 }
7732 QualType InteropType = Context.getTypeDeclType(TD);
7733 if (PTy->isVariadic()) {
7734 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7735 return std::nullopt;
7736 }
7738 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7739 Params.insert(Params.end(), NumAppendArgs, InteropType);
7740 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7741 PTy->getExtProtoInfo());
7742 }
7743
7744 // Convert VariantRef expression to the type of the original function to
7745 // resolve possible conflicts.
7746 ExprResult VariantRefCast = VariantRef;
7747 if (getLangOpts().CPlusPlus) {
7748 QualType FnPtrType;
7749 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7750 if (Method && !Method->isStatic()) {
7751 const Type *ClassType =
7752 Context.getTypeDeclType(Method->getParent()).getTypePtr();
7753 FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType);
7754 ExprResult ER;
7755 {
7756 // Build adrr_of unary op to correctly handle type checks for member
7757 // functions.
7759 ER = SemaRef.CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7760 VariantRef);
7761 }
7762 if (!ER.isUsable()) {
7763 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7764 << VariantId << VariantRef->getSourceRange();
7765 return std::nullopt;
7766 }
7767 VariantRef = ER.get();
7768 } else {
7769 FnPtrType = Context.getPointerType(AdjustedFnType);
7770 }
7771 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7772 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7774 VariantRef, FnPtrType.getUnqualifiedType(),
7775 /*SuppressUserConversions=*/false, Sema::AllowedExplicit::None,
7776 /*InOverloadResolution=*/false,
7777 /*CStyle=*/false,
7778 /*AllowObjCWritebackConversion=*/false);
7779 if (ICS.isFailure()) {
7780 Diag(VariantRef->getExprLoc(),
7781 diag::err_omp_declare_variant_incompat_types)
7782 << VariantRef->getType()
7783 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7784 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7785 return std::nullopt;
7786 }
7787 VariantRefCast = SemaRef.PerformImplicitConversion(
7788 VariantRef, FnPtrType.getUnqualifiedType(), Sema::AA_Converting);
7789 if (!VariantRefCast.isUsable())
7790 return std::nullopt;
7791 }
7792 // Drop previously built artificial addr_of unary op for member functions.
7793 if (Method && !Method->isStatic()) {
7794 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7795 if (auto *UO = dyn_cast<UnaryOperator>(
7796 PossibleAddrOfVariantRef->IgnoreImplicit()))
7797 VariantRefCast = UO->getSubExpr();
7798 }
7799 }
7800
7801 ExprResult ER = SemaRef.CheckPlaceholderExpr(VariantRefCast.get());
7802 if (!ER.isUsable() ||
7804 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7805 << VariantId << VariantRef->getSourceRange();
7806 return std::nullopt;
7807 }
7808
7809 // The VariantRef must point to function.
7810 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7811 if (!DRE) {
7812 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7813 << VariantId << VariantRef->getSourceRange();
7814 return std::nullopt;
7815 }
7816 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7817 if (!NewFD) {
7818 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7819 << VariantId << VariantRef->getSourceRange();
7820 return std::nullopt;
7821 }
7822
7823 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7824 Diag(VariantRef->getExprLoc(),
7825 diag::err_omp_declare_variant_same_base_function)
7826 << VariantRef->getSourceRange();
7827 return std::nullopt;
7828 }
7829
7830 // Check if function types are compatible in C.
7831 if (!getLangOpts().CPlusPlus) {
7832 QualType NewType =
7833 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7834 if (NewType.isNull()) {
7835 Diag(VariantRef->getExprLoc(),
7836 diag::err_omp_declare_variant_incompat_types)
7837 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7838 << VariantRef->getSourceRange();
7839 return std::nullopt;
7840 }
7841 if (NewType->isFunctionProtoType()) {
7842 if (FD->getType()->isFunctionNoProtoType())
7843 setPrototype(SemaRef, FD, NewFD, NewType);
7844 else if (NewFD->getType()->isFunctionNoProtoType())
7845 setPrototype(SemaRef, NewFD, FD, NewType);
7846 }
7847 }
7848
7849 // Check if variant function is not marked with declare variant directive.
7850 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7851 Diag(VariantRef->getExprLoc(),
7852 diag::warn_omp_declare_variant_marked_as_declare_variant)
7853 << VariantRef->getSourceRange();
7854 SourceRange SR =
7855 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7856 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7857 return std::nullopt;
7858 }
7859
7860 enum DoesntSupport {
7861 VirtFuncs = 1,
7862 Constructors = 3,
7863 Destructors = 4,
7864 DeletedFuncs = 5,
7865 DefaultedFuncs = 6,
7866 ConstexprFuncs = 7,
7867 ConstevalFuncs = 8,
7868 };
7869 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7870 if (CXXFD->isVirtual()) {
7871 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7872 << VirtFuncs;
7873 return std::nullopt;
7874 }
7875
7876 if (isa<CXXConstructorDecl>(FD)) {
7877 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7878 << Constructors;
7879 return std::nullopt;
7880 }
7881
7882 if (isa<CXXDestructorDecl>(FD)) {
7883 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7884 << Destructors;
7885 return std::nullopt;
7886 }
7887 }
7888
7889 if (FD->isDeleted()) {
7890 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7891 << DeletedFuncs;
7892 return std::nullopt;
7893 }
7894
7895 if (FD->isDefaulted()) {
7896 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7897 << DefaultedFuncs;
7898 return std::nullopt;
7899 }
7900
7901 if (FD->isConstexpr()) {
7902 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7903 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7904 return std::nullopt;
7905 }
7906
7907 // Check general compatibility.
7913 VariantRef->getExprLoc(),
7914 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7915 PartialDiagnosticAt(VariantRef->getExprLoc(),
7916 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7917 << FD->getLocation()),
7918 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7919 /*CLinkageMayDiffer=*/true))
7920 return std::nullopt;
7921 return std::make_pair(FD, cast<Expr>(DRE));
7922}
7923
7925 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7926 ArrayRef<Expr *> AdjustArgsNothing,
7927 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7928 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7929 SourceLocation AppendArgsLoc, SourceRange SR) {
7930
7931 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7932 // An adjust_args clause or append_args clause can only be specified if the
7933 // dispatch selector of the construct selector set appears in the match
7934 // clause.
7935
7936 SmallVector<Expr *, 8> AllAdjustArgs;
7937 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7938 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7939
7940 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7941 VariantMatchInfo VMI;
7943 if (!llvm::is_contained(
7944 VMI.ConstructTraits,
7945 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7946 if (!AllAdjustArgs.empty())
7947 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7948 << getOpenMPClauseName(OMPC_adjust_args);
7949 if (!AppendArgs.empty())
7950 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7951 << getOpenMPClauseName(OMPC_append_args);
7952 return;
7953 }
7954 }
7955
7956 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7957 // Each argument can only appear in a single adjust_args clause for each
7958 // declare variant directive.
7960
7961 for (Expr *E : AllAdjustArgs) {
7962 E = E->IgnoreParenImpCasts();
7963 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7964 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7965 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7966 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7967 FD->getParamDecl(PVD->getFunctionScopeIndex())
7968 ->getCanonicalDecl() == CanonPVD) {
7969 // It's a parameter of the function, check duplicates.
7970 if (!AdjustVars.insert(CanonPVD).second) {
7971 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7972 << PVD;
7973 return;
7974 }
7975 continue;
7976 }
7977 }
7978 }
7979 // Anything that is not a function parameter is an error.
7980 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7981 return;
7982 }
7983
7984 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7985 getASTContext(), VariantRef, &TI,
7986 const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7987 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7988 AdjustArgsNeedDevicePtr.size(),
7989 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7990 FD->addAttr(NewAttr);
7991}
7992
7995 Stmt *AStmt, SourceLocation StartLoc,
7996 SourceLocation EndLoc) {
7997 if (!AStmt)
7998 return StmtError();
7999
8000 auto *CS = cast<CapturedStmt>(AStmt);
8001 // 1.2.2 OpenMP Language Terminology
8002 // Structured block - An executable statement with a single entry at the
8003 // top and a single exit at the bottom.
8004 // The point of exit cannot be a branch out of the structured block.
8005 // longjmp() and throw() must not violate the entry/exit criteria.
8006 CS->getCapturedDecl()->setNothrow();
8007
8009
8011 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
8012 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
8013}
8014
8015namespace {
8016/// Iteration space of a single for loop.
8017struct LoopIterationSpace final {
8018 /// True if the condition operator is the strict compare operator (<, > or
8019 /// !=).
8020 bool IsStrictCompare = false;
8021 /// Condition of the loop.
8022 Expr *PreCond = nullptr;
8023 /// This expression calculates the number of iterations in the loop.
8024 /// It is always possible to calculate it before starting the loop.
8025 Expr *NumIterations = nullptr;
8026 /// The loop counter variable.
8027 Expr *CounterVar = nullptr;
8028 /// Private loop counter variable.
8029 Expr *PrivateCounterVar = nullptr;
8030 /// This is initializer for the initial value of #CounterVar.
8031 Expr *CounterInit = nullptr;
8032 /// This is step for the #CounterVar used to generate its update:
8033 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
8034 Expr *CounterStep = nullptr;
8035 /// Should step be subtracted?
8036 bool Subtract = false;
8037 /// Source range of the loop init.
8038 SourceRange InitSrcRange;
8039 /// Source range of the loop condition.
8040 SourceRange CondSrcRange;
8041 /// Source range of the loop increment.
8042 SourceRange IncSrcRange;
8043 /// Minimum value that can have the loop control variable. Used to support
8044 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
8045 /// since only such variables can be used in non-loop invariant expressions.
8046 Expr *MinValue = nullptr;
8047 /// Maximum value that can have the loop control variable. Used to support
8048 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
8049 /// since only such variables can be used in non-loop invariant expressions.
8050 Expr *MaxValue = nullptr;
8051 /// true, if the lower bound depends on the outer loop control var.
8052 bool IsNonRectangularLB = false;
8053 /// true, if the upper bound depends on the outer loop control var.
8054 bool IsNonRectangularUB = false;
8055 /// Index of the loop this loop depends on and forms non-rectangular loop
8056 /// nest.
8057 unsigned LoopDependentIdx = 0;
8058 /// Final condition for the non-rectangular loop nest support. It is used to
8059 /// check that the number of iterations for this particular counter must be
8060 /// finished.
8061 Expr *FinalCondition = nullptr;
8062};
8063
8064/// Helper class for checking canonical form of the OpenMP loops and
8065/// extracting iteration space of each loop in the loop nest, that will be used
8066/// for IR generation.
8067class OpenMPIterationSpaceChecker {
8068 /// Reference to Sema.
8069 Sema &SemaRef;
8070 /// Does the loop associated directive support non-rectangular loops?
8071 bool SupportsNonRectangular;
8072 /// Data-sharing stack.
8073 DSAStackTy &Stack;
8074 /// A location for diagnostics (when there is no some better location).
8075 SourceLocation DefaultLoc;
8076 /// A location for diagnostics (when increment is not compatible).
8077 SourceLocation ConditionLoc;
8078 /// A source location for referring to loop init later.
8079 SourceRange InitSrcRange;
8080 /// A source location for referring to condition later.
8081 SourceRange ConditionSrcRange;
8082 /// A source location for referring to increment later.
8083 SourceRange IncrementSrcRange;
8084 /// Loop variable.
8085 ValueDecl *LCDecl = nullptr;
8086 /// Reference to loop variable.
8087 Expr *LCRef = nullptr;
8088 /// Lower bound (initializer for the var).
8089 Expr *LB = nullptr;
8090 /// Upper bound.
8091 Expr *UB = nullptr;
8092 /// Loop step (increment).
8093 Expr *Step = nullptr;
8094 /// This flag is true when condition is one of:
8095 /// Var < UB
8096 /// Var <= UB
8097 /// UB > Var
8098 /// UB >= Var
8099 /// This will have no value when the condition is !=
8100 std::optional<bool> TestIsLessOp;
8101 /// This flag is true when condition is strict ( < or > ).
8102 bool TestIsStrictOp = false;
8103 /// This flag is true when step is subtracted on each iteration.
8104 bool SubtractStep = false;
8105 /// The outer loop counter this loop depends on (if any).
8106 const ValueDecl *DepDecl = nullptr;
8107 /// Contains number of loop (starts from 1) on which loop counter init
8108 /// expression of this loop depends on.
8109 std::optional<unsigned> InitDependOnLC;
8110 /// Contains number of loop (starts from 1) on which loop counter condition
8111 /// expression of this loop depends on.
8112 std::optional<unsigned> CondDependOnLC;
8113 /// Checks if the provide statement depends on the loop counter.
8114 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
8115 bool IsInitializer);
8116 /// Original condition required for checking of the exit condition for
8117 /// non-rectangular loop.
8118 Expr *Condition = nullptr;
8119
8120public:
8121 OpenMPIterationSpaceChecker(Sema &SemaRef, bool SupportsNonRectangular,
8122 DSAStackTy &Stack, SourceLocation DefaultLoc)
8123 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8124 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {}
8125 /// Check init-expr for canonical loop form and save loop counter
8126 /// variable - #Var and its initialization value - #LB.
8127 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
8128 /// Check test-expr for canonical form, save upper-bound (#UB), flags
8129 /// for less/greater and for strict/non-strict comparison.
8130 bool checkAndSetCond(Expr *S);
8131 /// Check incr-expr for canonical loop form and return true if it
8132 /// does not conform, otherwise save loop step (#Step).
8133 bool checkAndSetInc(Expr *S);
8134 /// Return the loop counter variable.
8135 ValueDecl *getLoopDecl() const { return LCDecl; }
8136 /// Return the reference expression to loop counter variable.
8137 Expr *getLoopDeclRefExpr() const { return LCRef; }
8138 /// Source range of the loop init.
8139 SourceRange getInitSrcRange() const { return InitSrcRange; }
8140 /// Source range of the loop condition.
8141 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
8142 /// Source range of the loop increment.
8143 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
8144 /// True if the step should be subtracted.
8145 bool shouldSubtractStep() const { return SubtractStep; }
8146 /// True, if the compare operator is strict (<, > or !=).
8147 bool isStrictTestOp() const { return TestIsStrictOp; }
8148 /// Build the expression to calculate the number of iterations.
8149 Expr *buildNumIterations(
8150 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8151 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8152 /// Build the precondition expression for the loops.
8153 Expr *
8154 buildPreCond(Scope *S, Expr *Cond,
8155 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8156 /// Build reference expression to the counter be used for codegen.
8157 DeclRefExpr *
8158 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8159 DSAStackTy &DSA) const;
8160 /// Build reference expression to the private counter be used for
8161 /// codegen.
8162 Expr *buildPrivateCounterVar() const;
8163 /// Build initialization of the counter be used for codegen.
8164 Expr *buildCounterInit() const;
8165 /// Build step of the counter be used for codegen.
8166 Expr *buildCounterStep() const;
8167 /// Build loop data with counter value for depend clauses in ordered
8168 /// directives.
8169 Expr *
8170 buildOrderedLoopData(Scope *S, Expr *Counter,
8171 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8172 SourceLocation Loc, Expr *Inc = nullptr,
8173 OverloadedOperatorKind OOK = OO_Amp);
8174 /// Builds the minimum value for the loop counter.
8175 std::pair<Expr *, Expr *> buildMinMaxValues(
8176 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8177 /// Builds final condition for the non-rectangular loops.
8178 Expr *buildFinalCondition(Scope *S) const;
8179 /// Return true if any expression is dependent.
8180 bool dependent() const;
8181 /// Returns true if the initializer forms non-rectangular loop.
8182 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
8183 /// Returns true if the condition forms non-rectangular loop.
8184 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
8185 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
8186 unsigned getLoopDependentIdx() const {
8187 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
8188 }
8189
8190private:
8191 /// Check the right-hand side of an assignment in the increment
8192 /// expression.
8193 bool checkAndSetIncRHS(Expr *RHS);
8194 /// Helper to set loop counter variable and its initializer.
8195 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8196 bool EmitDiags);
8197 /// Helper to set upper bound.
8198 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
8200 /// Helper to set loop increment.
8201 bool setStep(Expr *NewStep, bool Subtract);
8202};
8203
8204bool OpenMPIterationSpaceChecker::dependent() const {
8205 if (!LCDecl) {
8206 assert(!LB && !UB && !Step);
8207 return false;
8208 }
8209 return LCDecl->getType()->isDependentType() ||
8210 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
8211 (Step && Step->isValueDependent());
8212}
8213
8214bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
8215 Expr *NewLCRefExpr,
8216 Expr *NewLB, bool EmitDiags) {
8217 // State consistency checking to ensure correct usage.
8218 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
8219 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8220 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
8221 return true;
8222 LCDecl = getCanonicalDecl(NewLCDecl);
8223 LCRef = NewLCRefExpr;
8224 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
8225 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8226 if ((Ctor->isCopyOrMoveConstructor() ||
8227 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8228 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8229 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
8230 LB = NewLB;
8231 if (EmitDiags)
8232 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
8233 return false;
8234}
8235
8236bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
8237 bool StrictOp, SourceRange SR,
8238 SourceLocation SL) {
8239 // State consistency checking to ensure correct usage.
8240 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
8241 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8242 if (!NewUB || NewUB->containsErrors())
8243 return true;
8244 UB = NewUB;
8245 if (LessOp)
8246 TestIsLessOp = LessOp;
8247 TestIsStrictOp = StrictOp;
8248 ConditionSrcRange = SR;
8249 ConditionLoc = SL;
8250 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
8251 return false;
8252}
8253
8254bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
8255 // State consistency checking to ensure correct usage.
8256 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
8257 if (!NewStep || NewStep->containsErrors())
8258 return true;
8259 if (!NewStep->isValueDependent()) {
8260 // Check that the step is integer expression.
8261 SourceLocation StepLoc = NewStep->getBeginLoc();
8263 StepLoc, getExprAsWritten(NewStep));
8264 if (Val.isInvalid())
8265 return true;
8266 NewStep = Val.get();
8267
8268 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8269 // If test-expr is of form var relational-op b and relational-op is < or
8270 // <= then incr-expr must cause var to increase on each iteration of the
8271 // loop. If test-expr is of form var relational-op b and relational-op is
8272 // > or >= then incr-expr must cause var to decrease on each iteration of
8273 // the loop.
8274 // If test-expr is of form b relational-op var and relational-op is < or
8275 // <= then incr-expr must cause var to decrease on each iteration of the
8276 // loop. If test-expr is of form b relational-op var and relational-op is
8277 // > or >= then incr-expr must cause var to increase on each iteration of
8278 // the loop.
8279 std::optional<llvm::APSInt> Result =
8280 NewStep->getIntegerConstantExpr(SemaRef.Context);
8281 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
8282 bool IsConstNeg =
8283 Result && Result->isSigned() && (Subtract != Result->isNegative());
8284 bool IsConstPos =
8285 Result && Result->isSigned() && (Subtract == Result->isNegative());
8286 bool IsConstZero = Result && !Result->getBoolValue();
8287
8288 // != with increment is treated as <; != with decrement is treated as >
8289 if (!TestIsLessOp)
8290 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8291 if (UB && (IsConstZero ||
8292 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8293 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8294 SemaRef.Diag(NewStep->getExprLoc(),
8295 diag::err_omp_loop_incr_not_compatible)
8296 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
8297 SemaRef.Diag(ConditionLoc,
8298 diag::note_omp_loop_cond_requres_compatible_incr)
8299 << *TestIsLessOp << ConditionSrcRange;
8300 return true;
8301 }
8302 if (*TestIsLessOp == Subtract) {
8303 NewStep =
8304 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
8305 .get();
8306 Subtract = !Subtract;
8307 }
8308 }
8309
8310 Step = NewStep;
8311 SubtractStep = Subtract;
8312 return false;
8313}
8314
8315namespace {
8316/// Checker for the non-rectangular loops. Checks if the initializer or
8317/// condition expression references loop counter variable.
8318class LoopCounterRefChecker final
8319 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8320 Sema &SemaRef;
8321 DSAStackTy &Stack;
8322 const ValueDecl *CurLCDecl = nullptr;
8323 const ValueDecl *DepDecl = nullptr;
8324 const ValueDecl *PrevDepDecl = nullptr;
8325 bool IsInitializer = true;
8326 bool SupportsNonRectangular;
8327 unsigned BaseLoopId = 0;
8328 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8329 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
8330 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8331 << (IsInitializer ? 0 : 1);
8332 return false;
8333 }
8334 const auto &&Data = Stack.isLoopControlVariable(VD);
8335 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8336 // The type of the loop iterator on which we depend may not have a random
8337 // access iterator type.
8338 if (Data.first && VD->getType()->isRecordType()) {
8339 SmallString<128> Name;
8340 llvm::raw_svector_ostream OS(Name);
8341 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8342 /*Qualified=*/true);
8343 SemaRef.Diag(E->getExprLoc(),
8344 diag::err_omp_wrong_dependency_iterator_type)
8345 << OS.str();
8346 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8347 return false;
8348 }
8349 if (Data.first && !SupportsNonRectangular) {
8350 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8351 return false;
8352 }
8353 if (Data.first &&
8354 (DepDecl || (PrevDepDecl &&
8355 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8356 if (!DepDecl && PrevDepDecl)
8357 DepDecl = PrevDepDecl;
8358 SmallString<128> Name;
8359 llvm::raw_svector_ostream OS(Name);
8360 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8361 /*Qualified=*/true);
8362 SemaRef.Diag(E->getExprLoc(),
8363 diag::err_omp_invariant_or_linear_dependency)
8364 << OS.str();
8365 return false;
8366 }
8367 if (Data.first) {
8368 DepDecl = VD;
8369 BaseLoopId = Data.first;
8370 }
8371 return Data.first;
8372 }
8373
8374public:
8375 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8376 const ValueDecl *VD = E->getDecl();
8377 if (isa<VarDecl>(VD))
8378 return checkDecl(E, VD);
8379 return false;
8380 }
8381 bool VisitMemberExpr(const MemberExpr *E) {
8382 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8383 const ValueDecl *VD = E->getMemberDecl();
8384 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8385 return checkDecl(E, VD);
8386 }
8387 return false;
8388 }
8389 bool VisitStmt(const Stmt *S) {
8390 bool Res = false;
8391 for (const Stmt *Child : S->children())
8392 Res = (Child && Visit(Child)) || Res;
8393 return Res;
8394 }
8395 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8396 const ValueDecl *CurLCDecl, bool IsInitializer,
8397 const ValueDecl *PrevDepDecl = nullptr,
8398 bool SupportsNonRectangular = true)
8399 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8400 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8401 SupportsNonRectangular(SupportsNonRectangular) {}
8402 unsigned getBaseLoopId() const {
8403 assert(CurLCDecl && "Expected loop dependency.");
8404 return BaseLoopId;
8405 }
8406 const ValueDecl *getDepDecl() const {
8407 assert(CurLCDecl && "Expected loop dependency.");
8408 return DepDecl;
8409 }
8410};
8411} // namespace
8412
8413std::optional<unsigned>
8414OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8415 bool IsInitializer) {
8416 // Check for the non-rectangular loops.
8417 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8418 DepDecl, SupportsNonRectangular);
8419 if (LoopStmtChecker.Visit(S)) {
8420 DepDecl = LoopStmtChecker.getDepDecl();
8421 return LoopStmtChecker.getBaseLoopId();
8422 }
8423 return std::nullopt;
8424}
8425
8426bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8427 // Check init-expr for canonical loop form and save loop counter
8428 // variable - #Var and its initialization value - #LB.
8429 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8430 // var = lb
8431 // integer-type var = lb
8432 // random-access-iterator-type var = lb
8433 // pointer-type var = lb
8434 //
8435 if (!S) {
8436 if (EmitDiags) {
8437 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8438 }
8439 return true;
8440 }
8441 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8442 if (!ExprTemp->cleanupsHaveSideEffects())
8443 S = ExprTemp->getSubExpr();
8444
8445 InitSrcRange = S->getSourceRange();
8446 if (Expr *E = dyn_cast<Expr>(S))
8447 S = E->IgnoreParens();
8448 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8449 if (BO->getOpcode() == BO_Assign) {
8450 Expr *LHS = BO->getLHS()->IgnoreParens();
8451 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8452 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8453 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8454 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8455 EmitDiags);
8456 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8457 }
8458 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8459 if (ME->isArrow() &&
8460 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8461 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8462 EmitDiags);
8463 }
8464 }
8465 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8466 if (DS->isSingleDecl()) {
8467 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8468 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8469 // Accept non-canonical init form here but emit ext. warning.
8470 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8471 SemaRef.Diag(S->getBeginLoc(),
8472 diag::ext_omp_loop_not_canonical_init)
8473 << S->getSourceRange();
8474 return setLCDeclAndLB(
8475 Var,
8476 buildDeclRefExpr(SemaRef, Var,
8477 Var->getType().getNonReferenceType(),
8478 DS->getBeginLoc()),
8479 Var->getInit(), EmitDiags);
8480 }
8481 }
8482 }
8483 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8484 if (CE->getOperator() == OO_Equal) {
8485 Expr *LHS = CE->getArg(0);
8486 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8487 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8488 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8489 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8490 EmitDiags);
8491 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8492 }
8493 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8494 if (ME->isArrow() &&
8495 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8496 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8497 EmitDiags);
8498 }
8499 }
8500 }
8501
8502 if (dependent() || SemaRef.CurContext->isDependentContext())
8503 return false;
8504 if (EmitDiags) {
8505 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8506 << S->getSourceRange();
8507 }
8508 return true;
8509}
8510
8511/// Ignore parenthesizes, implicit casts, copy constructor and return the
8512/// variable (which may be the loop variable) if possible.
8513static const ValueDecl *getInitLCDecl(const Expr *E) {
8514 if (!E)
8515 return nullptr;
8516 E = getExprAsWritten(E);
8517 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8518 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8519 if ((Ctor->isCopyOrMoveConstructor() ||
8520 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8521 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8522 E = CE->getArg(0)->IgnoreParenImpCasts();
8523 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8524 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8525 return getCanonicalDecl(VD);
8526 }
8527 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8528 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8529 return getCanonicalDecl(ME->getMemberDecl());
8530 return nullptr;
8531}
8532
8533bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8534 // Check test-expr for canonical form, save upper-bound UB, flags for
8535 // less/greater and for strict/non-strict comparison.
8536 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8537 // var relational-op b
8538 // b relational-op var
8539 //
8540 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8541 if (!S) {
8542 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8543 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8544 return true;
8545 }
8546 Condition = S;
8547 S = getExprAsWritten(S);
8548 SourceLocation CondLoc = S->getBeginLoc();
8549 auto &&CheckAndSetCond =
8550 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8551 const Expr *RHS, SourceRange SR,
8552 SourceLocation OpLoc) -> std::optional<bool> {
8553 if (BinaryOperator::isRelationalOp(Opcode)) {
8554 if (getInitLCDecl(LHS) == LCDecl)
8555 return setUB(const_cast<Expr *>(RHS),
8556 (Opcode == BO_LT || Opcode == BO_LE),
8557 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8558 if (getInitLCDecl(RHS) == LCDecl)
8559 return setUB(const_cast<Expr *>(LHS),
8560 (Opcode == BO_GT || Opcode == BO_GE),
8561 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8562 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8563 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8564 /*LessOp=*/std::nullopt,
8565 /*StrictOp=*/true, SR, OpLoc);
8566 }
8567 return std::nullopt;
8568 };
8569 std::optional<bool> Res;
8570 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8571 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8572 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8573 RBO->getOperatorLoc());
8574 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8575 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8576 BO->getSourceRange(), BO->getOperatorLoc());
8577 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8578 if (CE->getNumArgs() == 2) {
8579 Res = CheckAndSetCond(
8580 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8581 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8582 }
8583 }
8584 if (Res)
8585 return *Res;
8586 if (dependent() || SemaRef.CurContext->isDependentContext())
8587 return false;
8588 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8589 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8590 return true;
8591}
8592
8593bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8594 // RHS of canonical loop form increment can be:
8595 // var + incr
8596 // incr + var
8597 // var - incr
8598 //
8599 RHS = RHS->IgnoreParenImpCasts();
8600 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8601 if (BO->isAdditiveOp()) {
8602 bool IsAdd = BO->getOpcode() == BO_Add;
8603 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8604 return setStep(BO->getRHS(), !IsAdd);
8605 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8606 return setStep(BO->getLHS(), /*Subtract=*/false);
8607 }
8608 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8609 bool IsAdd = CE->getOperator() == OO_Plus;
8610 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8611 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8612 return setStep(CE->getArg(1), !IsAdd);
8613 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8614 return setStep(CE->getArg(0), /*Subtract=*/false);
8615 }
8616 }
8617 if (dependent() || SemaRef.CurContext->isDependentContext())
8618 return false;
8619 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8620 << RHS->getSourceRange() << LCDecl;
8621 return true;
8622}
8623
8624bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8625 // Check incr-expr for canonical loop form and return true if it
8626 // does not conform.
8627 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8628 // ++var
8629 // var++
8630 // --var
8631 // var--
8632 // var += incr
8633 // var -= incr
8634 // var = var + incr
8635 // var = incr + var
8636 // var = var - incr
8637 //
8638 if (!S) {
8639 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8640 return true;
8641 }
8642 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8643 if (!ExprTemp->cleanupsHaveSideEffects())
8644 S = ExprTemp->getSubExpr();
8645
8646 IncrementSrcRange = S->getSourceRange();
8647 S = S->IgnoreParens();
8648 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8649 if (UO->isIncrementDecrementOp() &&
8650 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8651 return setStep(SemaRef
8652 .ActOnIntegerConstant(UO->getBeginLoc(),
8653 (UO->isDecrementOp() ? -1 : 1))
8654 .get(),
8655 /*Subtract=*/false);
8656 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8657 switch (BO->getOpcode()) {
8658 case BO_AddAssign:
8659 case BO_SubAssign:
8660 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8661 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8662 break;
8663 case BO_Assign:
8664 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8665 return checkAndSetIncRHS(BO->getRHS());
8666 break;
8667 default:
8668 break;
8669 }
8670 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8671 switch (CE->getOperator()) {
8672 case OO_PlusPlus:
8673 case OO_MinusMinus:
8674 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8675 return setStep(SemaRef
8676 .ActOnIntegerConstant(
8677 CE->getBeginLoc(),
8678 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8679 .get(),
8680 /*Subtract=*/false);
8681 break;
8682 case OO_PlusEqual:
8683 case OO_MinusEqual:
8684 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8685 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8686 break;
8687 case OO_Equal:
8688 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8689 return checkAndSetIncRHS(CE->getArg(1));
8690 break;
8691 default:
8692 break;
8693 }
8694 }
8695 if (dependent() || SemaRef.CurContext->isDependentContext())
8696 return false;
8697 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8698 << S->getSourceRange() << LCDecl;
8699 return true;
8700}
8701
8702static ExprResult
8703tryBuildCapture(Sema &SemaRef, Expr *Capture,
8704 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8705 StringRef Name = ".capture_expr.") {
8706 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8707 return Capture;
8708 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8709 return SemaRef.PerformImplicitConversion(
8710 Capture->IgnoreImpCasts(), Capture->getType(), Sema::AA_Converting,
8711 /*AllowExplicit=*/true);
8712 auto I = Captures.find(Capture);
8713 if (I != Captures.end())
8714 return buildCapture(SemaRef, Capture, I->second, Name);
8715 DeclRefExpr *Ref = nullptr;
8716 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8717 Captures[Capture] = Ref;
8718 return Res;
8719}
8720
8721/// Calculate number of iterations, transforming to unsigned, if number of
8722/// iterations may be larger than the original type.
8723static Expr *
8724calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8725 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8726 bool TestIsStrictOp, bool RoundToStep,
8727 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8728 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8729 if (!NewStep.isUsable())
8730 return nullptr;
8731 llvm::APSInt LRes, SRes;
8732 bool IsLowerConst = false, IsStepConst = false;
8733 if (std::optional<llvm::APSInt> Res =
8734 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8735 LRes = *Res;
8736 IsLowerConst = true;
8737 }
8738 if (std::optional<llvm::APSInt> Res =
8739 Step->getIntegerConstantExpr(SemaRef.Context)) {
8740 SRes = *Res;
8741 IsStepConst = true;
8742 }
8743 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8744 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8745 (TestIsStrictOp && LRes.isStrictlyPositive()));
8746 bool NeedToReorganize = false;
8747 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8748 if (!NoNeedToConvert && IsLowerConst &&
8749 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8750 NoNeedToConvert = true;
8751 if (RoundToStep) {
8752 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8753 ? LRes.getBitWidth()
8754 : SRes.getBitWidth();
8755 LRes = LRes.extend(BW + 1);
8756 LRes.setIsSigned(true);
8757 SRes = SRes.extend(BW + 1);
8758 SRes.setIsSigned(true);
8759 LRes -= SRes;
8760 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8761 LRes = LRes.trunc(BW);
8762 }
8763 if (TestIsStrictOp) {
8764 unsigned BW = LRes.getBitWidth();
8765 LRes = LRes.extend(BW + 1);
8766 LRes.setIsSigned(true);
8767 ++LRes;
8768 NoNeedToConvert =
8769 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8770 // truncate to the original bitwidth.
8771 LRes = LRes.trunc(BW);
8772 }
8773 NeedToReorganize = NoNeedToConvert;
8774 }
8775 llvm::APSInt URes;
8776 bool IsUpperConst = false;
8777 if (std::optional<llvm::APSInt> Res =
8778 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8779 URes = *Res;
8780 IsUpperConst = true;
8781 }
8782 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8783 (!RoundToStep || IsStepConst)) {
8784 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8785 : URes.getBitWidth();
8786 LRes = LRes.extend(BW + 1);
8787 LRes.setIsSigned(true);
8788 URes = URes.extend(BW + 1);
8789 URes.setIsSigned(true);
8790 URes -= LRes;
8791 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8792 NeedToReorganize = NoNeedToConvert;
8793 }
8794 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8795 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8796 // unsigned.
8797 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8798 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8799 QualType LowerTy = Lower->getType();
8800 QualType UpperTy = Upper->getType();
8801 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8802 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8803 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8804 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8806 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8807 Upper =
8808 SemaRef
8810 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8812 .get();
8813 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8814 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8815 }
8816 }
8817 if (!Lower || !Upper || NewStep.isInvalid())
8818 return nullptr;
8819
8820 ExprResult Diff;
8821 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8822 // 1]).
8823 if (NeedToReorganize) {
8824 Diff = Lower;
8825
8826 if (RoundToStep) {
8827 // Lower - Step
8828 Diff =
8829 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8830 if (!Diff.isUsable())
8831 return nullptr;
8832 }
8833
8834 // Lower - Step [+ 1]
8835 if (TestIsStrictOp)
8836 Diff = SemaRef.BuildBinOp(
8837 S, DefaultLoc, BO_Add, Diff.get(),
8838 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8839 if (!Diff.isUsable())
8840 return nullptr;
8841
8842 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8843 if (!Diff.isUsable())
8844 return nullptr;
8845
8846 // Upper - (Lower - Step [+ 1]).
8847 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8848 if (!Diff.isUsable())
8849 return nullptr;
8850 } else {
8851 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8852
8853 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8854 // BuildBinOp already emitted error, this one is to point user to upper
8855 // and lower bound, and to tell what is passed to 'operator-'.
8856 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8857 << Upper->getSourceRange() << Lower->getSourceRange();
8858 return nullptr;
8859 }
8860
8861 if (!Diff.isUsable())
8862 return nullptr;
8863
8864 // Upper - Lower [- 1]
8865 if (TestIsStrictOp)
8866 Diff = SemaRef.BuildBinOp(
8867 S, DefaultLoc, BO_Sub, Diff.get(),
8868 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8869 if (!Diff.isUsable())
8870 return nullptr;
8871
8872 if (RoundToStep) {
8873 // Upper - Lower [- 1] + Step
8874 Diff =
8875 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8876 if (!Diff.isUsable())
8877 return nullptr;
8878 }
8879 }
8880
8881 // Parentheses (for dumping/debugging purposes only).
8882 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8883 if (!Diff.isUsable())
8884 return nullptr;
8885
8886 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8887 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8888 if (!Diff.isUsable())
8889 return nullptr;
8890
8891 return Diff.get();
8892}
8893
8894/// Build the expression to calculate the number of iterations.
8895Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8896 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8897 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8898 QualType VarType = LCDecl->getType().getNonReferenceType();
8899 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8900 !SemaRef.getLangOpts().CPlusPlus)
8901 return nullptr;
8902 Expr *LBVal = LB;
8903 Expr *UBVal = UB;
8904 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8905 // max(LB(MinVal), LB(MaxVal)))
8906 if (InitDependOnLC) {
8907 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8908 if (!IS.MinValue || !IS.MaxValue)
8909 return nullptr;
8910 // OuterVar = Min
8911 ExprResult MinValue =
8912 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8913 if (!MinValue.isUsable())
8914 return nullptr;
8915
8916 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8917 IS.CounterVar, MinValue.get());
8918 if (!LBMinVal.isUsable())
8919 return nullptr;
8920 // OuterVar = Min, LBVal
8921 LBMinVal =
8922 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8923 if (!LBMinVal.isUsable())
8924 return nullptr;
8925 // (OuterVar = Min, LBVal)
8926 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8927 if (!LBMinVal.isUsable())
8928 return nullptr;
8929
8930 // OuterVar = Max
8931 ExprResult MaxValue =
8932 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8933 if (!MaxValue.isUsable())
8934 return nullptr;
8935
8936 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8937 IS.CounterVar, MaxValue.get());
8938 if (!LBMaxVal.isUsable())
8939 return nullptr;
8940 // OuterVar = Max, LBVal
8941 LBMaxVal =
8942 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8943 if (!LBMaxVal.isUsable())
8944 return nullptr;
8945 // (OuterVar = Max, LBVal)
8946 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8947 if (!LBMaxVal.isUsable())
8948 return nullptr;
8949
8950 Expr *LBMin =
8951 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
8952 Expr *LBMax =
8953 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
8954 if (!LBMin || !LBMax)
8955 return nullptr;
8956 // LB(MinVal) < LB(MaxVal)
8957 ExprResult MinLessMaxRes =
8958 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8959 if (!MinLessMaxRes.isUsable())
8960 return nullptr;
8961 Expr *MinLessMax =
8962 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
8963 .get();
8964 if (!MinLessMax)
8965 return nullptr;
8966 if (*TestIsLessOp) {
8967 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8968 // LB(MaxVal))
8969 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8970 MinLessMax, LBMin, LBMax);
8971 if (!MinLB.isUsable())
8972 return nullptr;
8973 LBVal = MinLB.get();
8974 } else {
8975 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8976 // LB(MaxVal))
8977 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8978 MinLessMax, LBMax, LBMin);
8979 if (!MaxLB.isUsable())
8980 return nullptr;
8981 LBVal = MaxLB.get();
8982 }
8983 // OuterVar = LB
8984 LBMinVal =
8985 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8986 if (!LBMinVal.isUsable())
8987 return nullptr;
8988 LBVal = LBMinVal.get();
8989 }
8990 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8991 // min(UB(MinVal), UB(MaxVal))
8992 if (CondDependOnLC) {
8993 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8994 if (!IS.MinValue || !IS.MaxValue)
8995 return nullptr;
8996 // OuterVar = Min
8997 ExprResult MinValue =
8998 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8999 if (!MinValue.isUsable())
9000 return nullptr;
9001
9002 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
9003 IS.CounterVar, MinValue.get());
9004 if (!UBMinVal.isUsable())
9005 return nullptr;
9006 // OuterVar = Min, UBVal
9007 UBMinVal =
9008 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
9009 if (!UBMinVal.isUsable())
9010 return nullptr;
9011 // (OuterVar = Min, UBVal)
9012 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
9013 if (!UBMinVal.isUsable())
9014 return nullptr;
9015
9016 // OuterVar = Max
9017 ExprResult MaxValue =
9018 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
9019 if (!MaxValue.isUsable())
9020 return nullptr;
9021
9022 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
9023 IS.CounterVar, MaxValue.get());
9024 if (!UBMaxVal.isUsable())
9025 return nullptr;
9026 // OuterVar = Max, UBVal
9027 UBMaxVal =
9028 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
9029 if (!UBMaxVal.isUsable())
9030 return nullptr;
9031 // (OuterVar = Max, UBVal)
9032 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
9033 if (!UBMaxVal.isUsable())
9034 return nullptr;
9035
9036 Expr *UBMin =
9037 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
9038 Expr *UBMax =
9039 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
9040 if (!UBMin || !UBMax)
9041 return nullptr;
9042 // UB(MinVal) > UB(MaxVal)
9043 ExprResult MinGreaterMaxRes =
9044 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
9045 if (!MinGreaterMaxRes.isUsable())
9046 return nullptr;
9047 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
9048 Captures, ".min_greater_max")
9049 .get();
9050 if (!MinGreaterMax)
9051 return nullptr;
9052 if (*TestIsLessOp) {
9053 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
9054 // UB(MaxVal))
9055 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
9056 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
9057 if (!MaxUB.isUsable())
9058 return nullptr;
9059 UBVal = MaxUB.get();
9060 } else {
9061 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
9062 // UB(MaxVal))
9063 ExprResult MinUB = SemaRef.ActOnConditionalOp(
9064 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
9065 if (!MinUB.isUsable())
9066 return nullptr;
9067 UBVal = MinUB.get();
9068 }
9069 }
9070 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9071 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9072 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
9073 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
9074 if (!Upper || !Lower)
9075 return nullptr;
9076
9077 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9078 Step, VarType, TestIsStrictOp,
9079 /*RoundToStep=*/true, Captures);
9080 if (!Diff.isUsable())
9081 return nullptr;
9082
9083 // OpenMP runtime requires 32-bit or 64-bit loop variables.
9084 QualType Type = Diff.get()->getType();
9085 ASTContext &C = SemaRef.Context;
9086 bool UseVarType = VarType->hasIntegerRepresentation() &&
9087 C.getTypeSize(Type) > C.getTypeSize(VarType);
9088 if (!Type->isIntegerType() || UseVarType) {
9089 unsigned NewSize =
9090 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
9091 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
9093 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
9094 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
9095 Diff = SemaRef.PerformImplicitConversion(
9096 Diff.get(), Type, Sema::AA_Converting, /*AllowExplicit=*/true);
9097 if (!Diff.isUsable())
9098 return nullptr;
9099 }
9100 }
9101 if (LimitedType) {
9102 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
9103 if (NewSize != C.getTypeSize(Type)) {
9104 if (NewSize < C.getTypeSize(Type)) {
9105 assert(NewSize == 64 && "incorrect loop var size");
9106 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
9107 << InitSrcRange << ConditionSrcRange;
9108 }
9109 QualType NewType = C.getIntTypeForBitwidth(
9111 C.getTypeSize(Type) < NewSize);
9112 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
9113 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
9114 Sema::AA_Converting, true);
9115 if (!Diff.isUsable())
9116 return nullptr;
9117 }
9118 }
9119 }
9120
9121 return Diff.get();
9122}
9123
9124std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9125 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9126 // Do not build for iterators, they cannot be used in non-rectangular loop
9127 // nests.
9128 if (LCDecl->getType()->isRecordType())
9129 return std::make_pair(nullptr, nullptr);
9130 // If we subtract, the min is in the condition, otherwise the min is in the
9131 // init value.
9132 Expr *MinExpr = nullptr;
9133 Expr *MaxExpr = nullptr;
9134 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9135 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9136 bool LBNonRect =
9137 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9138 bool UBNonRect =
9139 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9140 Expr *Lower =
9141 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
9142 Expr *Upper =
9143 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
9144 if (!Upper || !Lower)
9145 return std::make_pair(nullptr, nullptr);
9146
9147 if (*TestIsLessOp)
9148 MinExpr = Lower;
9149 else
9150 MaxExpr = Upper;
9151
9152 // Build minimum/maximum value based on number of iterations.
9153 QualType VarType = LCDecl->getType().getNonReferenceType();
9154
9155 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9156 Step, VarType, TestIsStrictOp,
9157 /*RoundToStep=*/false, Captures);
9158 if (!Diff.isUsable())
9159 return std::make_pair(nullptr, nullptr);
9160
9161 // ((Upper - Lower [- 1]) / Step) * Step
9162 // Parentheses (for dumping/debugging purposes only).
9163 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9164 if (!Diff.isUsable())
9165 return std::make_pair(nullptr, nullptr);
9166
9167 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
9168 if (!NewStep.isUsable())
9169 return std::make_pair(nullptr, nullptr);
9170 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
9171 if (!Diff.isUsable())
9172 return std::make_pair(nullptr, nullptr);
9173
9174 // Parentheses (for dumping/debugging purposes only).
9175 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9176 if (!Diff.isUsable())
9177 return std::make_pair(nullptr, nullptr);
9178
9179 // Convert to the ptrdiff_t, if original type is pointer.
9180 if (VarType->isAnyPointerType() &&
9181 !SemaRef.Context.hasSameType(
9182 Diff.get()->getType(),
9184 Diff = SemaRef.PerformImplicitConversion(
9185 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
9186 Sema::AA_Converting, /*AllowExplicit=*/true);
9187 }
9188 if (!Diff.isUsable())
9189 return std::make_pair(nullptr, nullptr);
9190
9191 if (*TestIsLessOp) {
9192 // MinExpr = Lower;
9193 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
9194 Diff = SemaRef.BuildBinOp(
9195 S, DefaultLoc, BO_Add,
9196 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
9197 Diff.get());
9198 if (!Diff.isUsable())
9199 return std::make_pair(nullptr, nullptr);
9200 } else {
9201 // MaxExpr = Upper;
9202 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
9203 Diff = SemaRef.BuildBinOp(
9204 S, DefaultLoc, BO_Sub,
9205 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
9206 Diff.get());
9207 if (!Diff.isUsable())
9208 return std::make_pair(nullptr, nullptr);
9209 }
9210
9211 // Convert to the original type.
9212 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
9213 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
9215 /*AllowExplicit=*/true);
9216 if (!Diff.isUsable())
9217 return std::make_pair(nullptr, nullptr);
9218
9219 Sema::TentativeAnalysisScope Trap(SemaRef);
9220 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
9221 if (!Diff.isUsable())
9222 return std::make_pair(nullptr, nullptr);
9223
9224 if (*TestIsLessOp)
9225 MaxExpr = Diff.get();
9226 else
9227 MinExpr = Diff.get();
9228
9229 return std::make_pair(MinExpr, MaxExpr);
9230}
9231
9232Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
9233 if (InitDependOnLC || CondDependOnLC)
9234 return Condition;
9235 return nullptr;
9236}
9237
9238Expr *OpenMPIterationSpaceChecker::buildPreCond(
9239 Scope *S, Expr *Cond,
9240 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9241 // Do not build a precondition when the condition/initialization is dependent
9242 // to prevent pessimistic early loop exit.
9243 // TODO: this can be improved by calculating min/max values but not sure that
9244 // it will be very effective.
9245 if (CondDependOnLC || InitDependOnLC)
9246 return SemaRef
9248 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
9249 SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
9250 /*AllowExplicit=*/true)
9251 .get();
9252
9253 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
9254 Sema::TentativeAnalysisScope Trap(SemaRef);
9255
9256 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9257 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9258 if (!NewLB.isUsable() || !NewUB.isUsable())
9259 return nullptr;
9260
9261 ExprResult CondExpr =
9262 SemaRef.BuildBinOp(S, DefaultLoc,
9263 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9264 : (TestIsStrictOp ? BO_GT : BO_GE),
9265 NewLB.get(), NewUB.get());
9266 if (CondExpr.isUsable()) {
9267 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
9268 SemaRef.Context.BoolTy))
9269 CondExpr = SemaRef.PerformImplicitConversion(
9270 CondExpr.get(), SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
9271 /*AllowExplicit=*/true);
9272 }
9273
9274 // Otherwise use original loop condition and evaluate it in runtime.
9275 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9276}
9277
9278/// Build reference expression to the counter be used for codegen.
9279DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9280 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9281 DSAStackTy &DSA) const {
9282 auto *VD = dyn_cast<VarDecl>(LCDecl);
9283 if (!VD) {
9284 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(LCDecl);
9286 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
9287 const DSAStackTy::DSAVarData Data =
9288 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
9289 // If the loop control decl is explicitly marked as private, do not mark it
9290 // as captured again.
9291 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
9292 Captures.insert(std::make_pair(LCRef, Ref));
9293 return Ref;
9294 }
9295 return cast<DeclRefExpr>(LCRef);
9296}
9297
9298Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9299 if (LCDecl && !LCDecl->isInvalidDecl()) {
9301 VarDecl *PrivateVar = buildVarDecl(
9302 SemaRef, DefaultLoc, Type, LCDecl->getName(),
9303 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9304 isa<VarDecl>(LCDecl)
9305 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
9306 : nullptr);
9307 if (PrivateVar->isInvalidDecl())
9308 return nullptr;
9309 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
9310 }
9311 return nullptr;
9312}
9313
9314/// Build initialization of the counter to be used for codegen.
9315Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9316
9317/// Build step of the counter be used for codegen.
9318Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9319
9320Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9321 Scope *S, Expr *Counter,
9322 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9323 Expr *Inc, OverloadedOperatorKind OOK) {
9324 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
9325 if (!Cnt)
9326 return nullptr;
9327 if (Inc) {
9328 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9329 "Expected only + or - operations for depend clauses.");
9330 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9331 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
9332 if (!Cnt)
9333 return nullptr;
9334 }
9335 QualType VarType = LCDecl->getType().getNonReferenceType();
9336 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9337 !SemaRef.getLangOpts().CPlusPlus)
9338 return nullptr;
9339 // Upper - Lower
9340 Expr *Upper =
9341 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9342 Expr *Lower =
9343 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9344 if (!Upper || !Lower)
9345 return nullptr;
9346
9347 ExprResult Diff = calculateNumIters(
9348 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9349 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9350 if (!Diff.isUsable())
9351 return nullptr;
9352
9353 return Diff.get();
9354}
9355} // namespace
9356
9358 Stmt *Init) {
9359 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9360 assert(Init && "Expected loop in canonical form.");
9361 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9362 if (AssociatedLoops > 0 &&
9363 isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
9364 DSAStack->loopStart();
9365 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9366 *DSAStack, ForLoc);
9367 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9368 if (ValueDecl *D = ISC.getLoopDecl()) {
9369 auto *VD = dyn_cast<VarDecl>(D);
9370 DeclRefExpr *PrivateRef = nullptr;
9371 if (!VD) {
9373 VD = Private;
9374 } else {
9375 PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(),
9376 /*WithInit=*/false);
9377 VD = cast<VarDecl>(PrivateRef->getDecl());
9378 }
9379 }
9380 DSAStack->addLoopControlVariable(D, VD);
9381 const Decl *LD = DSAStack->getPossiblyLoopCunter();
9382 if (LD != D->getCanonicalDecl()) {
9383 DSAStack->resetPossibleLoopCounter();
9384 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9386 SemaRef, const_cast<VarDecl *>(Var),
9387 Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
9388 /*RefersToCapture=*/true));
9389 }
9390 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9391 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9392 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9393 // associated for-loop of a simd construct with just one associated
9394 // for-loop may be listed in a linear clause with a constant-linear-step
9395 // that is the increment of the associated for-loop. The loop iteration
9396 // variable(s) in the associated for-loop(s) of a for or parallel for
9397 // construct may be listed in a private or lastprivate clause.
9398 DSAStackTy::DSAVarData DVar =
9399 DSAStack->getTopDSA(D, /*FromParent=*/false);
9400 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9401 // is declared in the loop and it is predetermined as a private.
9402 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9403 OpenMPClauseKind PredeterminedCKind =
9405 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9406 : OMPC_private;
9407 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9408 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9409 (getLangOpts().OpenMP <= 45 || (DVar.CKind != OMPC_lastprivate &&
9410 DVar.CKind != OMPC_private))) ||
9411 ((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop ||
9412 DKind == OMPD_master_taskloop || DKind == OMPD_masked_taskloop ||
9413 DKind == OMPD_parallel_master_taskloop ||
9414 DKind == OMPD_parallel_masked_taskloop ||
9416 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9417 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9418 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9419 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9420 << getOpenMPClauseName(DVar.CKind)
9421 << getOpenMPDirectiveName(DKind)
9422 << getOpenMPClauseName(PredeterminedCKind);
9423 if (DVar.RefExpr == nullptr)
9424 DVar.CKind = PredeterminedCKind;
9426 /*IsLoopIterVar=*/true);
9427 } else if (LoopDeclRefExpr) {
9428 // Make the loop iteration variable private (for worksharing
9429 // constructs), linear (for simd directives with the only one
9430 // associated loop) or lastprivate (for simd directives with several
9431 // collapsed or ordered loops).
9432 if (DVar.CKind == OMPC_unknown)
9433 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind,
9434 PrivateRef);
9435 }
9436 }
9437 }
9438 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9439 }
9440}
9441
9442namespace {
9443// Utility for openmp doacross clause kind
9444class OMPDoacrossKind {
9445public:
9446 bool isSource(const OMPDoacrossClause *C) {
9447 return C->getDependenceType() == OMPC_DOACROSS_source ||
9448 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9449 }
9450 bool isSink(const OMPDoacrossClause *C) {
9451 return C->getDependenceType() == OMPC_DOACROSS_sink;
9452 }
9453 bool isSinkIter(const OMPDoacrossClause *C) {
9454 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9455 }
9456};
9457} // namespace
9458/// Called on a for stmt to check and extract its iteration space
9459/// for further processing (such as collapsing).
9461 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9462 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9463 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9464 Expr *OrderedLoopCountExpr,
9465 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9467 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9468 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9469 // OpenMP [2.9.1, Canonical Loop Form]
9470 // for (init-expr; test-expr; incr-expr) structured-block
9471 // for (range-decl: range-expr) structured-block
9472 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9473 S = CanonLoop->getLoopStmt();
9474 auto *For = dyn_cast_or_null<ForStmt>(S);
9475 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9476 // Ranged for is supported only in OpenMP 5.0.
9477 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9478 OpenMPDirectiveKind DK = (SemaRef.getLangOpts().OpenMP < 50 ||
9479 DSA.getMappedDirective() == OMPD_unknown)
9480 ? DKind
9481 : DSA.getMappedDirective();
9482 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9483 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9484 << getOpenMPDirectiveName(DK) << TotalNestedLoopCount
9485 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9486 if (TotalNestedLoopCount > 1) {
9487 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9488 SemaRef.Diag(DSA.getConstructLoc(),
9489 diag::note_omp_collapse_ordered_expr)
9490 << 2 << CollapseLoopCountExpr->getSourceRange()
9491 << OrderedLoopCountExpr->getSourceRange();
9492 else if (CollapseLoopCountExpr)
9493 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9494 diag::note_omp_collapse_ordered_expr)
9495 << 0 << CollapseLoopCountExpr->getSourceRange();
9496 else
9497 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9498 diag::note_omp_collapse_ordered_expr)
9499 << 1 << OrderedLoopCountExpr->getSourceRange();
9500 }
9501 return true;
9502 }
9503 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9504 "No loop body.");
9505 // Postpone analysis in dependent contexts for ranged for loops.
9506 if (CXXFor && SemaRef.CurContext->isDependentContext())
9507 return false;
9508
9509 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9510 For ? For->getForLoc() : CXXFor->getForLoc());
9511
9512 // Check init.
9513 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9514 if (ISC.checkAndSetInit(Init))
9515 return true;
9516
9517 bool HasErrors = false;
9518
9519 // Check loop variable's type.
9520 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9521 // OpenMP [2.6, Canonical Loop Form]
9522 // Var is one of the following:
9523 // A variable of signed or unsigned integer type.
9524 // For C++, a variable of a random access iterator type.
9525 // For C, a variable of a pointer type.
9526 QualType VarType = LCDecl->getType().getNonReferenceType();
9527 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9528 !VarType->isPointerType() &&
9529 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9530 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9531 << SemaRef.getLangOpts().CPlusPlus;
9532 HasErrors = true;
9533 }
9534
9535 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9536 // a Construct
9537 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9538 // parallel for construct is (are) private.
9539 // The loop iteration variable in the associated for-loop of a simd
9540 // construct with just one associated for-loop is linear with a
9541 // constant-linear-step that is the increment of the associated for-loop.
9542 // Exclude loop var from the list of variables with implicitly defined data
9543 // sharing attributes.
9544 VarsWithImplicitDSA.erase(LCDecl);
9545
9546 assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
9547
9548 // Check test-expr.
9549 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9550
9551 // Check incr-expr.
9552 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9553 }
9554
9555 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9556 return HasErrors;
9557
9558 // Build the loop's iteration space representation.
9559 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9560 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9561 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9562 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9568 Captures);
9569 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9570 ISC.buildCounterVar(Captures, DSA);
9571 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9572 ISC.buildPrivateCounterVar();
9573 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9574 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9575 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9576 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9577 ISC.getConditionSrcRange();
9578 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9579 ISC.getIncrementSrcRange();
9580 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9581 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9582 ISC.isStrictTestOp();
9583 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9584 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9585 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9586 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9587 ISC.buildFinalCondition(DSA.getCurScope());
9588 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9589 ISC.doesInitDependOnLC();
9590 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9591 ISC.doesCondDependOnLC();
9592 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9593 ISC.getLoopDependentIdx();
9594
9595 HasErrors |=
9596 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9597 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9598 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9599 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9600 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9601 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9602 if (!HasErrors && DSA.isOrderedRegion()) {
9603 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9604 if (CurrentNestedLoopCount <
9605 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9606 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9607 CurrentNestedLoopCount,
9608 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9609 DSA.getOrderedRegionParam().second->setLoopCounter(
9610 CurrentNestedLoopCount,
9611 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9612 }
9613 }
9614 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9615 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9616 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9617 unsigned NumLoops =
9618 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9619 if (CurrentNestedLoopCount >= NumLoops) {
9620 // Erroneous case - clause has some problems.
9621 continue;
9622 }
9623 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9624 Pair.second.size() <= CurrentNestedLoopCount) {
9625 // Erroneous case - clause has some problems.
9626 DependC->setLoopData(CurrentNestedLoopCount, nullptr);
9627 continue;
9628 }
9629 OMPDoacrossKind ODK;
9630 if (DoacrossC && ODK.isSink(DoacrossC) &&
9631 Pair.second.size() <= CurrentNestedLoopCount) {
9632 // Erroneous case - clause has some problems.
9633 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
9634 continue;
9635 }
9636 Expr *CntValue;
9637 SourceLocation DepLoc =
9638 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9639 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9640 (DoacrossC && ODK.isSource(DoacrossC)))
9641 CntValue = ISC.buildOrderedLoopData(
9642 DSA.getCurScope(),
9643 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9644 DepLoc);
9645 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9646 Expr *Cnt = SemaRef
9648 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9649 .get();
9650 if (!Cnt)
9651 continue;
9652 // build CounterVar - 1
9653 Expr *Inc =
9654 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
9655 .get();
9656 CntValue = ISC.buildOrderedLoopData(
9657 DSA.getCurScope(),
9658 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9659 DepLoc, Inc, clang::OO_Minus);
9660 } else
9661 CntValue = ISC.buildOrderedLoopData(
9662 DSA.getCurScope(),
9663 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9664 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9665 Pair.second[CurrentNestedLoopCount].second);
9666 if (DependC)
9667 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9668 else
9669 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9670 }
9671 }
9672
9673 return HasErrors;
9674}
9675
9676/// Build 'VarRef = Start.
9677static ExprResult
9679 ExprResult Start, bool IsNonRectangularLB,
9680 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9681 // Build 'VarRef = Start.
9682 ExprResult NewStart = IsNonRectangularLB
9683 ? Start.get()
9684 : tryBuildCapture(SemaRef, Start.get(), Captures);
9685 if (!NewStart.isUsable())
9686 return ExprError();
9687 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9688 VarRef.get()->getType())) {
9689 NewStart = SemaRef.PerformImplicitConversion(
9690 NewStart.get(), VarRef.get()->getType(), Sema::AA_Converting,
9691 /*AllowExplicit=*/true);
9692 if (!NewStart.isUsable())
9693 return ExprError();
9694 }
9695
9697 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9698 return Init;
9699}
9700
9701/// Build 'VarRef = Start + Iter * Step'.
9703 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9704 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9705 bool IsNonRectangularLB,
9706 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9707 // Add parentheses (for debugging purposes only).
9708 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9709 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9710 !Step.isUsable())
9711 return ExprError();
9712
9713 ExprResult NewStep = Step;
9714 if (Captures)
9715 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9716 if (NewStep.isInvalid())
9717 return ExprError();
9719 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9720 if (!Update.isUsable())
9721 return ExprError();
9722
9723 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9724 // 'VarRef = Start (+|-) Iter * Step'.
9725 if (!Start.isUsable())
9726 return ExprError();
9727 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9728 if (!NewStart.isUsable())
9729 return ExprError();
9730 if (Captures && !IsNonRectangularLB)
9731 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9732 if (NewStart.isInvalid())
9733 return ExprError();
9734
9735 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9736 ExprResult SavedUpdate = Update;
9737 ExprResult UpdateVal;
9738 if (VarRef.get()->getType()->isOverloadableType() ||
9739 NewStart.get()->getType()->isOverloadableType() ||
9740 Update.get()->getType()->isOverloadableType()) {
9741 Sema::TentativeAnalysisScope Trap(SemaRef);
9742
9743 Update =
9744 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9745 if (Update.isUsable()) {
9746 UpdateVal =
9747 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9748 VarRef.get(), SavedUpdate.get());
9749 if (UpdateVal.isUsable()) {
9750 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9751 UpdateVal.get());
9752 }
9753 }
9754 }
9755
9756 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9757 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9758 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9759 NewStart.get(), SavedUpdate.get());
9760 if (!Update.isUsable())
9761 return ExprError();
9762
9763 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9764 VarRef.get()->getType())) {
9766 Update.get(), VarRef.get()->getType(), Sema::AA_Converting, true);
9767 if (!Update.isUsable())
9768 return ExprError();
9769 }
9770
9771 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9772 }
9773 return Update;
9774}
9775
9776/// Convert integer expression \a E to make it have at least \a Bits
9777/// bits.
9778static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9779 if (E == nullptr)
9780 return ExprError();
9781 ASTContext &C = SemaRef.Context;
9782 QualType OldType = E->getType();
9783 unsigned HasBits = C.getTypeSize(OldType);
9784 if (HasBits >= Bits)
9785 return ExprResult(E);
9786 // OK to convert to signed, because new type has more bits than old.
9787 QualType NewType = C.getIntTypeForBitwidth(Bits, /* Signed */ true);
9788 return SemaRef.PerformImplicitConversion(E, NewType, Sema::AA_Converting,
9789 true);
9790}
9791
9792/// Check if the given expression \a E is a constant integer that fits
9793/// into \a Bits bits.
9794static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9795 if (E == nullptr)
9796 return false;
9797 if (std::optional<llvm::APSInt> Result =
9798 E->getIntegerConstantExpr(SemaRef.Context))
9799 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9800 return false;
9801}
9802
9803/// Build preinits statement for the given declarations.
9805 MutableArrayRef<Decl *> PreInits) {
9806 if (!PreInits.empty()) {
9807 return new (Context) DeclStmt(
9808 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9810 }
9811 return nullptr;
9812}
9813
9814/// Build preinits statement for the given declarations.
9815static Stmt *
9817 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9818 if (!Captures.empty()) {
9819 SmallVector<Decl *, 16> PreInits;
9820 for (const auto &Pair : Captures)
9821 PreInits.push_back(Pair.second->getDecl());
9822 return buildPreInits(Context, PreInits);
9823 }
9824 return nullptr;
9825}
9826
9827/// Build postupdate expression for the given list of postupdates expressions.
9828static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9829 Expr *PostUpdate = nullptr;
9830 if (!PostUpdates.empty()) {
9831 for (Expr *E : PostUpdates) {
9832 Expr *ConvE = S.BuildCStyleCastExpr(
9833 E->getExprLoc(),
9835 E->getExprLoc(), E)
9836 .get();
9837 PostUpdate = PostUpdate
9838 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9839 PostUpdate, ConvE)
9840 .get()
9841 : ConvE;
9842 }
9843 }
9844 return PostUpdate;
9845}
9846
9847/// Called on a for stmt to check itself and nested loops (if any).
9848/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9849/// number of collapsed loops otherwise.
9850static unsigned
9851checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9852 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9853 DSAStackTy &DSA,
9854 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9856 unsigned NestedLoopCount = 1;
9857 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9859
9860 if (CollapseLoopCountExpr) {
9861 // Found 'collapse' clause - calculate collapse number.
9863 if (!CollapseLoopCountExpr->isValueDependent() &&
9864 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9865 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9866 } else {
9867 Built.clear(/*Size=*/1);
9868 return 1;
9869 }
9870 }
9871 unsigned OrderedLoopCount = 1;
9872 if (OrderedLoopCountExpr) {
9873 // Found 'ordered' clause - calculate collapse number.
9874 Expr::EvalResult EVResult;
9875 if (!OrderedLoopCountExpr->isValueDependent() &&
9876 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9877 SemaRef.getASTContext())) {
9878 llvm::APSInt Result = EVResult.Val.getInt();
9879 if (Result.getLimitedValue() < NestedLoopCount) {
9880 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9881 diag::err_omp_wrong_ordered_loop_count)
9882 << OrderedLoopCountExpr->getSourceRange();
9883 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9884 diag::note_collapse_loop_count)
9885 << CollapseLoopCountExpr->getSourceRange();
9886 }
9887 OrderedLoopCount = Result.getLimitedValue();
9888 } else {
9889 Built.clear(/*Size=*/1);
9890 return 1;
9891 }
9892 }
9893 // This is helper routine for loop directives (e.g., 'for', 'simd',
9894 // 'for simd', etc.).
9895 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9896 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9897 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9900 SupportsNonPerfectlyNested, NumLoops,
9901 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9902 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9903 &IterSpaces, &Captures](unsigned Cnt, Stmt *CurStmt) {
9905 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9906 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9907 VarsWithImplicitDSA, IterSpaces, Captures))
9908 return true;
9909 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9910 IterSpaces[Cnt].CounterVar) {
9911 // Handle initialization of captured loop iterator variables.
9912 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9913 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9914 Captures[DRE] = DRE;
9915 }
9916 }
9917 return false;
9918 },
9919 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9920 Stmt *DependentPreInits = Transform->getPreInits();
9921 if (!DependentPreInits)
9922 return;
9923 for (Decl *C : cast<DeclStmt>(DependentPreInits)->getDeclGroup()) {
9924 auto *D = cast<VarDecl>(C);
9925 DeclRefExpr *Ref = buildDeclRefExpr(SemaRef, D, D->getType(),
9926 Transform->getBeginLoc());
9927 Captures[Ref] = Ref;
9928 }
9929 }))
9930 return 0;
9931
9932 Built.clear(/* size */ NestedLoopCount);
9933
9934 if (SemaRef.CurContext->isDependentContext())
9935 return NestedLoopCount;
9936
9937 // An example of what is generated for the following code:
9938 //
9939 // #pragma omp simd collapse(2) ordered(2)
9940 // for (i = 0; i < NI; ++i)
9941 // for (k = 0; k < NK; ++k)
9942 // for (j = J0; j < NJ; j+=2) {
9943 // <loop body>
9944 // }
9945 //
9946 // We generate the code below.
9947 // Note: the loop body may be outlined in CodeGen.
9948 // Note: some counters may be C++ classes, operator- is used to find number of
9949 // iterations and operator+= to calculate counter value.
9950 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9951 // or i64 is currently supported).
9952 //
9953 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9954 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9955 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9956 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9957 // // similar updates for vars in clauses (e.g. 'linear')
9958 // <loop body (using local i and j)>
9959 // }
9960 // i = NI; // assign final values of counters
9961 // j = NJ;
9962 //
9963
9964 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9965 // the iteration counts of the collapsed for loops.
9966 // Precondition tests if there is at least one iteration (all conditions are
9967 // true).
9968 auto PreCond = ExprResult(IterSpaces[0].PreCond);
9969 Expr *N0 = IterSpaces[0].NumIterations;
9970 ExprResult LastIteration32 =
9971 widenIterationCount(/*Bits=*/32,
9972 SemaRef
9973 .PerformImplicitConversion(
9974 N0->IgnoreImpCasts(), N0->getType(),
9975 Sema::AA_Converting, /*AllowExplicit=*/true)
9976 .get(),
9977 SemaRef);
9978 ExprResult LastIteration64 = widenIterationCount(
9979 /*Bits=*/64,
9980 SemaRef
9981 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
9983 /*AllowExplicit=*/true)
9984 .get(),
9985 SemaRef);
9986
9987 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
9988 return NestedLoopCount;
9989
9990 ASTContext &C = SemaRef.Context;
9991 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
9992
9993 Scope *CurScope = DSA.getCurScope();
9994 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9995 if (PreCond.isUsable()) {
9996 PreCond =
9997 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
9998 PreCond.get(), IterSpaces[Cnt].PreCond);
9999 }
10000 Expr *N = IterSpaces[Cnt].NumIterations;
10001 SourceLocation Loc = N->getExprLoc();
10002 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
10003 if (LastIteration32.isUsable())
10004 LastIteration32 = SemaRef.BuildBinOp(
10005 CurScope, Loc, BO_Mul, LastIteration32.get(),
10006 SemaRef
10009 /*AllowExplicit=*/true)
10010 .get());
10011 if (LastIteration64.isUsable())
10012 LastIteration64 = SemaRef.BuildBinOp(
10013 CurScope, Loc, BO_Mul, LastIteration64.get(),
10014 SemaRef
10017 /*AllowExplicit=*/true)
10018 .get());
10019 }
10020
10021 // Choose either the 32-bit or 64-bit version.
10022 ExprResult LastIteration = LastIteration64;
10023 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
10024 (LastIteration32.isUsable() &&
10025 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
10026 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
10027 fitsInto(
10028 /*Bits=*/32,
10029 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
10030 LastIteration64.get(), SemaRef))))
10031 LastIteration = LastIteration32;
10032 QualType VType = LastIteration.get()->getType();
10033 QualType RealVType = VType;
10034 QualType StrideVType = VType;
10035 if (isOpenMPTaskLoopDirective(DKind)) {
10036 VType =
10037 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
10038 StrideVType =
10039 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
10040 }
10041
10042 if (!LastIteration.isUsable())
10043 return 0;
10044
10045 // Save the number of iterations.
10046 ExprResult NumIterations = LastIteration;
10047 {
10048 LastIteration = SemaRef.BuildBinOp(
10049 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
10050 LastIteration.get(),
10051 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
10052 if (!LastIteration.isUsable())
10053 return 0;
10054 }
10055
10056 // Calculate the last iteration number beforehand instead of doing this on
10057 // each iteration. Do not do this if the number of iterations may be kfold-ed.
10058 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
10059 ExprResult CalcLastIteration;
10060 if (!IsConstant) {
10061 ExprResult SaveRef =
10062 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
10063 LastIteration = SaveRef;
10064
10065 // Prepare SaveRef + 1.
10066 NumIterations = SemaRef.BuildBinOp(
10067 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
10068 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
10069 if (!NumIterations.isUsable())
10070 return 0;
10071 }
10072
10073 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
10074
10075 // Build variables passed into runtime, necessary for worksharing directives.
10076 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
10081 // Lower bound variable, initialized with zero.
10082 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
10083 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
10084 SemaRef.AddInitializerToDecl(LBDecl,
10085 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10086 /*DirectInit*/ false);
10087
10088 // Upper bound variable, initialized with last iteration number.
10089 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
10090 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
10091 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
10092 /*DirectInit*/ false);
10093
10094 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
10095 // This will be used to implement clause 'lastprivate'.
10096 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
10097 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
10098 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
10099 SemaRef.AddInitializerToDecl(ILDecl,
10100 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10101 /*DirectInit*/ false);
10102
10103 // Stride variable returned by runtime (we initialize it to 1 by default).
10104 VarDecl *STDecl =
10105 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
10106 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
10107 SemaRef.AddInitializerToDecl(STDecl,
10108 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
10109 /*DirectInit*/ false);
10110
10111 // Build expression: UB = min(UB, LastIteration)
10112 // It is necessary for CodeGen of directives with static scheduling.
10113 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
10114 UB.get(), LastIteration.get());
10115 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10116 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
10117 LastIteration.get(), UB.get());
10118 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
10119 CondOp.get());
10120 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false);
10121
10122 // If we have a combined directive that combines 'distribute', 'for' or
10123 // 'simd' we need to be able to access the bounds of the schedule of the
10124 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
10125 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
10127 // Lower bound variable, initialized with zero.
10128 VarDecl *CombLBDecl =
10129 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
10130 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
10131 SemaRef.AddInitializerToDecl(
10132 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10133 /*DirectInit*/ false);
10134
10135 // Upper bound variable, initialized with last iteration number.
10136 VarDecl *CombUBDecl =
10137 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
10138 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
10139 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
10140 /*DirectInit*/ false);
10141
10142 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
10143 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
10144 ExprResult CombCondOp =
10145 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
10146 LastIteration.get(), CombUB.get());
10147 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
10148 CombCondOp.get());
10149 CombEUB =
10150 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false);
10151
10152 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
10153 // We expect to have at least 2 more parameters than the 'parallel'
10154 // directive does - the lower and upper bounds of the previous schedule.
10155 assert(CD->getNumParams() >= 4 &&
10156 "Unexpected number of parameters in loop combined directive");
10157
10158 // Set the proper type for the bounds given what we learned from the
10159 // enclosed loops.
10160 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
10161 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
10162
10163 // Previous lower and upper bounds are obtained from the region
10164 // parameters.
10165 PrevLB =
10166 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
10167 PrevUB =
10168 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
10169 }
10170 }
10171
10172 // Build the iteration variable and its initialization before loop.
10173 ExprResult IV;
10174 ExprResult Init, CombInit;
10175 {
10176 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
10177 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
10178 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
10183 ? LB.get()
10184 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10185 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
10186 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false);
10187
10189 Expr *CombRHS =
10194 ? CombLB.get()
10195 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10196 CombInit =
10197 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
10198 CombInit =
10199 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false);
10200 }
10201 }
10202
10203 bool UseStrictCompare =
10204 RealVType->hasUnsignedIntegerRepresentation() &&
10205 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
10206 return LIS.IsStrictCompare;
10207 });
10208 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10209 // unsigned IV)) for worksharing loops.
10210 SourceLocation CondLoc = AStmt->getBeginLoc();
10211 Expr *BoundUB = UB.get();
10212 if (UseStrictCompare) {
10213 BoundUB =
10214 SemaRef
10215 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10216 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10217 .get();
10218 BoundUB =
10219 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue*/ false).get();
10220 }
10221 ExprResult Cond =
10226 ? SemaRef.BuildBinOp(CurScope, CondLoc,
10227 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
10228 BoundUB)
10229 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10230 NumIterations.get());
10231 ExprResult CombDistCond;
10233 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10234 NumIterations.get());
10235 }
10236
10237 ExprResult CombCond;
10239 Expr *BoundCombUB = CombUB.get();
10240 if (UseStrictCompare) {
10241 BoundCombUB =
10242 SemaRef
10243 .BuildBinOp(
10244 CurScope, CondLoc, BO_Add, BoundCombUB,
10245 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10246 .get();
10247 BoundCombUB =
10248 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue*/ false)
10249 .get();
10250 }
10251 CombCond =
10252 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10253 IV.get(), BoundCombUB);
10254 }
10255 // Loop increment (IV = IV + 1)
10256 SourceLocation IncLoc = AStmt->getBeginLoc();
10257 ExprResult Inc =
10258 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
10259 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
10260 if (!Inc.isUsable())
10261 return 0;
10262 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
10263 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false);
10264 if (!Inc.isUsable())
10265 return 0;
10266
10267 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10268 // Used for directives with static scheduling.
10269 // In combined construct, add combined version that use CombLB and CombUB
10270 // base variables for the update
10271 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10276 // LB + ST
10277 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
10278 if (!NextLB.isUsable())
10279 return 0;
10280 // LB = LB + ST
10281 NextLB =
10282 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
10283 NextLB =
10284 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false);
10285 if (!NextLB.isUsable())
10286 return 0;
10287 // UB + ST
10288 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
10289 if (!NextUB.isUsable())
10290 return 0;
10291 // UB = UB + ST
10292 NextUB =
10293 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
10294 NextUB =
10295 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false);
10296 if (!NextUB.isUsable())
10297 return 0;
10299 CombNextLB =
10300 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
10301 if (!NextLB.isUsable())
10302 return 0;
10303 // LB = LB + ST
10304 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
10305 CombNextLB.get());
10306 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
10307 /*DiscardedValue*/ false);
10308 if (!CombNextLB.isUsable())
10309 return 0;
10310 // UB + ST
10311 CombNextUB =
10312 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
10313 if (!CombNextUB.isUsable())
10314 return 0;
10315 // UB = UB + ST
10316 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
10317 CombNextUB.get());
10318 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
10319 /*DiscardedValue*/ false);
10320 if (!CombNextUB.isUsable())
10321 return 0;
10322 }
10323 }
10324
10325 // Create increment expression for distribute loop when combined in a same
10326 // directive with for as IV = IV + ST; ensure upper bound expression based
10327 // on PrevUB instead of NumIterations - used to implement 'for' when found
10328 // in combination with 'distribute', like in 'distribute parallel for'
10329 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10330 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10332 DistCond = SemaRef.BuildBinOp(
10333 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10334 assert(DistCond.isUsable() && "distribute cond expr was not built");
10335
10336 DistInc =
10337 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10338 assert(DistInc.isUsable() && "distribute inc expr was not built");
10339 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10340 DistInc.get());
10341 DistInc =
10342 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false);
10343 assert(DistInc.isUsable() && "distribute inc expr was not built");
10344
10345 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10346 // construct
10347 ExprResult NewPrevUB = PrevUB;
10348 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10349 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10350 PrevUB.get()->getType())) {
10351 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10352 DistEUBLoc,
10354 DistEUBLoc, NewPrevUB.get());
10355 if (!NewPrevUB.isUsable())
10356 return 0;
10357 }
10358 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10359 UB.get(), NewPrevUB.get());
10360 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10361 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10362 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10363 CondOp.get());
10364 PrevEUB =
10365 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false);
10366
10367 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10368 // parallel for is in combination with a distribute directive with
10369 // schedule(static, 1)
10370 Expr *BoundPrevUB = PrevUB.get();
10371 if (UseStrictCompare) {
10372 BoundPrevUB =
10373 SemaRef
10374 .BuildBinOp(
10375 CurScope, CondLoc, BO_Add, BoundPrevUB,
10376 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10377 .get();
10378 BoundPrevUB =
10379 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue*/ false)
10380 .get();
10381 }
10382 ParForInDistCond =
10383 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10384 IV.get(), BoundPrevUB);
10385 }
10386
10387 // Build updates and final values of the loop counters.
10388 bool HasErrors = false;
10389 Built.Counters.resize(NestedLoopCount);
10390 Built.Inits.resize(NestedLoopCount);
10391 Built.Updates.resize(NestedLoopCount);
10392 Built.Finals.resize(NestedLoopCount);
10393 Built.DependentCounters.resize(NestedLoopCount);
10394 Built.DependentInits.resize(NestedLoopCount);
10395 Built.FinalsConditions.resize(NestedLoopCount);
10396 {
10397 // We implement the following algorithm for obtaining the
10398 // original loop iteration variable values based on the
10399 // value of the collapsed loop iteration variable IV.
10400 //
10401 // Let n+1 be the number of collapsed loops in the nest.
10402 // Iteration variables (I0, I1, .... In)
10403 // Iteration counts (N0, N1, ... Nn)
10404 //
10405 // Acc = IV;
10406 //
10407 // To compute Ik for loop k, 0 <= k <= n, generate:
10408 // Prod = N(k+1) * N(k+2) * ... * Nn;
10409 // Ik = Acc / Prod;
10410 // Acc -= Ik * Prod;
10411 //
10412 ExprResult Acc = IV;
10413 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10414 LoopIterationSpace &IS = IterSpaces[Cnt];
10415 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10417
10418 // Compute prod
10419 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10420 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10421 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10422 IterSpaces[K].NumIterations);
10423
10424 // Iter = Acc / Prod
10425 // If there is at least one more inner loop to avoid
10426 // multiplication by 1.
10427 if (Cnt + 1 < NestedLoopCount)
10428 Iter =
10429 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10430 else
10431 Iter = Acc;
10432 if (!Iter.isUsable()) {
10433 HasErrors = true;
10434 break;
10435 }
10436
10437 // Update Acc:
10438 // Acc -= Iter * Prod
10439 // Check if there is at least one more inner loop to avoid
10440 // multiplication by 1.
10441 if (Cnt + 1 < NestedLoopCount)
10442 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10443 Prod.get());
10444 else
10445 Prod = Iter;
10446 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10447
10448 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10449 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10450 DeclRefExpr *CounterVar = buildDeclRefExpr(
10451 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10452 /*RefersToCapture=*/true);
10454 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10455 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10456 if (!Init.isUsable()) {
10457 HasErrors = true;
10458 break;
10459 }
10461 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10462 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10463 if (!Update.isUsable()) {
10464 HasErrors = true;
10465 break;
10466 }
10467
10468 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10469 ExprResult Final =
10470 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10471 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10472 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10473 if (!Final.isUsable()) {
10474 HasErrors = true;
10475 break;
10476 }
10477
10478 if (!Update.isUsable() || !Final.isUsable()) {
10479 HasErrors = true;
10480 break;
10481 }
10482 // Save results
10483 Built.Counters[Cnt] = IS.CounterVar;
10484 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10485 Built.Inits[Cnt] = Init.get();
10486 Built.Updates[Cnt] = Update.get();
10487 Built.Finals[Cnt] = Final.get();
10488 Built.DependentCounters[Cnt] = nullptr;
10489 Built.DependentInits[Cnt] = nullptr;
10490 Built.FinalsConditions[Cnt] = nullptr;
10491 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10492 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10493 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10494 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10495 }
10496 }
10497 }
10498
10499 if (HasErrors)
10500 return 0;
10501
10502 // Save results
10503 Built.IterationVarRef = IV.get();
10504 Built.LastIteration = LastIteration.get();
10505 Built.NumIterations = NumIterations.get();
10506 Built.CalcLastIteration = SemaRef
10507 .ActOnFinishFullExpr(CalcLastIteration.get(),
10508 /*DiscardedValue=*/false)
10509 .get();
10510 Built.PreCond = PreCond.get();
10511 Built.PreInits = buildPreInits(C, Captures);
10512 Built.Cond = Cond.get();
10513 Built.Init = Init.get();
10514 Built.Inc = Inc.get();
10515 Built.LB = LB.get();
10516 Built.UB = UB.get();
10517 Built.IL = IL.get();
10518 Built.ST = ST.get();
10519 Built.EUB = EUB.get();
10520 Built.NLB = NextLB.get();
10521 Built.NUB = NextUB.get();
10522 Built.PrevLB = PrevLB.get();
10523 Built.PrevUB = PrevUB.get();
10524 Built.DistInc = DistInc.get();
10525 Built.PrevEUB = PrevEUB.get();
10526 Built.DistCombinedFields.LB = CombLB.get();
10527 Built.DistCombinedFields.UB = CombUB.get();
10528 Built.DistCombinedFields.EUB = CombEUB.get();
10529 Built.DistCombinedFields.Init = CombInit.get();
10530 Built.DistCombinedFields.Cond = CombCond.get();
10531 Built.DistCombinedFields.NLB = CombNextLB.get();
10532 Built.DistCombinedFields.NUB = CombNextUB.get();
10533 Built.DistCombinedFields.DistCond = CombDistCond.get();
10534 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10535
10536 return NestedLoopCount;
10537}
10538
10540 auto CollapseClauses =
10541 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10542 if (CollapseClauses.begin() != CollapseClauses.end())
10543 return (*CollapseClauses.begin())->getNumForLoops();
10544 return nullptr;
10545}
10546
10548 auto OrderedClauses =
10549 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10550 if (OrderedClauses.begin() != OrderedClauses.end())
10551 return (*OrderedClauses.begin())->getNumForLoops();
10552 return nullptr;
10553}
10554
10556 const ArrayRef<OMPClause *> Clauses) {
10557 const OMPSafelenClause *Safelen = nullptr;
10558 const OMPSimdlenClause *Simdlen = nullptr;
10559
10560 for (const OMPClause *Clause : Clauses) {
10561 if (Clause->getClauseKind() == OMPC_safelen)
10562 Safelen = cast<OMPSafelenClause>(Clause);
10563 else if (Clause->getClauseKind() == OMPC_simdlen)
10564 Simdlen = cast<OMPSimdlenClause>(Clause);
10565 if (Safelen && Simdlen)
10566 break;
10567 }
10568
10569 if (Simdlen && Safelen) {
10570 const Expr *SimdlenLength = Simdlen->getSimdlen();
10571 const Expr *SafelenLength = Safelen->getSafelen();
10572 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10573 SimdlenLength->isInstantiationDependent() ||
10574 SimdlenLength->containsUnexpandedParameterPack())
10575 return false;
10576 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10577 SafelenLength->isInstantiationDependent() ||
10578 SafelenLength->containsUnexpandedParameterPack())
10579 return false;
10580 Expr::EvalResult SimdlenResult, SafelenResult;
10581 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10582 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10583 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10584 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10585 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10586 // If both simdlen and safelen clauses are specified, the value of the
10587 // simdlen parameter must be less than or equal to the value of the safelen
10588 // parameter.
10589 if (SimdlenRes > SafelenRes) {
10590 S.Diag(SimdlenLength->getExprLoc(),
10591 diag::err_omp_wrong_simdlen_safelen_values)
10592 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10593 return true;
10594 }
10595 }
10596 return false;
10597}
10598
10601 DSAStackTy *Stack);
10602
10603bool SemaOpenMP::checkLastPrivateForMappedDirectives(
10604 ArrayRef<OMPClause *> Clauses) {
10605
10606 // Check for syntax of lastprivate
10607 // Param of the lastprivate have different meanings in the mapped directives
10608 // e.g. "omp loop" Only loop iteration vars are allowed in lastprivate clause
10609 // "omp for" lastprivate vars must be shared
10610 if (getLangOpts().OpenMP >= 50 &&
10611 DSAStack->getMappedDirective() == OMPD_loop &&
10612 checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack)) {
10613 return false;
10614 }
10615 return true;
10616}
10617
10619 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10620 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10621 if (!AStmt)
10622 return StmtError();
10623
10624 if (!checkLastPrivateForMappedDirectives(Clauses))
10625 return StmtError();
10626
10627 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10629 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10630 // define the nested loops number.
10631 unsigned NestedLoopCount = checkOpenMPLoop(
10632 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10633 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10634 if (NestedLoopCount == 0)
10635 return StmtError();
10636
10637 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10638 "omp simd loop exprs were not built");
10639
10641 // Finalize the clauses that need pre-built expressions for CodeGen.
10642 for (OMPClause *C : Clauses) {
10643 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10644 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10647 return StmtError();
10648 }
10649 }
10650
10652 return StmtError();
10653
10655 auto *SimdDirective = OMPSimdDirective::Create(
10656 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10657 DSAStack->getMappedDirective());
10658 return SimdDirective;
10659}
10660
10662 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10663 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10664 if (!AStmt)
10665 return StmtError();
10666
10667 if (!checkLastPrivateForMappedDirectives(Clauses))
10668 return StmtError();
10669
10670 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10672 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10673 // define the nested loops number.
10674 unsigned NestedLoopCount = checkOpenMPLoop(
10675 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10676 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10677 if (NestedLoopCount == 0)
10678 return StmtError();
10679
10680 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10681 "omp for loop exprs were not built");
10682
10684 // Finalize the clauses that need pre-built expressions for CodeGen.
10685 for (OMPClause *C : Clauses) {
10686 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10687 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10690 return StmtError();
10691 }
10692 }
10693
10694 auto *ForDirective = OMPForDirective::Create(
10695 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10696 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion(),
10697 DSAStack->getMappedDirective());
10698 return ForDirective;
10699}
10700
10702 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10703 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10704 if (!AStmt)
10705 return StmtError();
10706
10707 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10709 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10710 // define the nested loops number.
10711 unsigned NestedLoopCount =
10712 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10713 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
10714 VarsWithImplicitDSA, B);
10715 if (NestedLoopCount == 0)
10716 return StmtError();
10717
10718 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10719 "omp for simd loop exprs were not built");
10720
10722 // Finalize the clauses that need pre-built expressions for CodeGen.
10723 for (OMPClause *C : Clauses) {
10724 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10725 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10728 return StmtError();
10729 }
10730 }
10731
10733 return StmtError();
10734
10736 return OMPForSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
10737 NestedLoopCount, Clauses, AStmt, B);
10738}
10739
10742 Stmt *AStmt, SourceLocation StartLoc,
10743 SourceLocation EndLoc) {
10744 if (!AStmt)
10745 return StmtError();
10746
10747 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10748 auto BaseStmt = AStmt;
10749 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10750 BaseStmt = CS->getCapturedStmt();
10751 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10752 auto S = C->children();
10753 if (S.begin() == S.end())
10754 return StmtError();
10755 // All associated statements must be '#pragma omp section' except for
10756 // the first one.
10757 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10758 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10759 if (SectionStmt)
10760 Diag(SectionStmt->getBeginLoc(),
10761 diag::err_omp_sections_substmt_not_section);
10762 return StmtError();
10763 }
10764 cast<OMPSectionDirective>(SectionStmt)
10765 ->setHasCancel(DSAStack->isCancelRegion());
10766 }
10767 } else {
10768 Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt);
10769 return StmtError();
10770 }
10771
10773
10775 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10776 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10777}
10778
10780 SourceLocation StartLoc,
10781 SourceLocation EndLoc) {
10782 if (!AStmt)
10783 return StmtError();
10784
10786 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10787
10788 return OMPSectionDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt,
10789 DSAStack->isCancelRegion());
10790}
10791
10793 E = E->IgnoreParenCasts()->IgnoreImplicit();
10794 if (auto *CE = dyn_cast<CallExpr>(E))
10795 if (CE->getDirectCallee())
10796 return E;
10797 return nullptr;
10798}
10799
10802 Stmt *AStmt, SourceLocation StartLoc,
10803 SourceLocation EndLoc) {
10804 if (!AStmt)
10805 return StmtError();
10806
10807 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10808
10809 // 5.1 OpenMP
10810 // expression-stmt : an expression statement with one of the following forms:
10811 // expression = target-call ( [expression-list] );
10812 // target-call ( [expression-list] );
10813
10814 SourceLocation TargetCallLoc;
10815
10817 Expr *TargetCall = nullptr;
10818
10819 auto *E = dyn_cast<Expr>(S);
10820 if (!E) {
10821 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10822 return StmtError();
10823 }
10824
10825 E = E->IgnoreParenCasts()->IgnoreImplicit();
10826
10827 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10828 if (BO->getOpcode() == BO_Assign)
10829 TargetCall = getDirectCallExpr(BO->getRHS());
10830 } else {
10831 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10832 if (COCE->getOperator() == OO_Equal)
10833 TargetCall = getDirectCallExpr(COCE->getArg(1));
10834 if (!TargetCall)
10835 TargetCall = getDirectCallExpr(E);
10836 }
10837 if (!TargetCall) {
10838 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10839 return StmtError();
10840 }
10841 TargetCallLoc = TargetCall->getExprLoc();
10842 }
10843
10845
10846 return OMPDispatchDirective::Create(getASTContext(), StartLoc, EndLoc,
10847 Clauses, AStmt, TargetCallLoc);
10848}
10849
10852 DSAStackTy *Stack) {
10853 bool ErrorFound = false;
10854 for (OMPClause *C : Clauses) {
10855 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10856 for (Expr *RefExpr : LPC->varlists()) {
10857 SourceLocation ELoc;
10858 SourceRange ERange;
10859 Expr *SimpleRefExpr = RefExpr;
10860 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10861 if (ValueDecl *D = Res.first) {
10862 auto &&Info = Stack->isLoopControlVariable(D);
10863 if (!Info.first) {
10864 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10865 << getOpenMPDirectiveName(K);
10866 ErrorFound = true;
10867 }
10868 }
10869 }
10870 }
10871 }
10872 return ErrorFound;
10873}
10874
10876 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10877 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10878 if (!AStmt)
10879 return StmtError();
10880
10881 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10882 // A list item may not appear in a lastprivate clause unless it is the
10883 // loop iteration variable of a loop that is associated with the construct.
10884 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack))
10885 return StmtError();
10886
10887 auto *CS = cast<CapturedStmt>(AStmt);
10888 // 1.2.2 OpenMP Language Terminology
10889 // Structured block - An executable statement with a single entry at the
10890 // top and a single exit at the bottom.
10891 // The point of exit cannot be a branch out of the structured block.
10892 // longjmp() and throw() must not violate the entry/exit criteria.
10893 CS->getCapturedDecl()->setNothrow();
10894
10896 // In presence of clause 'collapse', it will define the nested loops number.
10897 unsigned NestedLoopCount = checkOpenMPLoop(
10898 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10899 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10900 if (NestedLoopCount == 0)
10901 return StmtError();
10902
10903 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10904 "omp loop exprs were not built");
10905
10907 return OMPGenericLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
10908 NestedLoopCount, Clauses, AStmt, B);
10909}
10910
10912 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10913 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10914 if (!AStmt)
10915 return StmtError();
10916
10917 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10918 // A list item may not appear in a lastprivate clause unless it is the
10919 // loop iteration variable of a loop that is associated with the construct.
10920 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack))
10921 return StmtError();
10922
10923 auto *CS = cast<CapturedStmt>(AStmt);
10924 // 1.2.2 OpenMP Language Terminology
10925 // Structured block - An executable statement with a single entry at the
10926 // top and a single exit at the bottom.
10927 // The point of exit cannot be a branch out of the structured block.
10928 // longjmp() and throw() must not violate the entry/exit criteria.
10929 CS->getCapturedDecl()->setNothrow();
10930 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_loop);
10931 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10932 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10933 // 1.2.2 OpenMP Language Terminology
10934 // Structured block - An executable statement with a single entry at the
10935 // top and a single exit at the bottom.
10936 // The point of exit cannot be a branch out of the structured block.
10937 // longjmp() and throw() must not violate the entry/exit criteria.
10938 CS->getCapturedDecl()->setNothrow();
10939 }
10940
10942 // In presence of clause 'collapse', it will define the nested loops number.
10943 unsigned NestedLoopCount =
10944 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10945 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10946 VarsWithImplicitDSA, B);
10947 if (NestedLoopCount == 0)
10948 return StmtError();
10949
10950 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10951 "omp loop exprs were not built");
10952
10954 DSAStack->setParentTeamsRegionLoc(StartLoc);
10955
10957 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10958}
10959
10961 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10962 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10963 if (!AStmt)
10964 return StmtError();
10965
10966 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10967 // A list item may not appear in a lastprivate clause unless it is the
10968 // loop iteration variable of a loop that is associated with the construct.
10969 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop,
10970 DSAStack))
10971 return StmtError();
10972
10973 auto *CS = cast<CapturedStmt>(AStmt);
10974 // 1.2.2 OpenMP Language Terminology
10975 // Structured block - An executable statement with a single entry at the
10976 // top and a single exit at the bottom.
10977 // The point of exit cannot be a branch out of the structured block.
10978 // longjmp() and throw() must not violate the entry/exit criteria.
10979 CS->getCapturedDecl()->setNothrow();
10980 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams_loop);
10981 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10982 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10983 // 1.2.2 OpenMP Language Terminology
10984 // Structured block - An executable statement with a single entry at the
10985 // top and a single exit at the bottom.
10986 // The point of exit cannot be a branch out of the structured block.
10987 // longjmp() and throw() must not violate the entry/exit criteria.
10988 CS->getCapturedDecl()->setNothrow();
10989 }
10990
10992 // In presence of clause 'collapse', it will define the nested loops number.
10993 unsigned NestedLoopCount =
10994 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10995 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10996 VarsWithImplicitDSA, B);
10997 if (NestedLoopCount == 0)
10998 return StmtError();
10999
11000 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11001 "omp loop exprs were not built");
11002
11004
11006 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11008}
11009
11011 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11012 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11013 if (!AStmt)
11014 return StmtError();
11015
11016 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11017 // A list item may not appear in a lastprivate clause unless it is the
11018 // loop iteration variable of a loop that is associated with the construct.
11019 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_parallel_loop,
11020 DSAStack))
11021 return StmtError();
11022
11023 auto *CS = cast<CapturedStmt>(AStmt);
11024 // 1.2.2 OpenMP Language Terminology
11025 // Structured block - An executable statement with a single entry at the
11026 // top and a single exit at the bottom.
11027 // The point of exit cannot be a branch out of the structured block.
11028 // longjmp() and throw() must not violate the entry/exit criteria.
11029 CS->getCapturedDecl()->setNothrow();
11030 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_parallel_loop);
11031 ThisCaptureLevel > 1; --ThisCaptureLevel) {
11032 CS = cast<CapturedStmt>(CS->getCapturedStmt());
11033 // 1.2.2 OpenMP Language Terminology
11034 // Structured block - An executable statement with a single entry at the
11035 // top and a single exit at the bottom.
11036 // The point of exit cannot be a branch out of the structured block.
11037 // longjmp() and throw() must not violate the entry/exit criteria.
11038 CS->getCapturedDecl()->setNothrow();
11039 }
11040
11042 // In presence of clause 'collapse', it will define the nested loops number.
11043 unsigned NestedLoopCount =
11044 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
11045 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
11046 VarsWithImplicitDSA, B);
11047 if (NestedLoopCount == 0)
11048 return StmtError();
11049
11050 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11051 "omp loop exprs were not built");
11052
11054
11056 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11057}
11058
11060 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11061 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11062 if (!AStmt)
11063 return StmtError();
11064
11065 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11066 // A list item may not appear in a lastprivate clause unless it is the
11067 // loop iteration variable of a loop that is associated with the construct.
11068 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_parallel_loop,
11069 DSAStack))
11070 return StmtError();
11071
11072 auto *CS = cast<CapturedStmt>(AStmt);
11073 // 1.2.2 OpenMP Language Terminology
11074 // Structured block - An executable statement with a single entry at the
11075 // top and a single exit at the bottom.
11076 // The point of exit cannot be a branch out of the structured block.
11077 // longjmp() and throw() must not violate the entry/exit criteria.
11078 CS->getCapturedDecl()->setNothrow();
11079 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_loop);
11080 ThisCaptureLevel > 1; --ThisCaptureLevel) {
11081 CS = cast<CapturedStmt>(CS->getCapturedStmt());
11082 // 1.2.2 OpenMP Language Terminology
11083 // Structured block - An executable statement with a single entry at the
11084 // top and a single exit at the bottom.
11085 // The point of exit cannot be a branch out of the structured block.
11086 // longjmp() and throw() must not violate the entry/exit criteria.
11087 CS->getCapturedDecl()->setNothrow();
11088 }
11089
11091 // In presence of clause 'collapse', it will define the nested loops number.
11092 unsigned NestedLoopCount =
11093 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
11094 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
11095 VarsWithImplicitDSA, B);
11096 if (NestedLoopCount == 0)
11097 return StmtError();
11098
11099 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11100 "omp loop exprs were not built");
11101
11103
11105 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11106}
11107
11109 Stmt *AStmt,
11110 SourceLocation StartLoc,
11111 SourceLocation EndLoc) {
11112 if (!AStmt)
11113 return StmtError();
11114
11115 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11116
11118
11119 // OpenMP [2.7.3, single Construct, Restrictions]
11120 // The copyprivate clause must not be used with the nowait clause.
11121 const OMPClause *Nowait = nullptr;
11122 const OMPClause *Copyprivate = nullptr;
11123 for (const OMPClause *Clause : Clauses) {
11124 if (Clause->getClauseKind() == OMPC_nowait)
11125 Nowait = Clause;
11126 else if (Clause->getClauseKind() == OMPC_copyprivate)
11127 Copyprivate = Clause;
11128 if (Copyprivate && Nowait) {
11129 Diag(Copyprivate->getBeginLoc(),
11130 diag::err_omp_single_copyprivate_with_nowait);
11131 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
11132 return StmtError();
11133 }
11134 }
11135
11136 return OMPSingleDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11137 AStmt);
11138}
11139
11141 SourceLocation StartLoc,
11142 SourceLocation EndLoc) {
11143 if (!AStmt)
11144 return StmtError();
11145
11147
11148 return OMPMasterDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt);
11149}
11150
11152 Stmt *AStmt,
11153 SourceLocation StartLoc,
11154 SourceLocation EndLoc) {
11155 if (!AStmt)
11156 return StmtError();
11157
11159
11160 return OMPMaskedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11161 AStmt);
11162}
11163
11165 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
11166 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
11167 if (!AStmt)
11168 return StmtError();
11169
11170 bool ErrorFound = false;
11171 llvm::APSInt Hint;
11172 SourceLocation HintLoc;
11173 bool DependentHint = false;
11174 for (const OMPClause *C : Clauses) {
11175 if (C->getClauseKind() == OMPC_hint) {
11176 if (!DirName.getName()) {
11177 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
11178 ErrorFound = true;
11179 }
11180 Expr *E = cast<OMPHintClause>(C)->getHint();
11181 if (E->isTypeDependent() || E->isValueDependent() ||
11183 DependentHint = true;
11184 } else {
11186 HintLoc = C->getBeginLoc();
11187 }
11188 }
11189 }
11190 if (ErrorFound)
11191 return StmtError();
11192 const auto Pair = DSAStack->getCriticalWithHint(DirName);
11193 if (Pair.first && DirName.getName() && !DependentHint) {
11194 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
11195 Diag(StartLoc, diag::err_omp_critical_with_hint);
11196 if (HintLoc.isValid())
11197 Diag(HintLoc, diag::note_omp_critical_hint_here)
11198 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
11199 else
11200 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
11201 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
11202 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
11203 << 1
11204 << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()),
11205 /*Radix=*/10, /*Signed=*/false);
11206 } else {
11207 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
11208 }
11209 }
11210 }
11211
11213
11214 auto *Dir = OMPCriticalDirective::Create(getASTContext(), DirName, StartLoc,
11215 EndLoc, Clauses, AStmt);
11216 if (!Pair.first && DirName.getName() && !DependentHint)
11217 DSAStack->addCriticalWithHint(Dir, Hint);
11218 return Dir;
11219}
11220
11222 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11223 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11224 if (!AStmt)
11225 return StmtError();
11226
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 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11237 // define the nested loops number.
11238 unsigned NestedLoopCount =
11239 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
11240 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
11241 VarsWithImplicitDSA, B);
11242 if (NestedLoopCount == 0)
11243 return StmtError();
11244
11245 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11246 "omp parallel for loop exprs were not built");
11247
11249 // Finalize the clauses that need pre-built expressions for CodeGen.
11250 for (OMPClause *C : Clauses) {
11251 if (auto *LC = dyn_cast<OMPLinearClause>(C))
11252 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
11255 return StmtError();
11256 }
11257 }
11258
11261 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11262 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11263}
11264
11266 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11267 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11268 if (!AStmt)
11269 return StmtError();
11270
11271 auto *CS = cast<CapturedStmt>(AStmt);
11272 // 1.2.2 OpenMP Language Terminology
11273 // Structured block - An executable statement with a single entry at the
11274 // top and a single exit at the bottom.
11275 // The point of exit cannot be a branch out of the structured block.
11276 // longjmp() and throw() must not violate the entry/exit criteria.
11277 CS->getCapturedDecl()->setNothrow();
11278
11280 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11281 // define the nested loops number.
11282 unsigned NestedLoopCount =
11283 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
11284 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
11285 VarsWithImplicitDSA, B);
11286 if (NestedLoopCount == 0)
11287 return StmtError();
11288
11290 // Finalize the clauses that need pre-built expressions for CodeGen.
11291 for (OMPClause *C : Clauses) {
11292 if (auto *LC = dyn_cast<OMPLinearClause>(C))
11293 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
11296 return StmtError();
11297 }
11298 }
11299
11301 return StmtError();
11302
11305 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11306}
11307
11309 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11310 SourceLocation EndLoc) {
11311 if (!AStmt)
11312 return StmtError();
11313
11314 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11315 auto *CS = cast<CapturedStmt>(AStmt);
11316 // 1.2.2 OpenMP Language Terminology
11317 // Structured block - An executable statement with a single entry at the
11318 // top and a single exit at the bottom.
11319 // The point of exit cannot be a branch out of the structured block.
11320 // longjmp() and throw() must not violate the entry/exit criteria.
11321 CS->getCapturedDecl()->setNothrow();
11322
11324
11326 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11327 DSAStack->getTaskgroupReductionRef());
11328}
11329
11331 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11332 SourceLocation EndLoc) {
11333 if (!AStmt)
11334 return StmtError();
11335
11336 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11337 auto *CS = cast<CapturedStmt>(AStmt);
11338 // 1.2.2 OpenMP Language Terminology
11339 // Structured block - An executable statement with a single entry at the
11340 // top and a single exit at the bottom.
11341 // The point of exit cannot be a branch out of the structured block.
11342 // longjmp() and throw() must not violate the entry/exit criteria.
11343 CS->getCapturedDecl()->setNothrow();
11344
11346
11348 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11349 DSAStack->getTaskgroupReductionRef());
11350}
11351
11353 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11354 SourceLocation EndLoc) {
11355 if (!AStmt)
11356 return StmtError();
11357
11358 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11359 auto BaseStmt = AStmt;
11360 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
11361 BaseStmt = CS->getCapturedStmt();
11362 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
11363 auto S = C->children();
11364 if (S.begin() == S.end())
11365 return StmtError();
11366 // All associated statements must be '#pragma omp section' except for
11367 // the first one.
11368 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
11369 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
11370 if (SectionStmt)
11371 Diag(SectionStmt->getBeginLoc(),
11372 diag::err_omp_parallel_sections_substmt_not_section);
11373 return StmtError();
11374 }
11375 cast<OMPSectionDirective>(SectionStmt)
11376 ->setHasCancel(DSAStack->isCancelRegion());
11377 }
11378 } else {
11379 Diag(AStmt->getBeginLoc(),
11380 diag::err_omp_parallel_sections_not_compound_stmt);
11381 return StmtError();
11382 }
11383
11385
11387 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11388 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11389}
11390
11391/// Find and diagnose mutually exclusive clause kinds.
11393 Sema &S, ArrayRef<OMPClause *> Clauses,
11394 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11395 const OMPClause *PrevClause = nullptr;
11396 bool ErrorFound = false;
11397 for (const OMPClause *C : Clauses) {
11398 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
11399 if (!PrevClause) {
11400 PrevClause = C;
11401 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11402 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11403 << getOpenMPClauseName(C->getClauseKind())
11404 << getOpenMPClauseName(PrevClause->getClauseKind());
11405 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
11406 << getOpenMPClauseName(PrevClause->getClauseKind());
11407 ErrorFound = true;
11408 }
11409 }
11410 }
11411 return ErrorFound;
11412}
11413
11415 Stmt *AStmt,
11416 SourceLocation StartLoc,
11417 SourceLocation EndLoc) {
11418 if (!AStmt)
11419 return StmtError();
11420
11421 // OpenMP 5.0, 2.10.1 task Construct
11422 // If a detach clause appears on the directive, then a mergeable clause cannot
11423 // appear on the same directive.
11425 {OMPC_detach, OMPC_mergeable}))
11426 return StmtError();
11427
11428 auto *CS = cast<CapturedStmt>(AStmt);
11429 // 1.2.2 OpenMP Language Terminology
11430 // Structured block - An executable statement with a single entry at the
11431 // top and a single exit at the bottom.
11432 // The point of exit cannot be a branch out of the structured block.
11433 // longjmp() and throw() must not violate the entry/exit criteria.
11434 CS->getCapturedDecl()->setNothrow();
11435
11437
11438 return OMPTaskDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11439 AStmt, DSAStack->isCancelRegion());
11440}
11441
11443 SourceLocation EndLoc) {
11444 return OMPTaskyieldDirective::Create(getASTContext(), StartLoc, EndLoc);
11445}
11446
11448 SourceLocation EndLoc) {
11449 return OMPBarrierDirective::Create(getASTContext(), StartLoc, EndLoc);
11450}
11451
11453 SourceLocation StartLoc,
11454 SourceLocation EndLoc,
11455 bool InExContext) {
11456 const OMPAtClause *AtC =
11457 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11458
11459 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11460 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11461 return StmtError();
11462 }
11463
11464 const OMPSeverityClause *SeverityC =
11465 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11466 const OMPMessageClause *MessageC =
11467 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11468 Expr *ME = MessageC ? MessageC->getMessageString() : nullptr;
11469
11470 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11471 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11472 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11473 << (ME ? cast<StringLiteral>(ME)->getString() : "WARNING");
11474 else
11475 Diag(StartLoc, diag::err_diagnose_if_succeeded)
11476 << (ME ? cast<StringLiteral>(ME)->getString() : "ERROR");
11477 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11478 return StmtError();
11479 }
11480 return OMPErrorDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11481}
11482
11485 SourceLocation StartLoc,
11486 SourceLocation EndLoc) {
11487 const OMPNowaitClause *NowaitC =
11488 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11489 bool HasDependC =
11490 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11491 .empty();
11492 if (NowaitC && !HasDependC) {
11493 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11494 return StmtError();
11495 }
11496
11497 return OMPTaskwaitDirective::Create(getASTContext(), StartLoc, EndLoc,
11498 Clauses);
11499}
11500
11503 Stmt *AStmt, SourceLocation StartLoc,
11504 SourceLocation EndLoc) {
11505 if (!AStmt)
11506 return StmtError();
11507
11508 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11509
11511
11512 return OMPTaskgroupDirective::Create(getASTContext(), StartLoc, EndLoc,
11513 Clauses, AStmt,
11514 DSAStack->getTaskgroupReductionRef());
11515}
11516
11518 SourceLocation StartLoc,
11519 SourceLocation EndLoc) {
11520 OMPFlushClause *FC = nullptr;
11521 OMPClause *OrderClause = nullptr;
11522 for (OMPClause *C : Clauses) {
11523 if (C->getClauseKind() == OMPC_flush)
11524 FC = cast<OMPFlushClause>(C);
11525 else
11526 OrderClause = C;
11527 }
11528 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11529 SourceLocation MemOrderLoc;
11530 for (const OMPClause *C : Clauses) {
11531 if (C->getClauseKind() == OMPC_acq_rel ||
11532 C->getClauseKind() == OMPC_acquire ||
11533 C->getClauseKind() == OMPC_release) {
11534 if (MemOrderKind != OMPC_unknown) {
11535 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11536 << getOpenMPDirectiveName(OMPD_flush) << 1
11537 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11538 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11539 << getOpenMPClauseName(MemOrderKind);
11540 } else {
11541 MemOrderKind = C->getClauseKind();
11542 MemOrderLoc = C->getBeginLoc();
11543 }
11544 }
11545 }
11546 if (FC && OrderClause) {
11547 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11548 << getOpenMPClauseName(OrderClause->getClauseKind());
11549 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11550 << getOpenMPClauseName(OrderClause->getClauseKind());
11551 return StmtError();
11552 }
11553 return OMPFlushDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11554}
11555
11557 SourceLocation StartLoc,
11558 SourceLocation EndLoc) {
11559 if (Clauses.empty()) {
11560 Diag(StartLoc, diag::err_omp_depobj_expected);
11561 return StmtError();
11562 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11563 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11564 return StmtError();
11565 }
11566 // Only depobj expression and another single clause is allowed.
11567 if (Clauses.size() > 2) {
11568 Diag(Clauses[2]->getBeginLoc(),
11569 diag::err_omp_depobj_single_clause_expected);
11570 return StmtError();
11571 } else if (Clauses.size() < 1) {
11572 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11573 return StmtError();
11574 }
11575 return OMPDepobjDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11576}
11577
11579 SourceLocation StartLoc,
11580 SourceLocation EndLoc) {
11581 // Check that exactly one clause is specified.
11582 if (Clauses.size() != 1) {
11583 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11584 diag::err_omp_scan_single_clause_expected);
11585 return StmtError();
11586 }
11587 // Check that scan directive is used in the scopeof the OpenMP loop body.
11588 if (Scope *S = DSAStack->getCurScope()) {
11589 Scope *ParentS = S->getParent();
11590 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11591 !ParentS->getBreakParent()->isOpenMPLoopScope())
11592 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11593 << getOpenMPDirectiveName(OMPD_scan) << 5);
11594 }
11595 // Check that only one instance of scan directives is used in the same outer
11596 // region.
11597 if (DSAStack->doesParentHasScanDirective()) {
11598 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11599 Diag(DSAStack->getParentScanDirectiveLoc(),
11600 diag::note_omp_previous_directive)
11601 << "scan";
11602 return StmtError();
11603 }
11604 DSAStack->setParentHasScanDirective(StartLoc);
11605 return OMPScanDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11606}
11607
11610 Stmt *AStmt, SourceLocation StartLoc,
11611 SourceLocation EndLoc) {
11612 const OMPClause *DependFound = nullptr;
11613 const OMPClause *DependSourceClause = nullptr;
11614 const OMPClause *DependSinkClause = nullptr;
11615 const OMPClause *DoacrossFound = nullptr;
11616 const OMPClause *DoacrossSourceClause = nullptr;
11617 const OMPClause *DoacrossSinkClause = nullptr;
11618 bool ErrorFound = false;
11619 const OMPThreadsClause *TC = nullptr;
11620 const OMPSIMDClause *SC = nullptr;
11621 for (const OMPClause *C : Clauses) {
11622 auto DOC = dyn_cast<OMPDoacrossClause>(C);
11623 auto DC = dyn_cast<OMPDependClause>(C);
11624 if (DC || DOC) {
11625 DependFound = DC ? C : nullptr;
11626 DoacrossFound = DOC ? C : nullptr;
11627 OMPDoacrossKind ODK;
11628 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11629 (DOC && (ODK.isSource(DOC)))) {
11630 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11631 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11632 << getOpenMPDirectiveName(OMPD_ordered)
11633 << getOpenMPClauseName(DC ? OMPC_depend : OMPC_doacross) << 2;
11634 ErrorFound = true;
11635 } else {
11636 if (DC)
11637 DependSourceClause = C;
11638 else
11639 DoacrossSourceClause = C;
11640 }
11641 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11642 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11643 << (DC ? "depend" : "doacross") << 0;
11644 ErrorFound = true;
11645 }
11646 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11647 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11648 if (DependSourceClause || DoacrossSourceClause) {
11649 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11650 << (DC ? "depend" : "doacross") << 1;
11651 ErrorFound = true;
11652 }
11653 if (DC)
11654 DependSinkClause = C;
11655 else
11656 DoacrossSinkClause = C;
11657 }
11658 } else if (C->getClauseKind() == OMPC_threads) {
11659 TC = cast<OMPThreadsClause>(C);
11660 } else if (C->getClauseKind() == OMPC_simd) {
11661 SC = cast<OMPSIMDClause>(C);
11662 }
11663 }
11664 if (!ErrorFound && !SC &&
11665 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11666 // OpenMP [2.8.1,simd Construct, Restrictions]
11667 // An ordered construct with the simd clause is the only OpenMP construct
11668 // that can appear in the simd region.
11669 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11670 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11671 ErrorFound = true;
11672 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11673 SourceLocation Loc =
11674 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11675 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11676 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross)
11677 << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
11678 ErrorFound = true;
11679 } else if ((DependFound || DoacrossFound) &&
11680 !DSAStack->getParentOrderedRegionParam().first) {
11681 SourceLocation Loc =
11682 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11683 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11684 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross);
11685 ErrorFound = true;
11686 } else if (TC || Clauses.empty()) {
11687 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11688 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11689 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11690 << (TC != nullptr);
11691 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11692 ErrorFound = true;
11693 }
11694 }
11695 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11696 return StmtError();
11697
11698 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11699 // During execution of an iteration of a worksharing-loop or a loop nest
11700 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11701 // must not execute more than one ordered region corresponding to an ordered
11702 // construct without a depend clause.
11703 if (!DependFound && !DoacrossFound) {
11704 if (DSAStack->doesParentHasOrderedDirective()) {
11705 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11706 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11707 diag::note_omp_previous_directive)
11708 << "ordered";
11709 return StmtError();
11710 }
11711 DSAStack->setParentHasOrderedDirective(StartLoc);
11712 }
11713
11714 if (AStmt) {
11715 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11716
11718 }
11719
11720 return OMPOrderedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11721 AStmt);
11722}
11723
11724namespace {
11725/// Helper class for checking expression in 'omp atomic [update]'
11726/// construct.
11727class OpenMPAtomicUpdateChecker {
11728 /// Error results for atomic update expressions.
11729 enum ExprAnalysisErrorCode {
11730 /// A statement is not an expression statement.
11731 NotAnExpression,
11732 /// Expression is not builtin binary or unary operation.
11733 NotABinaryOrUnaryExpression,
11734 /// Unary operation is not post-/pre- increment/decrement operation.
11735 NotAnUnaryIncDecExpression,
11736 /// An expression is not of scalar type.
11737 NotAScalarType,
11738 /// A binary operation is not an assignment operation.
11739 NotAnAssignmentOp,
11740 /// RHS part of the binary operation is not a binary expression.
11741 NotABinaryExpression,
11742 /// RHS part is not additive/multiplicative/shift/biwise binary
11743 /// expression.
11744 NotABinaryOperator,
11745 /// RHS binary operation does not have reference to the updated LHS
11746 /// part.
11747 NotAnUpdateExpression,
11748 /// An expression contains semantical error not related to
11749 /// 'omp atomic [update]'
11750 NotAValidExpression,
11751 /// No errors is found.
11752 NoError
11753 };
11754 /// Reference to Sema.
11755 Sema &SemaRef;
11756 /// A location for note diagnostics (when error is found).
11757 SourceLocation NoteLoc;
11758 /// 'x' lvalue part of the source atomic expression.
11759 Expr *X;
11760 /// 'expr' rvalue part of the source atomic expression.
11761 Expr *E;
11762 /// Helper expression of the form
11763 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11764 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11765 Expr *UpdateExpr;
11766 /// Is 'x' a LHS in a RHS part of full update expression. It is
11767 /// important for non-associative operations.
11768 bool IsXLHSInRHSPart;
11770 SourceLocation OpLoc;
11771 /// true if the source expression is a postfix unary operation, false
11772 /// if it is a prefix unary operation.
11773 bool IsPostfixUpdate;
11774
11775public:
11776 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11777 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11778 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11779 /// Check specified statement that it is suitable for 'atomic update'
11780 /// constructs and extract 'x', 'expr' and Operation from the original
11781 /// expression. If DiagId and NoteId == 0, then only check is performed
11782 /// without error notification.
11783 /// \param DiagId Diagnostic which should be emitted if error is found.
11784 /// \param NoteId Diagnostic note for the main error message.
11785 /// \return true if statement is not an update expression, false otherwise.
11786 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11787 /// Return the 'x' lvalue part of the source atomic expression.
11788 Expr *getX() const { return X; }
11789 /// Return the 'expr' rvalue part of the source atomic expression.
11790 Expr *getExpr() const { return E; }
11791 /// Return the update expression used in calculation of the updated
11792 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11793 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11794 Expr *getUpdateExpr() const { return UpdateExpr; }
11795 /// Return true if 'x' is LHS in RHS part of full update expression,
11796 /// false otherwise.
11797 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11798
11799 /// true if the source expression is a postfix unary operation, false
11800 /// if it is a prefix unary operation.
11801 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11802
11803private:
11804 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11805 unsigned NoteId = 0);
11806};
11807
11808bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11809 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11810 ExprAnalysisErrorCode ErrorFound = NoError;
11811 SourceLocation ErrorLoc, NoteLoc;
11812 SourceRange ErrorRange, NoteRange;
11813 // Allowed constructs are:
11814 // x = x binop expr;
11815 // x = expr binop x;
11816 if (AtomicBinOp->getOpcode() == BO_Assign) {
11817 X = AtomicBinOp->getLHS();
11818 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11819 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11820 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11821 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11822 AtomicInnerBinOp->isBitwiseOp()) {
11823 Op = AtomicInnerBinOp->getOpcode();
11824 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11825 Expr *LHS = AtomicInnerBinOp->getLHS();
11826 Expr *RHS = AtomicInnerBinOp->getRHS();
11827 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11828 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11829 /*Canonical=*/true);
11830 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11831 /*Canonical=*/true);
11832 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11833 /*Canonical=*/true);
11834 if (XId == LHSId) {
11835 E = RHS;
11836 IsXLHSInRHSPart = true;
11837 } else if (XId == RHSId) {
11838 E = LHS;
11839 IsXLHSInRHSPart = false;
11840 } else {
11841 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11842 ErrorRange = AtomicInnerBinOp->getSourceRange();
11843 NoteLoc = X->getExprLoc();
11844 NoteRange = X->getSourceRange();
11845 ErrorFound = NotAnUpdateExpression;
11846 }
11847 } else {
11848 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11849 ErrorRange = AtomicInnerBinOp->getSourceRange();
11850 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11851 NoteRange = SourceRange(NoteLoc, NoteLoc);
11852 ErrorFound = NotABinaryOperator;
11853 }
11854 } else {
11855 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11856 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11857 ErrorFound = NotABinaryExpression;
11858 }
11859 } else {
11860 ErrorLoc = AtomicBinOp->getExprLoc();
11861 ErrorRange = AtomicBinOp->getSourceRange();
11862 NoteLoc = AtomicBinOp->getOperatorLoc();
11863 NoteRange = SourceRange(NoteLoc, NoteLoc);
11864 ErrorFound = NotAnAssignmentOp;
11865 }
11866 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11867 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11868 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11869 return true;
11870 }
11871 if (SemaRef.CurContext->isDependentContext())
11872 E = X = UpdateExpr = nullptr;
11873 return ErrorFound != NoError;
11874}
11875
11876bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11877 unsigned NoteId) {
11878 ExprAnalysisErrorCode ErrorFound = NoError;
11879 SourceLocation ErrorLoc, NoteLoc;
11880 SourceRange ErrorRange, NoteRange;
11881 // Allowed constructs are:
11882 // x++;
11883 // x--;
11884 // ++x;
11885 // --x;
11886 // x binop= expr;
11887 // x = x binop expr;
11888 // x = expr binop x;
11889 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11890 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11891 if (AtomicBody->getType()->isScalarType() ||
11892 AtomicBody->isInstantiationDependent()) {
11893 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11894 AtomicBody->IgnoreParenImpCasts())) {
11895 // Check for Compound Assignment Operation
11897 AtomicCompAssignOp->getOpcode());
11898 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11899 E = AtomicCompAssignOp->getRHS();
11900 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11901 IsXLHSInRHSPart = true;
11902 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11903 AtomicBody->IgnoreParenImpCasts())) {
11904 // Check for Binary Operation
11905 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11906 return true;
11907 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11908 AtomicBody->IgnoreParenImpCasts())) {
11909 // Check for Unary Operation
11910 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11911 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11912 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11913 OpLoc = AtomicUnaryOp->getOperatorLoc();
11914 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11915 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11916 IsXLHSInRHSPart = true;
11917 } else {
11918 ErrorFound = NotAnUnaryIncDecExpression;
11919 ErrorLoc = AtomicUnaryOp->getExprLoc();
11920 ErrorRange = AtomicUnaryOp->getSourceRange();
11921 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11922 NoteRange = SourceRange(NoteLoc, NoteLoc);
11923 }
11924 } else if (!AtomicBody->isInstantiationDependent()) {
11925 ErrorFound = NotABinaryOrUnaryExpression;
11926 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11927 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11928 } else if (AtomicBody->containsErrors()) {
11929 ErrorFound = NotAValidExpression;
11930 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11931 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11932 }
11933 } else {
11934 ErrorFound = NotAScalarType;
11935 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11936 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11937 }
11938 } else {
11939 ErrorFound = NotAnExpression;
11940 NoteLoc = ErrorLoc = S->getBeginLoc();
11941 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11942 }
11943 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11944 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11945 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11946 return true;
11947 }
11948 if (SemaRef.CurContext->isDependentContext())
11949 E = X = UpdateExpr = nullptr;
11950 if (ErrorFound == NoError && E && X) {
11951 // Build an update expression of form 'OpaqueValueExpr(x) binop
11952 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11953 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11954 auto *OVEX = new (SemaRef.getASTContext())
11955 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11956 auto *OVEExpr = new (SemaRef.getASTContext())
11959 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11960 IsXLHSInRHSPart ? OVEExpr : OVEX);
11961 if (Update.isInvalid())
11962 return true;
11963 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11965 if (Update.isInvalid())
11966 return true;
11967 UpdateExpr = Update.get();
11968 }
11969 return ErrorFound != NoError;
11970}
11971
11972/// Get the node id of the fixed point of an expression \a S.
11973llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11974 llvm::FoldingSetNodeID Id;
11975 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11976 return Id;
11977}
11978
11979/// Check if two expressions are same.
11980bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11981 const Expr *RHS) {
11982 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11983}
11984
11985class OpenMPAtomicCompareChecker {
11986public:
11987 /// All kinds of errors that can occur in `atomic compare`
11988 enum ErrorTy {
11989 /// Empty compound statement.
11990 NoStmt = 0,
11991 /// More than one statement in a compound statement.
11992 MoreThanOneStmt,
11993 /// Not an assignment binary operator.
11994 NotAnAssignment,
11995 /// Not a conditional operator.
11996 NotCondOp,
11997 /// Wrong false expr. According to the spec, 'x' should be at the false
11998 /// expression of a conditional expression.
11999 WrongFalseExpr,
12000 /// The condition of a conditional expression is not a binary operator.
12001 NotABinaryOp,
12002 /// Invalid binary operator (not <, >, or ==).
12003 InvalidBinaryOp,
12004 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
12005 InvalidComparison,
12006 /// X is not a lvalue.
12007 XNotLValue,
12008 /// Not a scalar.
12009 NotScalar,
12010 /// Not an integer.
12011 NotInteger,
12012 /// 'else' statement is not expected.
12013 UnexpectedElse,
12014 /// Not an equality operator.
12015 NotEQ,
12016 /// Invalid assignment (not v == x).
12017 InvalidAssignment,
12018 /// Not if statement
12019 NotIfStmt,
12020 /// More than two statements in a compund statement.
12021 MoreThanTwoStmts,
12022 /// Not a compound statement.
12023 NotCompoundStmt,
12024 /// No else statement.
12025 NoElse,
12026 /// Not 'if (r)'.
12027 InvalidCondition,
12028 /// No error.
12029 NoError,
12030 };
12031
12032 struct ErrorInfoTy {
12033 ErrorTy Error;
12034 SourceLocation ErrorLoc;
12035 SourceRange ErrorRange;
12036 SourceLocation NoteLoc;
12037 SourceRange NoteRange;
12038 };
12039
12040 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
12041
12042 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
12043 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12044
12045 Expr *getX() const { return X; }
12046 Expr *getE() const { return E; }
12047 Expr *getD() const { return D; }
12048 Expr *getCond() const { return C; }
12049 bool isXBinopExpr() const { return IsXBinopExpr; }
12050
12051protected:
12052 /// Reference to ASTContext
12053 ASTContext &ContextRef;
12054 /// 'x' lvalue part of the source atomic expression.
12055 Expr *X = nullptr;
12056 /// 'expr' or 'e' rvalue part of the source atomic expression.
12057 Expr *E = nullptr;
12058 /// 'd' rvalue part of the source atomic expression.
12059 Expr *D = nullptr;
12060 /// 'cond' part of the source atomic expression. It is in one of the following
12061 /// forms:
12062 /// expr ordop x
12063 /// x ordop expr
12064 /// x == e
12065 /// e == x
12066 Expr *C = nullptr;
12067 /// True if the cond expr is in the form of 'x ordop expr'.
12068 bool IsXBinopExpr = true;
12069
12070 /// Check if it is a valid conditional update statement (cond-update-stmt).
12071 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
12072
12073 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
12074 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12075
12076 /// Check if all captured values have right type.
12077 bool checkType(ErrorInfoTy &ErrorInfo) const;
12078
12079 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
12080 bool ShouldBeLValue, bool ShouldBeInteger = false) {
12081 if (E->isInstantiationDependent())
12082 return true;
12083
12084 if (ShouldBeLValue && !E->isLValue()) {
12085 ErrorInfo.Error = ErrorTy::XNotLValue;
12086 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12087 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12088 return false;
12089 }
12090
12091 QualType QTy = E->getType();
12092 if (!QTy->isScalarType()) {
12093 ErrorInfo.Error = ErrorTy::NotScalar;
12094 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12095 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12096 return false;
12097 }
12098 if (ShouldBeInteger && !QTy->isIntegerType()) {
12099 ErrorInfo.Error = ErrorTy::NotInteger;
12100 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12101 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12102 return false;
12103 }
12104
12105 return true;
12106 }
12107 };
12108
12109bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
12110 ErrorInfoTy &ErrorInfo) {
12111 auto *Then = S->getThen();
12112 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12113 if (CS->body_empty()) {
12114 ErrorInfo.Error = ErrorTy::NoStmt;
12115 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12116 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12117 return false;
12118 }
12119 if (CS->size() > 1) {
12120 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12121 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12122 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12123 return false;
12124 }
12125 Then = CS->body_front();
12126 }
12127
12128 auto *BO = dyn_cast<BinaryOperator>(Then);
12129 if (!BO) {
12130 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12131 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12132 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12133 return false;
12134 }
12135 if (BO->getOpcode() != BO_Assign) {
12136 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12137 ErrorInfo.ErrorLoc = BO->getExprLoc();
12138 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12139 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12140 return false;
12141 }
12142
12143 X = BO->getLHS();
12144
12145 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12146 if (!Cond) {
12147 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12148 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12149 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12150 return false;
12151 }
12152
12153 switch (Cond->getOpcode()) {
12154 case BO_EQ: {
12155 C = Cond;
12156 D = BO->getRHS();
12157 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12158 E = Cond->getRHS();
12159 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12160 E = Cond->getLHS();
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 case BO_LT:
12170 case BO_GT: {
12171 E = BO->getRHS();
12172 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
12173 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
12174 C = Cond;
12175 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
12176 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12177 C = Cond;
12178 IsXBinopExpr = false;
12179 } else {
12180 ErrorInfo.Error = ErrorTy::InvalidComparison;
12181 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12182 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12183 return false;
12184 }
12185 break;
12186 }
12187 default:
12188 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12189 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12190 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12191 return false;
12192 }
12193
12194 if (S->getElse()) {
12195 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12196 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
12197 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
12198 return false;
12199 }
12200
12201 return true;
12202}
12203
12204bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
12205 ErrorInfoTy &ErrorInfo) {
12206 auto *BO = dyn_cast<BinaryOperator>(S);
12207 if (!BO) {
12208 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12209 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12210 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12211 return false;
12212 }
12213 if (BO->getOpcode() != BO_Assign) {
12214 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12215 ErrorInfo.ErrorLoc = BO->getExprLoc();
12216 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12217 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12218 return false;
12219 }
12220
12221 X = BO->getLHS();
12222
12223 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
12224 if (!CO) {
12225 ErrorInfo.Error = ErrorTy::NotCondOp;
12226 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12227 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12228 return false;
12229 }
12230
12231 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
12232 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12233 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12234 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12235 CO->getFalseExpr()->getSourceRange();
12236 return false;
12237 }
12238
12239 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
12240 if (!Cond) {
12241 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12242 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12243 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12244 CO->getCond()->getSourceRange();
12245 return false;
12246 }
12247
12248 switch (Cond->getOpcode()) {
12249 case BO_EQ: {
12250 C = Cond;
12251 D = CO->getTrueExpr();
12252 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12253 E = Cond->getRHS();
12254 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12255 E = Cond->getLHS();
12256 } else {
12257 ErrorInfo.Error = ErrorTy::InvalidComparison;
12258 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12259 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12260 return false;
12261 }
12262 break;
12263 }
12264 case BO_LT:
12265 case BO_GT: {
12266 E = CO->getTrueExpr();
12267 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
12268 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
12269 C = Cond;
12270 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
12271 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12272 C = Cond;
12273 IsXBinopExpr = false;
12274 } else {
12275 ErrorInfo.Error = ErrorTy::InvalidComparison;
12276 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12277 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12278 return false;
12279 }
12280 break;
12281 }
12282 default:
12283 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12284 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12285 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12286 return false;
12287 }
12288
12289 return true;
12290}
12291
12292bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
12293 // 'x' and 'e' cannot be nullptr
12294 assert(X && E && "X and E cannot be nullptr");
12295
12296 if (!CheckValue(X, ErrorInfo, true))
12297 return false;
12298
12299 if (!CheckValue(E, ErrorInfo, false))
12300 return false;
12301
12302 if (D && !CheckValue(D, ErrorInfo, false))
12303 return false;
12304
12305 return true;
12306}
12307
12308bool OpenMPAtomicCompareChecker::checkStmt(
12309 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12310 auto *CS = dyn_cast<CompoundStmt>(S);
12311 if (CS) {
12312 if (CS->body_empty()) {
12313 ErrorInfo.Error = ErrorTy::NoStmt;
12314 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12315 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12316 return false;
12317 }
12318
12319 if (CS->size() != 1) {
12320 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12321 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12322 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12323 return false;
12324 }
12325 S = CS->body_front();
12326 }
12327
12328 auto Res = false;
12329
12330 if (auto *IS = dyn_cast<IfStmt>(S)) {
12331 // Check if the statement is in one of the following forms
12332 // (cond-update-stmt):
12333 // if (expr ordop x) { x = expr; }
12334 // if (x ordop expr) { x = expr; }
12335 // if (x == e) { x = d; }
12336 Res = checkCondUpdateStmt(IS, ErrorInfo);
12337 } else {
12338 // Check if the statement is in one of the following forms (cond-expr-stmt):
12339 // x = expr ordop x ? expr : x;
12340 // x = x ordop expr ? expr : x;
12341 // x = x == e ? d : x;
12342 Res = checkCondExprStmt(S, ErrorInfo);
12343 }
12344
12345 if (!Res)
12346 return false;
12347
12348 return checkType(ErrorInfo);
12349}
12350
12351class OpenMPAtomicCompareCaptureChecker final
12352 : public OpenMPAtomicCompareChecker {
12353public:
12354 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12355
12356 Expr *getV() const { return V; }
12357 Expr *getR() const { return R; }
12358 bool isFailOnly() const { return IsFailOnly; }
12359 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12360
12361 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12362 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12363
12364private:
12365 bool checkType(ErrorInfoTy &ErrorInfo);
12366
12367 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12368 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12369 // spec p.p. 82:
12370 // (1) { v = x; cond-update-stmt }
12371 // (2) { cond-update-stmt v = x; }
12372 // (3) if(x == e) { x = d; } else { v = x; }
12373 // (4) { r = x == e; if(r) { x = d; } }
12374 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12375
12376 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12377 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12378
12379 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12380 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12381 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12382
12383 /// 'v' lvalue part of the source atomic expression.
12384 Expr *V = nullptr;
12385 /// 'r' lvalue part of the source atomic expression.
12386 Expr *R = nullptr;
12387 /// If 'v' is only updated when the comparison fails.
12388 bool IsFailOnly = false;
12389 /// If original value of 'x' must be stored in 'v', not an updated one.
12390 bool IsPostfixUpdate = false;
12391};
12392
12393bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12394 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12395 return false;
12396
12397 if (V && !CheckValue(V, ErrorInfo, true))
12398 return false;
12399
12400 if (R && !CheckValue(R, ErrorInfo, true, true))
12401 return false;
12402
12403 return true;
12404}
12405
12406bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12407 ErrorInfoTy &ErrorInfo) {
12408 IsFailOnly = true;
12409
12410 auto *Then = S->getThen();
12411 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12412 if (CS->body_empty()) {
12413 ErrorInfo.Error = ErrorTy::NoStmt;
12414 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12415 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12416 return false;
12417 }
12418 if (CS->size() > 1) {
12419 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12420 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12421 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12422 return false;
12423 }
12424 Then = CS->body_front();
12425 }
12426
12427 auto *BO = dyn_cast<BinaryOperator>(Then);
12428 if (!BO) {
12429 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12430 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12431 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12432 return false;
12433 }
12434 if (BO->getOpcode() != BO_Assign) {
12435 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12436 ErrorInfo.ErrorLoc = BO->getExprLoc();
12437 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12438 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12439 return false;
12440 }
12441
12442 X = BO->getLHS();
12443 D = BO->getRHS();
12444
12445 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12446 if (!Cond) {
12447 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12448 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12449 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12450 return false;
12451 }
12452 if (Cond->getOpcode() != BO_EQ) {
12453 ErrorInfo.Error = ErrorTy::NotEQ;
12454 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12455 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12456 return false;
12457 }
12458
12459 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12460 E = Cond->getRHS();
12461 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12462 E = Cond->getLHS();
12463 } else {
12464 ErrorInfo.Error = ErrorTy::InvalidComparison;
12465 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12466 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12467 return false;
12468 }
12469
12470 C = Cond;
12471
12472 if (!S->getElse()) {
12473 ErrorInfo.Error = ErrorTy::NoElse;
12474 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12475 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12476 return false;
12477 }
12478
12479 auto *Else = S->getElse();
12480 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12481 if (CS->body_empty()) {
12482 ErrorInfo.Error = ErrorTy::NoStmt;
12483 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12484 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12485 return false;
12486 }
12487 if (CS->size() > 1) {
12488 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12489 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12490 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12491 return false;
12492 }
12493 Else = CS->body_front();
12494 }
12495
12496 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12497 if (!ElseBO) {
12498 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12499 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12500 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12501 return false;
12502 }
12503 if (ElseBO->getOpcode() != BO_Assign) {
12504 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12505 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12506 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12507 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12508 return false;
12509 }
12510
12511 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12512 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12513 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12514 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12515 ElseBO->getRHS()->getSourceRange();
12516 return false;
12517 }
12518
12519 V = ElseBO->getLHS();
12520
12521 return checkType(ErrorInfo);
12522}
12523
12524bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12525 ErrorInfoTy &ErrorInfo) {
12526 // We don't check here as they should be already done before call this
12527 // function.
12528 auto *CS = cast<CompoundStmt>(S);
12529 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12530 auto *S1 = cast<BinaryOperator>(CS->body_front());
12531 auto *S2 = cast<IfStmt>(CS->body_back());
12532 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12533
12534 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12535 ErrorInfo.Error = ErrorTy::InvalidCondition;
12536 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12537 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12538 return false;
12539 }
12540
12541 R = S1->getLHS();
12542
12543 auto *Then = S2->getThen();
12544 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12545 if (ThenCS->body_empty()) {
12546 ErrorInfo.Error = ErrorTy::NoStmt;
12547 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12548 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12549 return false;
12550 }
12551 if (ThenCS->size() > 1) {
12552 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12553 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12554 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12555 return false;
12556 }
12557 Then = ThenCS->body_front();
12558 }
12559
12560 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12561 if (!ThenBO) {
12562 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12563 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12564 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12565 return false;
12566 }
12567 if (ThenBO->getOpcode() != BO_Assign) {
12568 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12569 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12570 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12571 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12572 return false;
12573 }
12574
12575 X = ThenBO->getLHS();
12576 D = ThenBO->getRHS();
12577
12578 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12579 if (BO->getOpcode() != BO_EQ) {
12580 ErrorInfo.Error = ErrorTy::NotEQ;
12581 ErrorInfo.ErrorLoc = BO->getExprLoc();
12582 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12583 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12584 return false;
12585 }
12586
12587 C = BO;
12588
12589 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12590 E = BO->getRHS();
12591 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12592 E = BO->getLHS();
12593 } else {
12594 ErrorInfo.Error = ErrorTy::InvalidComparison;
12595 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12596 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12597 return false;
12598 }
12599
12600 if (S2->getElse()) {
12601 IsFailOnly = true;
12602
12603 auto *Else = S2->getElse();
12604 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12605 if (ElseCS->body_empty()) {
12606 ErrorInfo.Error = ErrorTy::NoStmt;
12607 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12608 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12609 return false;
12610 }
12611 if (ElseCS->size() > 1) {
12612 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12613 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12614 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12615 return false;
12616 }
12617 Else = ElseCS->body_front();
12618 }
12619
12620 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12621 if (!ElseBO) {
12622 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12623 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12624 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12625 return false;
12626 }
12627 if (ElseBO->getOpcode() != BO_Assign) {
12628 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12629 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12630 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12631 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12632 return false;
12633 }
12634 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12635 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12636 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12637 ErrorInfo.NoteLoc = X->getExprLoc();
12638 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12639 ErrorInfo.NoteRange = X->getSourceRange();
12640 return false;
12641 }
12642
12643 V = ElseBO->getLHS();
12644 }
12645
12646 return checkType(ErrorInfo);
12647}
12648
12649bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12650 ErrorInfoTy &ErrorInfo) {
12651 // if(x == e) { x = d; } else { v = x; }
12652 if (auto *IS = dyn_cast<IfStmt>(S))
12653 return checkForm3(IS, ErrorInfo);
12654
12655 auto *CS = dyn_cast<CompoundStmt>(S);
12656 if (!CS) {
12657 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12658 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12659 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12660 return false;
12661 }
12662 if (CS->body_empty()) {
12663 ErrorInfo.Error = ErrorTy::NoStmt;
12664 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12665 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12666 return false;
12667 }
12668
12669 // { if(x == e) { x = d; } else { v = x; } }
12670 if (CS->size() == 1) {
12671 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12672 if (!IS) {
12673 ErrorInfo.Error = ErrorTy::NotIfStmt;
12674 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12675 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12676 CS->body_front()->getSourceRange();
12677 return false;
12678 }
12679
12680 return checkForm3(IS, ErrorInfo);
12681 } else if (CS->size() == 2) {
12682 auto *S1 = CS->body_front();
12683 auto *S2 = CS->body_back();
12684
12685 Stmt *UpdateStmt = nullptr;
12686 Stmt *CondUpdateStmt = nullptr;
12687 Stmt *CondExprStmt = nullptr;
12688
12689 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12690 // It could be one of the following cases:
12691 // { v = x; cond-update-stmt }
12692 // { v = x; cond-expr-stmt }
12693 // { cond-expr-stmt; v = x; }
12694 // form 45
12695 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12696 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12697 // check if form 45
12698 if (isa<IfStmt>(S2))
12699 return checkForm45(CS, ErrorInfo);
12700 // { cond-expr-stmt; v = x; }
12701 CondExprStmt = S1;
12702 UpdateStmt = S2;
12703 } else {
12704 IsPostfixUpdate = true;
12705 UpdateStmt = S1;
12706 if (isa<IfStmt>(S2)) {
12707 // { v = x; cond-update-stmt }
12708 CondUpdateStmt = S2;
12709 } else {
12710 // { v = x; cond-expr-stmt }
12711 CondExprStmt = S2;
12712 }
12713 }
12714 } else {
12715 // { cond-update-stmt v = x; }
12716 UpdateStmt = S2;
12717 CondUpdateStmt = S1;
12718 }
12719
12720 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12721 auto *IS = dyn_cast<IfStmt>(CUS);
12722 if (!IS) {
12723 ErrorInfo.Error = ErrorTy::NotIfStmt;
12724 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12725 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12726 return false;
12727 }
12728
12729 return checkCondUpdateStmt(IS, ErrorInfo);
12730 };
12731
12732 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12733 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12734 auto *BO = dyn_cast<BinaryOperator>(US);
12735 if (!BO) {
12736 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12737 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12738 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12739 return false;
12740 }
12741 if (BO->getOpcode() != BO_Assign) {
12742 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12743 ErrorInfo.ErrorLoc = BO->getExprLoc();
12744 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12745 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12746 return false;
12747 }
12748 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12749 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12750 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12751 ErrorInfo.NoteLoc = this->X->getExprLoc();
12752 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12753 ErrorInfo.NoteRange = this->X->getSourceRange();
12754 return false;
12755 }
12756
12757 this->V = BO->getLHS();
12758
12759 return true;
12760 };
12761
12762 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12763 return false;
12764 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12765 return false;
12766 if (!CheckUpdateStmt(UpdateStmt))
12767 return false;
12768 } else {
12769 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12770 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12771 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12772 return false;
12773 }
12774
12775 return checkType(ErrorInfo);
12776}
12777} // namespace
12778
12780 Stmt *AStmt,
12781 SourceLocation StartLoc,
12782 SourceLocation EndLoc) {
12783 ASTContext &Context = getASTContext();
12784 // Register location of the first atomic directive.
12785 DSAStack->addAtomicDirectiveLoc(StartLoc);
12786 if (!AStmt)
12787 return StmtError();
12788
12789 // 1.2.2 OpenMP Language Terminology
12790 // Structured block - An executable statement with a single entry at the
12791 // top and a single exit at the bottom.
12792 // The point of exit cannot be a branch out of the structured block.
12793 // longjmp() and throw() must not violate the entry/exit criteria.
12794 OpenMPClauseKind AtomicKind = OMPC_unknown;
12795 SourceLocation AtomicKindLoc;
12796 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12797 SourceLocation MemOrderLoc;
12798 bool MutexClauseEncountered = false;
12799 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12800 for (const OMPClause *C : Clauses) {
12801 switch (C->getClauseKind()) {
12802 case OMPC_read:
12803 case OMPC_write:
12804 case OMPC_update:
12805 MutexClauseEncountered = true;
12806 [[fallthrough]];
12807 case OMPC_capture:
12808 case OMPC_compare: {
12809 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12810 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12811 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12812 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12813 << getOpenMPClauseName(AtomicKind);
12814 } else {
12815 AtomicKind = C->getClauseKind();
12816 AtomicKindLoc = C->getBeginLoc();
12817 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12818 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12819 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12820 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12821 << getOpenMPClauseName(AtomicKind);
12822 }
12823 }
12824 break;
12825 }
12826 case OMPC_weak:
12827 case OMPC_fail: {
12828 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12829 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12830 << getOpenMPClauseName(C->getClauseKind())
12831 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12832 return StmtError();
12833 }
12834 break;
12835 }
12836 case OMPC_seq_cst:
12837 case OMPC_acq_rel:
12838 case OMPC_acquire:
12839 case OMPC_release:
12840 case OMPC_relaxed: {
12841 if (MemOrderKind != OMPC_unknown) {
12842 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12843 << getOpenMPDirectiveName(OMPD_atomic) << 0
12844 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12845 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12846 << getOpenMPClauseName(MemOrderKind);
12847 } else {
12848 MemOrderKind = C->getClauseKind();
12849 MemOrderLoc = C->getBeginLoc();
12850 }
12851 break;
12852 }
12853 // The following clauses are allowed, but we don't need to do anything here.
12854 case OMPC_hint:
12855 break;
12856 default:
12857 llvm_unreachable("unknown clause is encountered");
12858 }
12859 }
12860 bool IsCompareCapture = false;
12861 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12862 EncounteredAtomicKinds.contains(OMPC_capture)) {
12863 IsCompareCapture = true;
12864 AtomicKind = OMPC_compare;
12865 }
12866 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12867 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12868 // release.
12869 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12870 // acquire.
12871 // If atomic-clause is update or not present then memory-order-clause must not
12872 // be acq_rel or acquire.
12873 if ((AtomicKind == OMPC_read &&
12874 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12875 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12876 AtomicKind == OMPC_unknown) &&
12877 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12878 SourceLocation Loc = AtomicKindLoc;
12879 if (AtomicKind == OMPC_unknown)
12880 Loc = StartLoc;
12881 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12882 << getOpenMPClauseName(AtomicKind)
12883 << (AtomicKind == OMPC_unknown ? 1 : 0)
12884 << getOpenMPClauseName(MemOrderKind);
12885 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12886 << getOpenMPClauseName(MemOrderKind);
12887 }
12888
12889 Stmt *Body = AStmt;
12890 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12891 Body = EWC->getSubExpr();
12892
12893 Expr *X = nullptr;
12894 Expr *V = nullptr;
12895 Expr *E = nullptr;
12896 Expr *UE = nullptr;
12897 Expr *D = nullptr;
12898 Expr *CE = nullptr;
12899 Expr *R = nullptr;
12900 bool IsXLHSInRHSPart = false;
12901 bool IsPostfixUpdate = false;
12902 bool IsFailOnly = false;
12903 // OpenMP [2.12.6, atomic Construct]
12904 // In the next expressions:
12905 // * x and v (as applicable) are both l-value expressions with scalar type.
12906 // * During the execution of an atomic region, multiple syntactic
12907 // occurrences of x must designate the same storage location.
12908 // * Neither of v and expr (as applicable) may access the storage location
12909 // designated by x.
12910 // * Neither of x and expr (as applicable) may access the storage location
12911 // designated by v.
12912 // * expr is an expression with scalar type.
12913 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12914 // * binop, binop=, ++, and -- are not overloaded operators.
12915 // * The expression x binop expr must be numerically equivalent to x binop
12916 // (expr). This requirement is satisfied if the operators in expr have
12917 // precedence greater than binop, or by using parentheses around expr or
12918 // subexpressions of expr.
12919 // * The expression expr binop x must be numerically equivalent to (expr)
12920 // binop x. This requirement is satisfied if the operators in expr have
12921 // precedence equal to or greater than binop, or by using parentheses around
12922 // expr or subexpressions of expr.
12923 // * For forms that allow multiple occurrences of x, the number of times
12924 // that x is evaluated is unspecified.
12925 if (AtomicKind == OMPC_read) {
12926 enum {
12927 NotAnExpression,
12928 NotAnAssignmentOp,
12929 NotAScalarType,
12930 NotAnLValue,
12931 NoError
12932 } ErrorFound = NoError;
12933 SourceLocation ErrorLoc, NoteLoc;
12934 SourceRange ErrorRange, NoteRange;
12935 // If clause is read:
12936 // v = x;
12937 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12938 const auto *AtomicBinOp =
12939 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12940 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12941 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12942 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12943 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12944 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12945 if (!X->isLValue() || !V->isLValue()) {
12946 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12947 ErrorFound = NotAnLValue;
12948 ErrorLoc = AtomicBinOp->getExprLoc();
12949 ErrorRange = AtomicBinOp->getSourceRange();
12950 NoteLoc = NotLValueExpr->getExprLoc();
12951 NoteRange = NotLValueExpr->getSourceRange();
12952 }
12953 } else if (!X->isInstantiationDependent() ||
12954 !V->isInstantiationDependent()) {
12955 const Expr *NotScalarExpr =
12956 (X->isInstantiationDependent() || X->getType()->isScalarType())
12957 ? V
12958 : X;
12959 ErrorFound = NotAScalarType;
12960 ErrorLoc = AtomicBinOp->getExprLoc();
12961 ErrorRange = AtomicBinOp->getSourceRange();
12962 NoteLoc = NotScalarExpr->getExprLoc();
12963 NoteRange = NotScalarExpr->getSourceRange();
12964 }
12965 } else if (!AtomicBody->isInstantiationDependent()) {
12966 ErrorFound = NotAnAssignmentOp;
12967 ErrorLoc = AtomicBody->getExprLoc();
12968 ErrorRange = AtomicBody->getSourceRange();
12969 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12970 : AtomicBody->getExprLoc();
12971 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12972 : AtomicBody->getSourceRange();
12973 }
12974 } else {
12975 ErrorFound = NotAnExpression;
12976 NoteLoc = ErrorLoc = Body->getBeginLoc();
12977 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12978 }
12979 if (ErrorFound != NoError) {
12980 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12981 << ErrorRange;
12982 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12983 << ErrorFound << NoteRange;
12984 return StmtError();
12985 }
12987 V = X = nullptr;
12988 } else if (AtomicKind == OMPC_write) {
12989 enum {
12990 NotAnExpression,
12991 NotAnAssignmentOp,
12992 NotAScalarType,
12993 NotAnLValue,
12994 NoError
12995 } ErrorFound = NoError;
12996 SourceLocation ErrorLoc, NoteLoc;
12997 SourceRange ErrorRange, NoteRange;
12998 // If clause is write:
12999 // x = expr;
13000 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
13001 const auto *AtomicBinOp =
13002 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
13003 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
13004 X = AtomicBinOp->getLHS();
13005 E = AtomicBinOp->getRHS();
13006 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
13007 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
13008 if (!X->isLValue()) {
13009 ErrorFound = NotAnLValue;
13010 ErrorLoc = AtomicBinOp->getExprLoc();
13011 ErrorRange = AtomicBinOp->getSourceRange();
13012 NoteLoc = X->getExprLoc();
13013 NoteRange = X->getSourceRange();
13014 }
13015 } else if (!X->isInstantiationDependent() ||
13017 const Expr *NotScalarExpr =
13018 (X->isInstantiationDependent() || X->getType()->isScalarType())
13019 ? E
13020 : X;
13021 ErrorFound = NotAScalarType;
13022 ErrorLoc = AtomicBinOp->getExprLoc();
13023 ErrorRange = AtomicBinOp->getSourceRange();
13024 NoteLoc = NotScalarExpr->getExprLoc();
13025 NoteRange = NotScalarExpr->getSourceRange();
13026 }
13027 } else if (!AtomicBody->isInstantiationDependent()) {
13028 ErrorFound = NotAnAssignmentOp;
13029 ErrorLoc = AtomicBody->getExprLoc();
13030 ErrorRange = AtomicBody->getSourceRange();
13031 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13032 : AtomicBody->getExprLoc();
13033 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13034 : AtomicBody->getSourceRange();
13035 }
13036 } else {
13037 ErrorFound = NotAnExpression;
13038 NoteLoc = ErrorLoc = Body->getBeginLoc();
13039 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
13040 }
13041 if (ErrorFound != NoError) {
13042 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
13043 << ErrorRange;
13044 Diag(NoteLoc, diag::note_omp_atomic_read_write)
13045 << ErrorFound << NoteRange;
13046 return StmtError();
13047 }
13049 E = X = nullptr;
13050 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
13051 // If clause is update:
13052 // x++;
13053 // x--;
13054 // ++x;
13055 // --x;
13056 // x binop= expr;
13057 // x = x binop expr;
13058 // x = expr binop x;
13059 OpenMPAtomicUpdateChecker Checker(SemaRef);
13060 if (Checker.checkStatement(
13061 Body,
13062 (AtomicKind == OMPC_update)
13063 ? diag::err_omp_atomic_update_not_expression_statement
13064 : diag::err_omp_atomic_not_expression_statement,
13065 diag::note_omp_atomic_update))
13066 return StmtError();
13068 E = Checker.getExpr();
13069 X = Checker.getX();
13070 UE = Checker.getUpdateExpr();
13071 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13072 }
13073 } else if (AtomicKind == OMPC_capture) {
13074 enum {
13075 NotAnAssignmentOp,
13076 NotACompoundStatement,
13077 NotTwoSubstatements,
13078 NotASpecificExpression,
13079 NoError
13080 } ErrorFound = NoError;
13081 SourceLocation ErrorLoc, NoteLoc;
13082 SourceRange ErrorRange, NoteRange;
13083 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
13084 // If clause is a capture:
13085 // v = x++;
13086 // v = x--;
13087 // v = ++x;
13088 // v = --x;
13089 // v = x binop= expr;
13090 // v = x = x binop expr;
13091 // v = x = expr binop x;
13092 const auto *AtomicBinOp =
13093 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
13094 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
13095 V = AtomicBinOp->getLHS();
13096 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
13097 OpenMPAtomicUpdateChecker Checker(SemaRef);
13098 if (Checker.checkStatement(
13099 Body, diag::err_omp_atomic_capture_not_expression_statement,
13100 diag::note_omp_atomic_update))
13101 return StmtError();
13102 E = Checker.getExpr();
13103 X = Checker.getX();
13104 UE = Checker.getUpdateExpr();
13105 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13106 IsPostfixUpdate = Checker.isPostfixUpdate();
13107 } else if (!AtomicBody->isInstantiationDependent()) {
13108 ErrorLoc = AtomicBody->getExprLoc();
13109 ErrorRange = AtomicBody->getSourceRange();
13110 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13111 : AtomicBody->getExprLoc();
13112 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13113 : AtomicBody->getSourceRange();
13114 ErrorFound = NotAnAssignmentOp;
13115 }
13116 if (ErrorFound != NoError) {
13117 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
13118 << ErrorRange;
13119 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13120 return StmtError();
13121 }
13123 UE = V = E = X = nullptr;
13124 } else {
13125 // If clause is a capture:
13126 // { v = x; x = expr; }
13127 // { v = x; x++; }
13128 // { v = x; x--; }
13129 // { v = x; ++x; }
13130 // { v = x; --x; }
13131 // { v = x; x binop= expr; }
13132 // { v = x; x = x binop expr; }
13133 // { v = x; x = expr binop x; }
13134 // { x++; v = x; }
13135 // { x--; v = x; }
13136 // { ++x; v = x; }
13137 // { --x; v = x; }
13138 // { x binop= expr; v = x; }
13139 // { x = x binop expr; v = x; }
13140 // { x = expr binop x; v = x; }
13141 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
13142 // Check that this is { expr1; expr2; }
13143 if (CS->size() == 2) {
13144 Stmt *First = CS->body_front();
13145 Stmt *Second = CS->body_back();
13146 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
13147 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13148 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
13149 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13150 // Need to find what subexpression is 'v' and what is 'x'.
13151 OpenMPAtomicUpdateChecker Checker(SemaRef);
13152 bool IsUpdateExprFound = !Checker.checkStatement(Second);
13153 BinaryOperator *BinOp = nullptr;
13154 if (IsUpdateExprFound) {
13155 BinOp = dyn_cast<BinaryOperator>(First);
13156 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13157 }
13158 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
13159 // { v = x; x++; }
13160 // { v = x; x--; }
13161 // { v = x; ++x; }
13162 // { v = x; --x; }
13163 // { v = x; x binop= expr; }
13164 // { v = x; x = x binop expr; }
13165 // { v = x; x = expr binop x; }
13166 // Check that the first expression has form v = x.
13167 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13168 llvm::FoldingSetNodeID XId, PossibleXId;
13169 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13170 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13171 IsUpdateExprFound = XId == PossibleXId;
13172 if (IsUpdateExprFound) {
13173 V = BinOp->getLHS();
13174 X = Checker.getX();
13175 E = Checker.getExpr();
13176 UE = Checker.getUpdateExpr();
13177 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13178 IsPostfixUpdate = true;
13179 }
13180 }
13181 if (!IsUpdateExprFound) {
13182 IsUpdateExprFound = !Checker.checkStatement(First);
13183 BinOp = nullptr;
13184 if (IsUpdateExprFound) {
13185 BinOp = dyn_cast<BinaryOperator>(Second);
13186 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13187 }
13188 if (IsUpdateExprFound &&
13190 // { x++; v = x; }
13191 // { x--; v = x; }
13192 // { ++x; v = x; }
13193 // { --x; v = x; }
13194 // { x binop= expr; v = x; }
13195 // { x = x binop expr; v = x; }
13196 // { x = expr binop x; v = x; }
13197 // Check that the second expression has form v = x.
13198 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13199 llvm::FoldingSetNodeID XId, PossibleXId;
13200 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13201 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13202 IsUpdateExprFound = XId == PossibleXId;
13203 if (IsUpdateExprFound) {
13204 V = BinOp->getLHS();
13205 X = Checker.getX();
13206 E = Checker.getExpr();
13207 UE = Checker.getUpdateExpr();
13208 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13209 IsPostfixUpdate = false;
13210 }
13211 }
13212 }
13213 if (!IsUpdateExprFound) {
13214 // { v = x; x = expr; }
13215 auto *FirstExpr = dyn_cast<Expr>(First);
13216 auto *SecondExpr = dyn_cast<Expr>(Second);
13217 if (!FirstExpr || !SecondExpr ||
13218 !(FirstExpr->isInstantiationDependent() ||
13219 SecondExpr->isInstantiationDependent())) {
13220 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
13221 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13222 ErrorFound = NotAnAssignmentOp;
13223 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13224 : First->getBeginLoc();
13225 NoteRange = ErrorRange = FirstBinOp
13226 ? FirstBinOp->getSourceRange()
13227 : SourceRange(ErrorLoc, ErrorLoc);
13228 } else {
13229 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
13230 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13231 ErrorFound = NotAnAssignmentOp;
13232 NoteLoc = ErrorLoc = SecondBinOp
13233 ? SecondBinOp->getOperatorLoc()
13234 : Second->getBeginLoc();
13235 NoteRange = ErrorRange =
13236 SecondBinOp ? SecondBinOp->getSourceRange()
13237 : SourceRange(ErrorLoc, ErrorLoc);
13238 } else {
13239 Expr *PossibleXRHSInFirst =
13240 FirstBinOp->getRHS()->IgnoreParenImpCasts();
13241 Expr *PossibleXLHSInSecond =
13242 SecondBinOp->getLHS()->IgnoreParenImpCasts();
13243 llvm::FoldingSetNodeID X1Id, X2Id;
13244 PossibleXRHSInFirst->Profile(X1Id, Context,
13245 /*Canonical=*/true);
13246 PossibleXLHSInSecond->Profile(X2Id, Context,
13247 /*Canonical=*/true);
13248 IsUpdateExprFound = X1Id == X2Id;
13249 if (IsUpdateExprFound) {
13250 V = FirstBinOp->getLHS();
13251 X = SecondBinOp->getLHS();
13252 E = SecondBinOp->getRHS();
13253 UE = nullptr;
13254 IsXLHSInRHSPart = false;
13255 IsPostfixUpdate = true;
13256 } else {
13257 ErrorFound = NotASpecificExpression;
13258 ErrorLoc = FirstBinOp->getExprLoc();
13259 ErrorRange = FirstBinOp->getSourceRange();
13260 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13261 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13262 }
13263 }
13264 }
13265 }
13266 }
13267 } else {
13268 NoteLoc = ErrorLoc = Body->getBeginLoc();
13269 NoteRange = ErrorRange =
13270 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13271 ErrorFound = NotTwoSubstatements;
13272 }
13273 } else {
13274 NoteLoc = ErrorLoc = Body->getBeginLoc();
13275 NoteRange = ErrorRange =
13276 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13277 ErrorFound = NotACompoundStatement;
13278 }
13279 }
13280 if (ErrorFound != NoError) {
13281 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
13282 << ErrorRange;
13283 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13284 return StmtError();
13285 }
13287 UE = V = E = X = nullptr;
13288 } else if (AtomicKind == OMPC_compare) {
13289 if (IsCompareCapture) {
13290 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13291 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
13292 if (!Checker.checkStmt(Body, ErrorInfo)) {
13293 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
13294 << ErrorInfo.ErrorRange;
13295 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13296 << ErrorInfo.Error << ErrorInfo.NoteRange;
13297 return StmtError();
13298 }
13299 X = Checker.getX();
13300 E = Checker.getE();
13301 D = Checker.getD();
13302 CE = Checker.getCond();
13303 V = Checker.getV();
13304 R = Checker.getR();
13305 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13306 IsXLHSInRHSPart = Checker.isXBinopExpr();
13307 IsFailOnly = Checker.isFailOnly();
13308 IsPostfixUpdate = Checker.isPostfixUpdate();
13309 } else {
13310 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13311 OpenMPAtomicCompareChecker Checker(SemaRef);
13312 if (!Checker.checkStmt(Body, ErrorInfo)) {
13313 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
13314 << ErrorInfo.ErrorRange;
13315 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13316 << ErrorInfo.Error << ErrorInfo.NoteRange;
13317 return StmtError();
13318 }
13319 X = Checker.getX();
13320 E = Checker.getE();
13321 D = Checker.getD();
13322 CE = Checker.getCond();
13323 // The weak clause may only appear if the resulting atomic operation is
13324 // an atomic conditional update for which the comparison tests for
13325 // equality. It was not possible to do this check in
13326 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
13327 // could not be performed (Clauses are not available).
13328 auto *It = find_if(Clauses, [](OMPClause *C) {
13329 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13330 });
13331 if (It != Clauses.end()) {
13332 auto *Cond = dyn_cast<BinaryOperator>(CE);
13333 if (Cond->getOpcode() != BO_EQ) {
13334 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13335 ErrorInfo.ErrorLoc = Cond->getExprLoc();
13336 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
13337 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
13338
13339 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
13340 << ErrorInfo.ErrorRange;
13341 return StmtError();
13342 }
13343 }
13344 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13345 IsXLHSInRHSPart = Checker.isXBinopExpr();
13346 }
13347 }
13348
13350
13352 Context, StartLoc, EndLoc, Clauses, AStmt,
13353 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
13354}
13355
13357 Stmt *AStmt,
13358 SourceLocation StartLoc,
13359 SourceLocation EndLoc) {
13360 if (!AStmt)
13361 return StmtError();
13362
13363 auto *CS = cast<CapturedStmt>(AStmt);
13364 // 1.2.2 OpenMP Language Terminology
13365 // Structured block - An executable statement with a single entry at the
13366 // top and a single exit at the bottom.
13367 // The point of exit cannot be a branch out of the structured block.
13368 // longjmp() and throw() must not violate the entry/exit criteria.
13369 CS->getCapturedDecl()->setNothrow();
13370 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target);
13371 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13372 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13373 // 1.2.2 OpenMP Language Terminology
13374 // Structured block - An executable statement with a single entry at the
13375 // top and a single exit at the bottom.
13376 // The point of exit cannot be a branch out of the structured block.
13377 // longjmp() and throw() must not violate the entry/exit criteria.
13378 CS->getCapturedDecl()->setNothrow();
13379 }
13380
13381 // OpenMP [2.16, Nesting of Regions]
13382 // If specified, a teams construct must be contained within a target
13383 // construct. That target construct must contain no statements or directives
13384 // outside of the teams construct.
13385 if (DSAStack->hasInnerTeamsRegion()) {
13386 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13387 bool OMPTeamsFound = true;
13388 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
13389 auto I = CS->body_begin();
13390 while (I != CS->body_end()) {
13391 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13392 if (!OED || !isOpenMPTeamsDirective(OED->getDirectiveKind()) ||
13393 OMPTeamsFound) {
13394
13395 OMPTeamsFound = false;
13396 break;
13397 }
13398 ++I;
13399 }
13400 assert(I != CS->body_end() && "Not found statement");
13401 S = *I;
13402 } else {
13403 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13404 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13405 }
13406 if (!OMPTeamsFound) {
13407 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13408 Diag(DSAStack->getInnerTeamsRegionLoc(),
13409 diag::note_omp_nested_teams_construct_here);
13410 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
13411 << isa<OMPExecutableDirective>(S);
13412 return StmtError();
13413 }
13414 }
13415
13417
13418 return OMPTargetDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13419 AStmt);
13420}
13421
13423 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13424 SourceLocation EndLoc) {
13425 if (!AStmt)
13426 return StmtError();
13427
13428 auto *CS = cast<CapturedStmt>(AStmt);
13429 // 1.2.2 OpenMP Language Terminology
13430 // Structured block - An executable statement with a single entry at the
13431 // top and a single exit at the bottom.
13432 // The point of exit cannot be a branch out of the structured block.
13433 // longjmp() and throw() must not violate the entry/exit criteria.
13434 CS->getCapturedDecl()->setNothrow();
13435 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel);
13436 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13437 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13438 // 1.2.2 OpenMP Language Terminology
13439 // Structured block - An executable statement with a single entry at the
13440 // top and a single exit at the bottom.
13441 // The point of exit cannot be a branch out of the structured block.
13442 // longjmp() and throw() must not violate the entry/exit criteria.
13443 CS->getCapturedDecl()->setNothrow();
13444 }
13445
13447
13449 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
13450 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13451}
13452
13454 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13455 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13456 if (!AStmt)
13457 return StmtError();
13458
13459 auto *CS = cast<CapturedStmt>(AStmt);
13460 // 1.2.2 OpenMP Language Terminology
13461 // Structured block - An executable statement with a single entry at the
13462 // top and a single exit at the bottom.
13463 // The point of exit cannot be a branch out of the structured block.
13464 // longjmp() and throw() must not violate the entry/exit criteria.
13465 CS->getCapturedDecl()->setNothrow();
13466 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for);
13467 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13468 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13469 // 1.2.2 OpenMP Language Terminology
13470 // Structured block - An executable statement with a single entry at the
13471 // top and a single exit at the bottom.
13472 // The point of exit cannot be a branch out of the structured block.
13473 // longjmp() and throw() must not violate the entry/exit criteria.
13474 CS->getCapturedDecl()->setNothrow();
13475 }
13476
13478 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13479 // define the nested loops number.
13480 unsigned NestedLoopCount =
13481 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13482 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13483 VarsWithImplicitDSA, B);
13484 if (NestedLoopCount == 0)
13485 return StmtError();
13486
13487 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13488 "omp target parallel for loop exprs were not built");
13489
13491 // Finalize the clauses that need pre-built expressions for CodeGen.
13492 for (OMPClause *C : Clauses) {
13493 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13494 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13497 return StmtError();
13498 }
13499 }
13500
13503 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13504 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13505}
13506
13507/// Check for existence of a map clause in the list of clauses.
13509 const OpenMPClauseKind K) {
13510 return llvm::any_of(
13511 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13512}
13513
13514template <typename... Params>
13516 const Params... ClauseTypes) {
13517 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13518}
13519
13520/// Check if the variables in the mapping clause are externally visible.
13522 for (const OMPClause *C : Clauses) {
13523 if (auto *TC = dyn_cast<OMPToClause>(C))
13524 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13525 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13526 (VD->isExternallyVisible() &&
13527 VD->getVisibility() != HiddenVisibility);
13528 });
13529 else if (auto *FC = dyn_cast<OMPFromClause>(C))
13530 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13531 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13532 (VD->isExternallyVisible() &&
13533 VD->getVisibility() != HiddenVisibility);
13534 });
13535 }
13536
13537 return true;
13538}
13539
13542 Stmt *AStmt, SourceLocation StartLoc,
13543 SourceLocation EndLoc) {
13544 if (!AStmt)
13545 return StmtError();
13546
13547 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13548
13549 // OpenMP [2.12.2, target data Construct, Restrictions]
13550 // At least one map, use_device_addr or use_device_ptr clause must appear on
13551 // the directive.
13552 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13553 (getLangOpts().OpenMP < 50 ||
13554 !hasClauses(Clauses, OMPC_use_device_addr))) {
13555 StringRef Expected;
13556 if (getLangOpts().OpenMP < 50)
13557 Expected = "'map' or 'use_device_ptr'";
13558 else
13559 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13560 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13561 << Expected << getOpenMPDirectiveName(OMPD_target_data);
13562 return StmtError();
13563 }
13564
13566
13567 return OMPTargetDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13568 Clauses, AStmt);
13569}
13570
13572 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13573 SourceLocation EndLoc, Stmt *AStmt) {
13574 if (!AStmt)
13575 return StmtError();
13576
13577 auto *CS = cast<CapturedStmt>(AStmt);
13578 // 1.2.2 OpenMP Language Terminology
13579 // Structured block - An executable statement with a single entry at the
13580 // top and a single exit at the bottom.
13581 // The point of exit cannot be a branch out of the structured block.
13582 // longjmp() and throw() must not violate the entry/exit criteria.
13583 CS->getCapturedDecl()->setNothrow();
13584 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_enter_data);
13585 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13586 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13587 // 1.2.2 OpenMP Language Terminology
13588 // Structured block - An executable statement with a single entry at the
13589 // top and a single exit at the bottom.
13590 // The point of exit cannot be a branch out of the structured block.
13591 // longjmp() and throw() must not violate the entry/exit criteria.
13592 CS->getCapturedDecl()->setNothrow();
13593 }
13594
13595 // OpenMP [2.10.2, Restrictions, p. 99]
13596 // At least one map clause must appear on the directive.
13597 if (!hasClauses(Clauses, OMPC_map)) {
13598 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13599 << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
13600 return StmtError();
13601 }
13602
13603 return OMPTargetEnterDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13604 Clauses, AStmt);
13605}
13606
13608 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13609 SourceLocation EndLoc, Stmt *AStmt) {
13610 if (!AStmt)
13611 return StmtError();
13612
13613 auto *CS = cast<CapturedStmt>(AStmt);
13614 // 1.2.2 OpenMP Language Terminology
13615 // Structured block - An executable statement with a single entry at the
13616 // top and a single exit at the bottom.
13617 // The point of exit cannot be a branch out of the structured block.
13618 // longjmp() and throw() must not violate the entry/exit criteria.
13619 CS->getCapturedDecl()->setNothrow();
13620 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_exit_data);
13621 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13622 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13623 // 1.2.2 OpenMP Language Terminology
13624 // Structured block - An executable statement with a single entry at the
13625 // top and a single exit at the bottom.
13626 // The point of exit cannot be a branch out of the structured block.
13627 // longjmp() and throw() must not violate the entry/exit criteria.
13628 CS->getCapturedDecl()->setNothrow();
13629 }
13630
13631 // OpenMP [2.10.3, Restrictions, p. 102]
13632 // At least one map clause must appear on the directive.
13633 if (!hasClauses(Clauses, OMPC_map)) {
13634 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13635 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
13636 return StmtError();
13637 }
13638
13639 return OMPTargetExitDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13640 Clauses, AStmt);
13641}
13642
13644 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13645 SourceLocation EndLoc, Stmt *AStmt) {
13646 if (!AStmt)
13647 return StmtError();
13648
13649 auto *CS = cast<CapturedStmt>(AStmt);
13650 // 1.2.2 OpenMP Language Terminology
13651 // Structured block - An executable statement with a single entry at the
13652 // top and a single exit at the bottom.
13653 // The point of exit cannot be a branch out of the structured block.
13654 // longjmp() and throw() must not violate the entry/exit criteria.
13655 CS->getCapturedDecl()->setNothrow();
13656 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_update);
13657 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13658 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13659 // 1.2.2 OpenMP Language Terminology
13660 // Structured block - An executable statement with a single entry at the
13661 // top and a single exit at the bottom.
13662 // The point of exit cannot be a branch out of the structured block.
13663 // longjmp() and throw() must not violate the entry/exit criteria.
13664 CS->getCapturedDecl()->setNothrow();
13665 }
13666
13667 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13668 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13669 return StmtError();
13670 }
13671
13672 if (!isClauseMappable(Clauses)) {
13673 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13674 return StmtError();
13675 }
13676
13677 return OMPTargetUpdateDirective::Create(getASTContext(), StartLoc, EndLoc,
13678 Clauses, AStmt);
13679}
13680
13682 Stmt *AStmt,
13683 SourceLocation StartLoc,
13684 SourceLocation EndLoc) {
13685 if (!AStmt)
13686 return StmtError();
13687
13688 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13689 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13690 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13691
13692 auto *CS = cast<CapturedStmt>(AStmt);
13693 // 1.2.2 OpenMP Language Terminology
13694 // Structured block - An executable statement with a single entry at the
13695 // top and a single exit at the bottom.
13696 // The point of exit cannot be a branch out of the structured block.
13697 // longjmp() and throw() must not violate the entry/exit criteria.
13698 CS->getCapturedDecl()->setNothrow();
13699
13701
13702 DSAStack->setParentTeamsRegionLoc(StartLoc);
13703
13704 return OMPTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13705 AStmt);
13706}
13707
13709 SourceLocation StartLoc, SourceLocation EndLoc,
13710 OpenMPDirectiveKind CancelRegion) {
13711 if (DSAStack->isParentNowaitRegion()) {
13712 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13713 return StmtError();
13714 }
13715 if (DSAStack->isParentOrderedRegion()) {
13716 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13717 return StmtError();
13718 }
13720 EndLoc, CancelRegion);
13721}
13722
13724 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13725 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13726 if (DSAStack->isParentNowaitRegion()) {
13727 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13728 return StmtError();
13729 }
13730 if (DSAStack->isParentOrderedRegion()) {
13731 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13732 return StmtError();
13733 }
13734 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13735 return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13736 CancelRegion);
13737}
13738
13740 ArrayRef<OMPClause *> Clauses) {
13741 const OMPClause *ReductionClause = nullptr;
13742 const OMPClause *NogroupClause = nullptr;
13743 for (const OMPClause *C : Clauses) {
13744 if (C->getClauseKind() == OMPC_reduction) {
13745 ReductionClause = C;
13746 if (NogroupClause)
13747 break;
13748 continue;
13749 }
13750 if (C->getClauseKind() == OMPC_nogroup) {
13751 NogroupClause = C;
13752 if (ReductionClause)
13753 break;
13754 continue;
13755 }
13756 }
13757 if (ReductionClause && NogroupClause) {
13758 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13759 << SourceRange(NogroupClause->getBeginLoc(),
13760 NogroupClause->getEndLoc());
13761 return true;
13762 }
13763 return false;
13764}
13765
13767 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13768 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13769 if (!AStmt)
13770 return StmtError();
13771
13772 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13774 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13775 // define the nested loops number.
13776 unsigned NestedLoopCount =
13777 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13778 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13779 *DSAStack, VarsWithImplicitDSA, B);
13780 if (NestedLoopCount == 0)
13781 return StmtError();
13782
13783 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13784 "omp for loop exprs were not built");
13785
13786 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13787 // The grainsize clause and num_tasks clause are mutually exclusive and may
13788 // not appear on the same taskloop directive.
13790 {OMPC_grainsize, OMPC_num_tasks}))
13791 return StmtError();
13792 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13793 // If a reduction clause is present on the taskloop directive, the nogroup
13794 // clause must not be specified.
13796 return StmtError();
13797
13799 return OMPTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13800 NestedLoopCount, Clauses, AStmt, B,
13801 DSAStack->isCancelRegion());
13802}
13803
13805 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13806 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13807 if (!AStmt)
13808 return StmtError();
13809
13810 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13812 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13813 // define the nested loops number.
13814 unsigned NestedLoopCount =
13815 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13816 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13817 *DSAStack, VarsWithImplicitDSA, B);
13818 if (NestedLoopCount == 0)
13819 return StmtError();
13820
13821 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13822 "omp for loop exprs were not built");
13823
13825 // Finalize the clauses that need pre-built expressions for CodeGen.
13826 for (OMPClause *C : Clauses) {
13827 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13828 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13831 return StmtError();
13832 }
13833 }
13834
13835 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13836 // The grainsize clause and num_tasks clause are mutually exclusive and may
13837 // not appear on the same taskloop directive.
13839 {OMPC_grainsize, OMPC_num_tasks}))
13840 return StmtError();
13841 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13842 // If a reduction clause is present on the taskloop directive, the nogroup
13843 // clause must not be specified.
13845 return StmtError();
13847 return StmtError();
13848
13850 return OMPTaskLoopSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13851 NestedLoopCount, Clauses, AStmt, B);
13852}
13853
13855 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13856 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13857 if (!AStmt)
13858 return StmtError();
13859
13860 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13862 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13863 // define the nested loops number.
13864 unsigned NestedLoopCount =
13865 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13866 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13867 *DSAStack, VarsWithImplicitDSA, B);
13868 if (NestedLoopCount == 0)
13869 return StmtError();
13870
13871 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13872 "omp for loop exprs were not built");
13873
13874 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13875 // The grainsize clause and num_tasks clause are mutually exclusive and may
13876 // not appear on the same taskloop directive.
13878 {OMPC_grainsize, OMPC_num_tasks}))
13879 return StmtError();
13880 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13881 // If a reduction clause is present on the taskloop directive, the nogroup
13882 // clause must not be specified.
13884 return StmtError();
13885
13887 return OMPMasterTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13888 NestedLoopCount, Clauses, AStmt, B,
13889 DSAStack->isCancelRegion());
13890}
13891
13893 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13894 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13895 if (!AStmt)
13896 return StmtError();
13897
13898 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13900 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13901 // define the nested loops number.
13902 unsigned NestedLoopCount =
13903 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13904 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13905 *DSAStack, VarsWithImplicitDSA, B);
13906 if (NestedLoopCount == 0)
13907 return StmtError();
13908
13909 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13910 "omp for loop exprs were not built");
13911
13912 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13913 // The grainsize clause and num_tasks clause are mutually exclusive and may
13914 // not appear on the same taskloop directive.
13916 {OMPC_grainsize, OMPC_num_tasks}))
13917 return StmtError();
13918 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13919 // If a reduction clause is present on the taskloop directive, the nogroup
13920 // clause must not be specified.
13922 return StmtError();
13923
13925 return OMPMaskedTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13926 NestedLoopCount, Clauses, AStmt, B,
13927 DSAStack->isCancelRegion());
13928}
13929
13931 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13932 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13933 if (!AStmt)
13934 return StmtError();
13935
13936 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13938 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13939 // define the nested loops number.
13940 unsigned NestedLoopCount =
13941 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13942 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13943 *DSAStack, VarsWithImplicitDSA, B);
13944 if (NestedLoopCount == 0)
13945 return StmtError();
13946
13947 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13948 "omp for loop exprs were not built");
13949
13951 // Finalize the clauses that need pre-built expressions for CodeGen.
13952 for (OMPClause *C : Clauses) {
13953 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13954 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13957 return StmtError();
13958 }
13959 }
13960
13961 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13962 // The grainsize clause and num_tasks clause are mutually exclusive and may
13963 // not appear on the same taskloop directive.
13965 {OMPC_grainsize, OMPC_num_tasks}))
13966 return StmtError();
13967 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13968 // If a reduction clause is present on the taskloop directive, the nogroup
13969 // clause must not be specified.
13971 return StmtError();
13973 return StmtError();
13974
13977 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13978}
13979
13981 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13982 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13983 if (!AStmt)
13984 return StmtError();
13985
13986 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13988 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13989 // define the nested loops number.
13990 unsigned NestedLoopCount =
13991 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13992 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13993 *DSAStack, VarsWithImplicitDSA, B);
13994 if (NestedLoopCount == 0)
13995 return StmtError();
13996
13997 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13998 "omp for loop exprs were not built");
13999
14001 // Finalize the clauses that need pre-built expressions for CodeGen.
14002 for (OMPClause *C : Clauses) {
14003 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14004 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14007 return StmtError();
14008 }
14009 }
14010
14011 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14012 // The grainsize clause and num_tasks clause are mutually exclusive and may
14013 // not appear on the same taskloop directive.
14015 {OMPC_grainsize, OMPC_num_tasks}))
14016 return StmtError();
14017 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14018 // If a reduction clause is present on the taskloop directive, the nogroup
14019 // clause must not be specified.
14021 return StmtError();
14023 return StmtError();
14024
14027 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14028}
14029
14031 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14032 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14033 if (!AStmt)
14034 return StmtError();
14035
14036 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14037 auto *CS = cast<CapturedStmt>(AStmt);
14038 // 1.2.2 OpenMP Language Terminology
14039 // Structured block - An executable statement with a single entry at the
14040 // top and a single exit at the bottom.
14041 // The point of exit cannot be a branch out of the structured block.
14042 // longjmp() and throw() must not violate the entry/exit criteria.
14043 CS->getCapturedDecl()->setNothrow();
14044 for (int ThisCaptureLevel =
14045 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop);
14046 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14047 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14048 // 1.2.2 OpenMP Language Terminology
14049 // Structured block - An executable statement with a single entry at the
14050 // top and a single exit at the bottom.
14051 // The point of exit cannot be a branch out of the structured block.
14052 // longjmp() and throw() must not violate the entry/exit criteria.
14053 CS->getCapturedDecl()->setNothrow();
14054 }
14055
14057 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14058 // define the nested loops number.
14059 unsigned NestedLoopCount = checkOpenMPLoop(
14060 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
14061 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
14062 VarsWithImplicitDSA, B);
14063 if (NestedLoopCount == 0)
14064 return StmtError();
14065
14066 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14067 "omp for loop exprs were not built");
14068
14069 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14070 // The grainsize clause and num_tasks clause are mutually exclusive and may
14071 // not appear on the same taskloop directive.
14073 {OMPC_grainsize, OMPC_num_tasks}))
14074 return StmtError();
14075 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14076 // If a reduction clause is present on the taskloop directive, the nogroup
14077 // clause must not be specified.
14079 return StmtError();
14080
14083 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14084 DSAStack->isCancelRegion());
14085}
14086
14088 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14089 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14090 if (!AStmt)
14091 return StmtError();
14092
14093 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14094 auto *CS = cast<CapturedStmt>(AStmt);
14095 // 1.2.2 OpenMP Language Terminology
14096 // Structured block - An executable statement with a single entry at the
14097 // top and a single exit at the bottom.
14098 // The point of exit cannot be a branch out of the structured block.
14099 // longjmp() and throw() must not violate the entry/exit criteria.
14100 CS->getCapturedDecl()->setNothrow();
14101 for (int ThisCaptureLevel =
14102 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop);
14103 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14104 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14105 // 1.2.2 OpenMP Language Terminology
14106 // Structured block - An executable statement with a single entry at the
14107 // top and a single exit at the bottom.
14108 // The point of exit cannot be a branch out of the structured block.
14109 // longjmp() and throw() must not violate the entry/exit criteria.
14110 CS->getCapturedDecl()->setNothrow();
14111 }
14112
14114 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14115 // define the nested loops number.
14116 unsigned NestedLoopCount = checkOpenMPLoop(
14117 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
14118 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
14119 VarsWithImplicitDSA, B);
14120 if (NestedLoopCount == 0)
14121 return StmtError();
14122
14123 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14124 "omp for loop exprs were not built");
14125
14126 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14127 // The grainsize clause and num_tasks clause are mutually exclusive and may
14128 // not appear on the same taskloop directive.
14130 {OMPC_grainsize, OMPC_num_tasks}))
14131 return StmtError();
14132 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14133 // If a reduction clause is present on the taskloop directive, the nogroup
14134 // clause must not be specified.
14136 return StmtError();
14137
14140 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14141 DSAStack->isCancelRegion());
14142}
14143
14145 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14146 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14147 if (!AStmt)
14148 return StmtError();
14149
14150 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14151 auto *CS = cast<CapturedStmt>(AStmt);
14152 // 1.2.2 OpenMP Language Terminology
14153 // Structured block - An executable statement with a single entry at the
14154 // top and a single exit at the bottom.
14155 // The point of exit cannot be a branch out of the structured block.
14156 // longjmp() and throw() must not violate the entry/exit criteria.
14157 CS->getCapturedDecl()->setNothrow();
14158 for (int ThisCaptureLevel =
14159 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop_simd);
14160 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14161 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14162 // 1.2.2 OpenMP Language Terminology
14163 // Structured block - An executable statement with a single entry at the
14164 // top and a single exit at the bottom.
14165 // The point of exit cannot be a branch out of the structured block.
14166 // longjmp() and throw() must not violate the entry/exit criteria.
14167 CS->getCapturedDecl()->setNothrow();
14168 }
14169
14171 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14172 // define the nested loops number.
14173 unsigned NestedLoopCount = checkOpenMPLoop(
14174 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
14175 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
14176 VarsWithImplicitDSA, B);
14177 if (NestedLoopCount == 0)
14178 return StmtError();
14179
14180 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14181 "omp for loop exprs were not built");
14182
14184 // Finalize the clauses that need pre-built expressions for CodeGen.
14185 for (OMPClause *C : Clauses) {
14186 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14187 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14190 return StmtError();
14191 }
14192 }
14193
14194 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14195 // The grainsize clause and num_tasks clause are mutually exclusive and may
14196 // not appear on the same taskloop directive.
14198 {OMPC_grainsize, OMPC_num_tasks}))
14199 return StmtError();
14200 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14201 // If a reduction clause is present on the taskloop directive, the nogroup
14202 // clause must not be specified.
14204 return StmtError();
14206 return StmtError();
14207
14210 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14211}
14212
14214 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14215 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14216 if (!AStmt)
14217 return StmtError();
14218
14219 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14220 auto *CS = cast<CapturedStmt>(AStmt);
14221 // 1.2.2 OpenMP Language Terminology
14222 // Structured block - An executable statement with a single entry at the
14223 // top and a single exit at the bottom.
14224 // The point of exit cannot be a branch out of the structured block.
14225 // longjmp() and throw() must not violate the entry/exit criteria.
14226 CS->getCapturedDecl()->setNothrow();
14227 for (int ThisCaptureLevel =
14228 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop_simd);
14229 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14230 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14231 // 1.2.2 OpenMP Language Terminology
14232 // Structured block - An executable statement with a single entry at the
14233 // top and a single exit at the bottom.
14234 // The point of exit cannot be a branch out of the structured block.
14235 // longjmp() and throw() must not violate the entry/exit criteria.
14236 CS->getCapturedDecl()->setNothrow();
14237 }
14238
14240 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14241 // define the nested loops number.
14242 unsigned NestedLoopCount = checkOpenMPLoop(
14243 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
14244 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
14245 VarsWithImplicitDSA, B);
14246 if (NestedLoopCount == 0)
14247 return StmtError();
14248
14249 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14250 "omp for loop exprs were not built");
14251
14253 // Finalize the clauses that need pre-built expressions for CodeGen.
14254 for (OMPClause *C : Clauses) {
14255 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14256 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14259 return StmtError();
14260 }
14261 }
14262
14263 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14264 // The grainsize clause and num_tasks clause are mutually exclusive and may
14265 // not appear on the same taskloop directive.
14267 {OMPC_grainsize, OMPC_num_tasks}))
14268 return StmtError();
14269 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14270 // If a reduction clause is present on the taskloop directive, the nogroup
14271 // clause must not be specified.
14273 return StmtError();
14275 return StmtError();
14276
14279 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14280}
14281
14283 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14284 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14285 if (!AStmt)
14286 return StmtError();
14287
14288 if (!checkLastPrivateForMappedDirectives(Clauses))
14289 return StmtError();
14290
14291 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14293 // In presence of clause 'collapse' with number of loops, it will
14294 // define the nested loops number.
14295 unsigned NestedLoopCount =
14296 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
14297 nullptr /*ordered not a clause on distribute*/, AStmt,
14298 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14299 if (NestedLoopCount == 0)
14300 return StmtError();
14301
14302 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14303 "omp for loop exprs were not built");
14304
14306 auto *DistributeDirective = OMPDistributeDirective::Create(
14307 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14308 DSAStack->getMappedDirective());
14309 return DistributeDirective;
14310}
14311
14313 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14314 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14315 if (!AStmt)
14316 return StmtError();
14317
14318 auto *CS = cast<CapturedStmt>(AStmt);
14319 // 1.2.2 OpenMP Language Terminology
14320 // Structured block - An executable statement with a single entry at the
14321 // top and a single exit at the bottom.
14322 // The point of exit cannot be a branch out of the structured block.
14323 // longjmp() and throw() must not violate the entry/exit criteria.
14324 CS->getCapturedDecl()->setNothrow();
14325 for (int ThisCaptureLevel =
14326 getOpenMPCaptureLevels(OMPD_distribute_parallel_for);
14327 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14328 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14329 // 1.2.2 OpenMP Language Terminology
14330 // Structured block - An executable statement with a single entry at the
14331 // top and a single exit at the bottom.
14332 // The point of exit cannot be a branch out of the structured block.
14333 // longjmp() and throw() must not violate the entry/exit criteria.
14334 CS->getCapturedDecl()->setNothrow();
14335 }
14336
14338 // In presence of clause 'collapse' with number of loops, it will
14339 // define the nested loops number.
14340 unsigned NestedLoopCount = checkOpenMPLoop(
14341 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14342 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14343 VarsWithImplicitDSA, B);
14344 if (NestedLoopCount == 0)
14345 return StmtError();
14346
14347 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14348 "omp for loop exprs were not built");
14349
14352 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14353 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
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_distribute_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' with number of loops, it will
14383 // define the nested loops number.
14384 unsigned NestedLoopCount = checkOpenMPLoop(
14385 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14386 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14387 VarsWithImplicitDSA, B);
14388 if (NestedLoopCount == 0)
14389 return StmtError();
14390
14391 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14392 "omp for 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),
14401 return StmtError();
14402 }
14403 }
14404
14406 return StmtError();
14407
14410 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14411}
14412
14414 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14415 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14416 if (!AStmt)
14417 return StmtError();
14418
14419 auto *CS = cast<CapturedStmt>(AStmt);
14420 // 1.2.2 OpenMP Language Terminology
14421 // Structured block - An executable statement with a single entry at the
14422 // top and a single exit at the bottom.
14423 // The point of exit cannot be a branch out of the structured block.
14424 // longjmp() and throw() must not violate the entry/exit criteria.
14425 CS->getCapturedDecl()->setNothrow();
14426 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_distribute_simd);
14427 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14428 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14429 // 1.2.2 OpenMP Language Terminology
14430 // Structured block - An executable statement with a single entry at the
14431 // top and a single exit at the bottom.
14432 // The point of exit cannot be a branch out of the structured block.
14433 // longjmp() and throw() must not violate the entry/exit criteria.
14434 CS->getCapturedDecl()->setNothrow();
14435 }
14436
14438 // In presence of clause 'collapse' with number of loops, it will
14439 // define the nested loops number.
14440 unsigned NestedLoopCount =
14441 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
14442 nullptr /*ordered not a clause on distribute*/, CS,
14443 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14444 if (NestedLoopCount == 0)
14445 return StmtError();
14446
14447 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14448 "omp for loop exprs were not built");
14449
14451 // Finalize the clauses that need pre-built expressions for CodeGen.
14452 for (OMPClause *C : Clauses) {
14453 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14454 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14457 return StmtError();
14458 }
14459 }
14460
14462 return StmtError();
14463
14465 return OMPDistributeSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
14466 NestedLoopCount, Clauses, AStmt, B);
14467}
14468
14470 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14471 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14472 if (!AStmt)
14473 return StmtError();
14474
14475 auto *CS = cast<CapturedStmt>(AStmt);
14476 // 1.2.2 OpenMP Language Terminology
14477 // Structured block - An executable statement with a single entry at the
14478 // top and a single exit at the bottom.
14479 // The point of exit cannot be a branch out of the structured block.
14480 // longjmp() and throw() must not violate the entry/exit criteria.
14481 CS->getCapturedDecl()->setNothrow();
14482 for (int ThisCaptureLevel =
14483 getOpenMPCaptureLevels(OMPD_target_parallel_for_simd);
14484 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14485 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14486 // 1.2.2 OpenMP Language Terminology
14487 // Structured block - An executable statement with a single entry at the
14488 // top and a single exit at the bottom.
14489 // The point of exit cannot be a branch out of the structured block.
14490 // longjmp() and throw() must not violate the entry/exit criteria.
14491 CS->getCapturedDecl()->setNothrow();
14492 }
14493
14495 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14496 // define the nested loops number.
14497 unsigned NestedLoopCount = checkOpenMPLoop(
14498 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
14499 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
14500 VarsWithImplicitDSA, B);
14501 if (NestedLoopCount == 0)
14502 return StmtError();
14503
14504 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14505 "omp target parallel for simd loop exprs were not built");
14506
14508 // Finalize the clauses that need pre-built expressions for CodeGen.
14509 for (OMPClause *C : Clauses) {
14510 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14511 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14514 return StmtError();
14515 }
14516 }
14518 return StmtError();
14519
14522 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14523}
14524
14526 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14527 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14528 if (!AStmt)
14529 return StmtError();
14530
14531 auto *CS = cast<CapturedStmt>(AStmt);
14532 // 1.2.2 OpenMP Language Terminology
14533 // Structured block - An executable statement with a single entry at the
14534 // top and a single exit at the bottom.
14535 // The point of exit cannot be a branch out of the structured block.
14536 // longjmp() and throw() must not violate the entry/exit criteria.
14537 CS->getCapturedDecl()->setNothrow();
14538 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_simd);
14539 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14540 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14541 // 1.2.2 OpenMP Language Terminology
14542 // Structured block - An executable statement with a single entry at the
14543 // top and a single exit at the bottom.
14544 // The point of exit cannot be a branch out of the structured block.
14545 // longjmp() and throw() must not violate the entry/exit criteria.
14546 CS->getCapturedDecl()->setNothrow();
14547 }
14548
14550 // In presence of clause 'collapse' with number of loops, it will define the
14551 // nested loops number.
14552 unsigned NestedLoopCount =
14553 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
14554 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
14555 VarsWithImplicitDSA, B);
14556 if (NestedLoopCount == 0)
14557 return StmtError();
14558
14559 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14560 "omp target simd loop exprs were not built");
14561
14563 // Finalize the clauses that need pre-built expressions for CodeGen.
14564 for (OMPClause *C : Clauses) {
14565 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14566 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14569 return StmtError();
14570 }
14571 }
14572
14574 return StmtError();
14575
14577 return OMPTargetSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
14578 NestedLoopCount, Clauses, AStmt, B);
14579}
14580
14582 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14583 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14584 if (!AStmt)
14585 return StmtError();
14586
14587 auto *CS = cast<CapturedStmt>(AStmt);
14588 // 1.2.2 OpenMP Language Terminology
14589 // Structured block - An executable statement with a single entry at the
14590 // top and a single exit at the bottom.
14591 // The point of exit cannot be a branch out of the structured block.
14592 // longjmp() and throw() must not violate the entry/exit criteria.
14593 CS->getCapturedDecl()->setNothrow();
14594 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_distribute);
14595 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14596 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14597 // 1.2.2 OpenMP Language Terminology
14598 // Structured block - An executable statement with a single entry at the
14599 // top and a single exit at the bottom.
14600 // The point of exit cannot be a branch out of the structured block.
14601 // longjmp() and throw() must not violate the entry/exit criteria.
14602 CS->getCapturedDecl()->setNothrow();
14603 }
14604
14606 // In presence of clause 'collapse' with number of loops, it will
14607 // define the nested loops number.
14608 unsigned NestedLoopCount =
14609 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
14610 nullptr /*ordered not a clause on distribute*/, CS,
14611 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14612 if (NestedLoopCount == 0)
14613 return StmtError();
14614
14615 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14616 "omp teams distribute loop exprs were not built");
14617
14619
14620 DSAStack->setParentTeamsRegionLoc(StartLoc);
14621
14623 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14624}
14625
14627 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14628 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14629 if (!AStmt)
14630 return StmtError();
14631
14632 auto *CS = cast<CapturedStmt>(AStmt);
14633 // 1.2.2 OpenMP Language Terminology
14634 // Structured block - An executable statement with a single entry at the
14635 // top and a single exit at the bottom.
14636 // The point of exit cannot be a branch out of the structured block.
14637 // longjmp() and throw() must not violate the entry/exit criteria.
14638 CS->getCapturedDecl()->setNothrow();
14639 for (int ThisCaptureLevel =
14640 getOpenMPCaptureLevels(OMPD_teams_distribute_simd);
14641 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14642 CS = cast<CapturedStmt>(CS->getCapturedStmt());
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
14652 // In presence of clause 'collapse' with number of loops, it will
14653 // define the nested loops number.
14654 unsigned NestedLoopCount = checkOpenMPLoop(
14655 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14656 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14657 VarsWithImplicitDSA, B);
14658
14659 if (NestedLoopCount == 0)
14660 return StmtError();
14661
14662 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14663 "omp teams distribute simd loop exprs were not built");
14664
14666 // Finalize the clauses that need pre-built expressions for CodeGen.
14667 for (OMPClause *C : Clauses) {
14668 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14669 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14672 return StmtError();
14673 }
14674 }
14675
14677 return StmtError();
14678
14680
14681 DSAStack->setParentTeamsRegionLoc(StartLoc);
14682
14684 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14685}
14686
14688 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14689 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14690 if (!AStmt)
14691 return StmtError();
14692
14693 auto *CS = cast<CapturedStmt>(AStmt);
14694 // 1.2.2 OpenMP Language Terminology
14695 // Structured block - An executable statement with a single entry at the
14696 // top and a single exit at the bottom.
14697 // The point of exit cannot be a branch out of the structured block.
14698 // longjmp() and throw() must not violate the entry/exit criteria.
14699 CS->getCapturedDecl()->setNothrow();
14700
14701 for (int ThisCaptureLevel =
14702 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for_simd);
14703 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14704 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14705 // 1.2.2 OpenMP Language Terminology
14706 // Structured block - An executable statement with a single entry at the
14707 // top and a single exit at the bottom.
14708 // The point of exit cannot be a branch out of the structured block.
14709 // longjmp() and throw() must not violate the entry/exit criteria.
14710 CS->getCapturedDecl()->setNothrow();
14711 }
14712
14714 // In presence of clause 'collapse' with number of loops, it will
14715 // define the nested loops number.
14716 unsigned NestedLoopCount = checkOpenMPLoop(
14717 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14718 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14719 VarsWithImplicitDSA, B);
14720
14721 if (NestedLoopCount == 0)
14722 return StmtError();
14723
14724 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14725 "omp for loop exprs were not built");
14726
14728 // Finalize the clauses that need pre-built expressions for CodeGen.
14729 for (OMPClause *C : Clauses) {
14730 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14731 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14734 return StmtError();
14735 }
14736 }
14737
14739 return StmtError();
14740
14742
14743 DSAStack->setParentTeamsRegionLoc(StartLoc);
14744
14746 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14747}
14748
14750 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14751 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14752 if (!AStmt)
14753 return StmtError();
14754
14755 auto *CS = cast<CapturedStmt>(AStmt);
14756 // 1.2.2 OpenMP Language Terminology
14757 // Structured block - An executable statement with a single entry at the
14758 // top and a single exit at the bottom.
14759 // The point of exit cannot be a branch out of the structured block.
14760 // longjmp() and throw() must not violate the entry/exit criteria.
14761 CS->getCapturedDecl()->setNothrow();
14762
14763 for (int ThisCaptureLevel =
14764 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for);
14765 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14766 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14767 // 1.2.2 OpenMP Language Terminology
14768 // Structured block - An executable statement with a single entry at the
14769 // top and a single exit at the bottom.
14770 // The point of exit cannot be a branch out of the structured block.
14771 // longjmp() and throw() must not violate the entry/exit criteria.
14772 CS->getCapturedDecl()->setNothrow();
14773 }
14774
14776 // In presence of clause 'collapse' with number of loops, it will
14777 // define the nested loops number.
14778 unsigned NestedLoopCount = checkOpenMPLoop(
14779 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14780 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14781 VarsWithImplicitDSA, B);
14782
14783 if (NestedLoopCount == 0)
14784 return StmtError();
14785
14786 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14787 "omp for loop exprs were not built");
14788
14790
14791 DSAStack->setParentTeamsRegionLoc(StartLoc);
14792
14794 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14795 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14796}
14797
14799 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14800 SourceLocation EndLoc) {
14801 if (!AStmt)
14802 return StmtError();
14803
14804 auto *CS = cast<CapturedStmt>(AStmt);
14805 // 1.2.2 OpenMP Language Terminology
14806 // Structured block - An executable statement with a single entry at the
14807 // top and a single exit at the bottom.
14808 // The point of exit cannot be a branch out of the structured block.
14809 // longjmp() and throw() must not violate the entry/exit criteria.
14810 CS->getCapturedDecl()->setNothrow();
14811
14812 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams);
14813 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14814 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14815 // 1.2.2 OpenMP Language Terminology
14816 // Structured block - An executable statement with a single entry at the
14817 // top and a single exit at the bottom.
14818 // The point of exit cannot be a branch out of the structured block.
14819 // longjmp() and throw() must not violate the entry/exit criteria.
14820 CS->getCapturedDecl()->setNothrow();
14821 }
14823
14824 const OMPClause *BareClause = nullptr;
14825 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) &&
14826 hasClauses(Clauses, OMPC_thread_limit);
14827 bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) {
14828 BareClause = C;
14829 return C->getClauseKind() == OMPC_ompx_bare;
14830 });
14831
14832 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14833 Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
14834 return StmtError();
14835 }
14836
14837 return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc,
14838 Clauses, AStmt);
14839}
14840
14842 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14843 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14844 if (!AStmt)
14845 return StmtError();
14846
14847 auto *CS = cast<CapturedStmt>(AStmt);
14848 // 1.2.2 OpenMP Language Terminology
14849 // Structured block - An executable statement with a single entry at the
14850 // top and a single exit at the bottom.
14851 // The point of exit cannot be a branch out of the structured block.
14852 // longjmp() and throw() must not violate the entry/exit criteria.
14853 CS->getCapturedDecl()->setNothrow();
14854 for (int ThisCaptureLevel =
14855 getOpenMPCaptureLevels(OMPD_target_teams_distribute);
14856 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14857 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14858 // 1.2.2 OpenMP Language Terminology
14859 // Structured block - An executable statement with a single entry at the
14860 // top and a single exit at the bottom.
14861 // The point of exit cannot be a branch out of the structured block.
14862 // longjmp() and throw() must not violate the entry/exit criteria.
14863 CS->getCapturedDecl()->setNothrow();
14864 }
14865
14867 // In presence of clause 'collapse' with number of loops, it will
14868 // define the nested loops number.
14869 unsigned NestedLoopCount = checkOpenMPLoop(
14870 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14871 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14872 VarsWithImplicitDSA, B);
14873 if (NestedLoopCount == 0)
14874 return StmtError();
14875
14876 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14877 "omp target teams distribute loop exprs were not built");
14878
14881 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14882}
14883
14885 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14886 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14887 if (!AStmt)
14888 return StmtError();
14889
14890 auto *CS = cast<CapturedStmt>(AStmt);
14891 // 1.2.2 OpenMP Language Terminology
14892 // Structured block - An executable statement with a single entry at the
14893 // top and a single exit at the bottom.
14894 // The point of exit cannot be a branch out of the structured block.
14895 // longjmp() and throw() must not violate the entry/exit criteria.
14896 CS->getCapturedDecl()->setNothrow();
14897 for (int ThisCaptureLevel =
14898 getOpenMPCaptureLevels(OMPD_target_teams_distribute_parallel_for);
14899 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14900 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14901 // 1.2.2 OpenMP Language Terminology
14902 // Structured block - An executable statement with a single entry at the
14903 // top and a single exit at the bottom.
14904 // The point of exit cannot be a branch out of the structured block.
14905 // longjmp() and throw() must not violate the entry/exit criteria.
14906 CS->getCapturedDecl()->setNothrow();
14907 }
14908
14910 // In presence of clause 'collapse' with number of loops, it will
14911 // define the nested loops number.
14912 unsigned NestedLoopCount = checkOpenMPLoop(
14913 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14914 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14915 VarsWithImplicitDSA, B);
14916 if (NestedLoopCount == 0)
14917 return StmtError();
14918
14919 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14920 "omp target teams distribute parallel for loop exprs were not built");
14921
14923 // Finalize the clauses that need pre-built expressions for CodeGen.
14924 for (OMPClause *C : Clauses) {
14925 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14926 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14929 return StmtError();
14930 }
14931 }
14932
14935 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14936 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14937}
14938
14940 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14941 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14942 if (!AStmt)
14943 return StmtError();
14944
14945 auto *CS = cast<CapturedStmt>(AStmt);
14946 // 1.2.2 OpenMP Language Terminology
14947 // Structured block - An executable statement with a single entry at the
14948 // top and a single exit at the bottom.
14949 // The point of exit cannot be a branch out of the structured block.
14950 // longjmp() and throw() must not violate the entry/exit criteria.
14951 CS->getCapturedDecl()->setNothrow();
14952 for (int ThisCaptureLevel = getOpenMPCaptureLevels(
14953 OMPD_target_teams_distribute_parallel_for_simd);
14954 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14955 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14956 // 1.2.2 OpenMP Language Terminology
14957 // Structured block - An executable statement with a single entry at the
14958 // top and a single exit at the bottom.
14959 // The point of exit cannot be a branch out of the structured block.
14960 // longjmp() and throw() must not violate the entry/exit criteria.
14961 CS->getCapturedDecl()->setNothrow();
14962 }
14963
14965 // In presence of clause 'collapse' with number of loops, it will
14966 // define the nested loops number.
14967 unsigned NestedLoopCount =
14968 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14969 getCollapseNumberExpr(Clauses),
14970 nullptr /*ordered not a clause on distribute*/, CS,
14971 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14972 if (NestedLoopCount == 0)
14973 return StmtError();
14974
14975 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14976 "omp target teams distribute parallel for simd loop exprs were not "
14977 "built");
14978
14980 // Finalize the clauses that need pre-built expressions for CodeGen.
14981 for (OMPClause *C : Clauses) {
14982 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14983 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14986 return StmtError();
14987 }
14988 }
14989
14991 return StmtError();
14992
14995 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14996}
14997
14999 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15000 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15001 if (!AStmt)
15002 return StmtError();
15003
15004 auto *CS = cast<CapturedStmt>(AStmt);
15005 // 1.2.2 OpenMP Language Terminology
15006 // Structured block - An executable statement with a single entry at the
15007 // top and a single exit at the bottom.
15008 // The point of exit cannot be a branch out of the structured block.
15009 // longjmp() and throw() must not violate the entry/exit criteria.
15010 CS->getCapturedDecl()->setNothrow();
15011 for (int ThisCaptureLevel =
15012 getOpenMPCaptureLevels(OMPD_target_teams_distribute_simd);
15013 ThisCaptureLevel > 1; --ThisCaptureLevel) {
15014 CS = cast<CapturedStmt>(CS->getCapturedStmt());
15015 // 1.2.2 OpenMP Language Terminology
15016 // Structured block - An executable statement with a single entry at the
15017 // top and a single exit at the bottom.
15018 // The point of exit cannot be a branch out of the structured block.
15019 // longjmp() and throw() must not violate the entry/exit criteria.
15020 CS->getCapturedDecl()->setNothrow();
15021 }
15022
15024 // In presence of clause 'collapse' with number of loops, it will
15025 // define the nested loops number.
15026 unsigned NestedLoopCount = checkOpenMPLoop(
15027 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
15028 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
15029 VarsWithImplicitDSA, B);
15030 if (NestedLoopCount == 0)
15031 return StmtError();
15032
15033 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
15034 "omp target teams distribute simd loop exprs were not built");
15035
15037 // Finalize the clauses that need pre-built expressions for CodeGen.
15038 for (OMPClause *C : Clauses) {
15039 if (auto *LC = dyn_cast<OMPLinearClause>(C))
15040 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
15043 return StmtError();
15044 }
15045 }
15046
15048 return StmtError();
15049
15052 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15053}
15054
15055bool SemaOpenMP::checkTransformableLoopNest(
15056 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
15058 Stmt *&Body,
15059 SmallVectorImpl<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>>
15060 &OriginalInits) {
15061 OriginalInits.emplace_back();
15063 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
15064 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
15065 Stmt *CurStmt) {
15066 VarsWithInheritedDSAType TmpDSA;
15067 unsigned SingleNumLoops =
15068 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
15069 TmpDSA, LoopHelpers[Cnt]);
15070 if (SingleNumLoops == 0)
15071 return true;
15072 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
15073 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
15074 OriginalInits.back().push_back(For->getInit());
15075 Body = For->getBody();
15076 } else {
15077 assert(isa<CXXForRangeStmt>(CurStmt) &&
15078 "Expected canonical for or range-based for loops.");
15079 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
15080 OriginalInits.back().push_back(CXXFor->getBeginStmt());
15081 Body = CXXFor->getBody();
15082 }
15083 OriginalInits.emplace_back();
15084 return false;
15085 },
15086 [&OriginalInits](OMPLoopBasedDirective *Transform) {
15087 Stmt *DependentPreInits;
15088 if (auto *Dir = dyn_cast<OMPTileDirective>(Transform))
15089 DependentPreInits = Dir->getPreInits();
15090 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
15091 DependentPreInits = Dir->getPreInits();
15092 else
15093 llvm_unreachable("Unhandled loop transformation");
15094 if (!DependentPreInits)
15095 return;
15096 llvm::append_range(OriginalInits.back(),
15097 cast<DeclStmt>(DependentPreInits)->getDeclGroup());
15098 });
15099 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
15100 OriginalInits.pop_back();
15101 return Result;
15102}
15103
15105 Stmt *AStmt,
15106 SourceLocation StartLoc,
15107 SourceLocation EndLoc) {
15108 ASTContext &Context = getASTContext();
15109 auto SizesClauses =
15110 OMPExecutableDirective::getClausesOfKind<OMPSizesClause>(Clauses);
15111 if (SizesClauses.empty()) {
15112 // A missing 'sizes' clause is already reported by the parser.
15113 return StmtError();
15114 }
15115 const OMPSizesClause *SizesClause = *SizesClauses.begin();
15116 unsigned NumLoops = SizesClause->getNumSizes();
15117
15118 // Empty statement should only be possible if there already was an error.
15119 if (!AStmt)
15120 return StmtError();
15121
15122 // Verify and diagnose loop nest.
15124 Stmt *Body = nullptr;
15126 OriginalInits;
15127 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
15128 OriginalInits))
15129 return StmtError();
15130
15131 // Delay tiling to when template is completely instantiated.
15133 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
15134 NumLoops, AStmt, nullptr, nullptr);
15135
15136 SmallVector<Decl *, 4> PreInits;
15137
15138 // Create iteration variables for the generated loops.
15139 SmallVector<VarDecl *, 4> FloorIndVars;
15140 SmallVector<VarDecl *, 4> TileIndVars;
15141 FloorIndVars.resize(NumLoops);
15142 TileIndVars.resize(NumLoops);
15143 for (unsigned I = 0; I < NumLoops; ++I) {
15144 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15145
15146 assert(LoopHelper.Counters.size() == 1 &&
15147 "Expect single-dimensional loop iteration space");
15148 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15149 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15150 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15151 QualType CntTy = IterVarRef->getType();
15152
15153 // Iteration variable for the floor (i.e. outer) loop.
15154 {
15155 std::string FloorCntName =
15156 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15157 VarDecl *FloorCntDecl =
15158 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
15159 FloorIndVars[I] = FloorCntDecl;
15160 }
15161
15162 // Iteration variable for the tile (i.e. inner) loop.
15163 {
15164 std::string TileCntName =
15165 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15166
15167 // Reuse the iteration variable created by checkOpenMPLoop. It is also
15168 // used by the expressions to derive the original iteration variable's
15169 // value from the logical iteration number.
15170 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15171 TileCntDecl->setDeclName(
15172 &SemaRef.PP.getIdentifierTable().get(TileCntName));
15173 TileIndVars[I] = TileCntDecl;
15174 }
15175 for (auto &P : OriginalInits[I]) {
15176 if (auto *D = P.dyn_cast<Decl *>())
15177 PreInits.push_back(D);
15178 else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
15179 PreInits.append(PI->decl_begin(), PI->decl_end());
15180 }
15181 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
15182 PreInits.append(PI->decl_begin(), PI->decl_end());
15183 // Gather declarations for the data members used as counters.
15184 for (Expr *CounterRef : LoopHelper.Counters) {
15185 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
15186 if (isa<OMPCapturedExprDecl>(CounterDecl))
15187 PreInits.push_back(CounterDecl);
15188 }
15189 }
15190
15191 // Once the original iteration values are set, append the innermost body.
15192 Stmt *Inner = Body;
15193
15194 // Create tile loops from the inside to the outside.
15195 for (int I = NumLoops - 1; I >= 0; --I) {
15196 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15197 Expr *NumIterations = LoopHelper.NumIterations;
15198 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15199 QualType CntTy = OrigCntVar->getType();
15200 Expr *DimTileSize = SizesClause->getSizesRefs()[I];
15201 Scope *CurScope = SemaRef.getCurScope();
15202
15203 // Commonly used variables.
15204 DeclRefExpr *TileIV = buildDeclRefExpr(SemaRef, TileIndVars[I], CntTy,
15205 OrigCntVar->getExprLoc());
15206 DeclRefExpr *FloorIV = buildDeclRefExpr(SemaRef, FloorIndVars[I], CntTy,
15207 OrigCntVar->getExprLoc());
15208
15209 // For init-statement: auto .tile.iv = .floor.iv
15210 SemaRef.AddInitializerToDecl(TileIndVars[I],
15212 /*DirectInit=*/false);
15213 Decl *CounterDecl = TileIndVars[I];
15214 StmtResult InitStmt = new (Context)
15215 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15216 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15217 if (!InitStmt.isUsable())
15218 return StmtError();
15219
15220 // For cond-expression: .tile.iv < min(.floor.iv + DimTileSize,
15221 // NumIterations)
15222 ExprResult EndOfTile = SemaRef.BuildBinOp(
15223 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add, FloorIV, DimTileSize);
15224 if (!EndOfTile.isUsable())
15225 return StmtError();
15226 ExprResult IsPartialTile =
15227 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15228 NumIterations, EndOfTile.get());
15229 if (!IsPartialTile.isUsable())
15230 return StmtError();
15231 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
15232 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15233 IsPartialTile.get(), NumIterations, EndOfTile.get());
15234 if (!MinTileAndIterSpace.isUsable())
15235 return StmtError();
15236 ExprResult CondExpr =
15237 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15238 TileIV, MinTileAndIterSpace.get());
15239 if (!CondExpr.isUsable())
15240 return StmtError();
15241
15242 // For incr-statement: ++.tile.iv
15243 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15244 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, TileIV);
15245 if (!IncrStmt.isUsable())
15246 return StmtError();
15247
15248 // Statements to set the original iteration variable's value from the
15249 // logical iteration number.
15250 // Generated for loop is:
15251 // Original_for_init;
15252 // for (auto .tile.iv = .floor.iv; .tile.iv < min(.floor.iv + DimTileSize,
15253 // NumIterations); ++.tile.iv) {
15254 // Original_Body;
15255 // Original_counter_update;
15256 // }
15257 // FIXME: If the innermost body is an loop itself, inserting these
15258 // statements stops it being recognized as a perfectly nested loop (e.g.
15259 // for applying tiling again). If this is the case, sink the expressions
15260 // further into the inner loop.
15261 SmallVector<Stmt *, 4> BodyParts;
15262 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15263 BodyParts.push_back(Inner);
15264 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15265 Inner->getBeginLoc(), Inner->getEndLoc());
15266 Inner = new (Context)
15267 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15268 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15269 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15270 }
15271
15272 // Create floor loops from the inside to the outside.
15273 for (int I = NumLoops - 1; I >= 0; --I) {
15274 auto &LoopHelper = LoopHelpers[I];
15275 Expr *NumIterations = LoopHelper.NumIterations;
15276 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15277 QualType CntTy = OrigCntVar->getType();
15278 Expr *DimTileSize = SizesClause->getSizesRefs()[I];
15279 Scope *CurScope = SemaRef.getCurScope();
15280
15281 // Commonly used variables.
15282 DeclRefExpr *FloorIV = buildDeclRefExpr(SemaRef, FloorIndVars[I], CntTy,
15283 OrigCntVar->getExprLoc());
15284
15285 // For init-statement: auto .floor.iv = 0
15287 FloorIndVars[I],
15288 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15289 /*DirectInit=*/false);
15290 Decl *CounterDecl = FloorIndVars[I];
15291 StmtResult InitStmt = new (Context)
15292 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15293 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15294 if (!InitStmt.isUsable())
15295 return StmtError();
15296
15297 // For cond-expression: .floor.iv < NumIterations
15298 ExprResult CondExpr = SemaRef.BuildBinOp(
15299 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, FloorIV, NumIterations);
15300 if (!CondExpr.isUsable())
15301 return StmtError();
15302
15303 // For incr-statement: .floor.iv += DimTileSize
15304 ExprResult IncrStmt =
15305 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15306 FloorIV, DimTileSize);
15307 if (!IncrStmt.isUsable())
15308 return StmtError();
15309
15310 Inner = new (Context)
15311 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15312 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15313 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15314 }
15315
15316 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
15317 AStmt, Inner,
15318 buildPreInits(Context, PreInits));
15319}
15320
15322 Stmt *AStmt,
15323 SourceLocation StartLoc,
15324 SourceLocation EndLoc) {
15325 ASTContext &Context = getASTContext();
15326 Scope *CurScope = SemaRef.getCurScope();
15327 // Empty statement should only be possible if there already was an error.
15328 if (!AStmt)
15329 return StmtError();
15330
15332 {OMPC_partial, OMPC_full}))
15333 return StmtError();
15334
15335 const OMPFullClause *FullClause =
15336 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15337 const OMPPartialClause *PartialClause =
15338 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15339 assert(!(FullClause && PartialClause) &&
15340 "mutual exclusivity must have been checked before");
15341
15342 constexpr unsigned NumLoops = 1;
15343 Stmt *Body = nullptr;
15345 NumLoops);
15347 OriginalInits;
15348 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15349 Body, OriginalInits))
15350 return StmtError();
15351
15352 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
15353
15354 // Delay unrolling to when template is completely instantiated.
15356 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15357 NumGeneratedLoops, nullptr, nullptr);
15358
15359 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15360
15361 if (FullClause) {
15363 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
15364 /*SuppressExprDiags=*/true)
15365 .isUsable()) {
15366 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
15367 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
15368 << "#pragma omp unroll full";
15369 return StmtError();
15370 }
15371 }
15372
15373 // The generated loop may only be passed to other loop-associated directive
15374 // when a partial clause is specified. Without the requirement it is
15375 // sufficient to generate loop unroll metadata at code-generation.
15376 if (NumGeneratedLoops == 0)
15377 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15378 NumGeneratedLoops, nullptr, nullptr);
15379
15380 // Otherwise, we need to provide a de-sugared/transformed AST that can be
15381 // associated with another loop directive.
15382 //
15383 // The canonical loop analysis return by checkTransformableLoopNest assumes
15384 // the following structure to be the same loop without transformations or
15385 // directives applied: \code OriginalInits; LoopHelper.PreInits;
15386 // LoopHelper.Counters;
15387 // for (; IV < LoopHelper.NumIterations; ++IV) {
15388 // LoopHelper.Updates;
15389 // Body;
15390 // }
15391 // \endcode
15392 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
15393 // and referenced by LoopHelper.IterationVarRef.
15394 //
15395 // The unrolling directive transforms this into the following loop:
15396 // \code
15397 // OriginalInits; \
15398 // LoopHelper.PreInits; > NewPreInits
15399 // LoopHelper.Counters; /
15400 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
15401 // #pragma clang loop unroll_count(Factor)
15402 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
15403 // {
15404 // LoopHelper.Updates;
15405 // Body;
15406 // }
15407 // }
15408 // \endcode
15409 // where UIV is a new logical iteration counter. IV must be the same VarDecl
15410 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
15411 // references it. If the partially unrolled loop is associated with another
15412 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
15413 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
15414 // OpenMP canonical loop. The inner loop is not an associable canonical loop
15415 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
15416 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
15417 // property of the OMPLoopBasedDirective instead of statements in
15418 // CompoundStatement. This is to allow the loop to become a non-outermost loop
15419 // of a canonical loop nest where these PreInits are emitted before the
15420 // outermost directive.
15421
15422 // Determine the PreInit declarations.
15423 SmallVector<Decl *, 4> PreInits;
15424 assert(OriginalInits.size() == 1 &&
15425 "Expecting a single-dimensional loop iteration space");
15426 for (auto &P : OriginalInits[0]) {
15427 if (auto *D = P.dyn_cast<Decl *>())
15428 PreInits.push_back(D);
15429 else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
15430 PreInits.append(PI->decl_begin(), PI->decl_end());
15431 }
15432 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
15433 PreInits.append(PI->decl_begin(), PI->decl_end());
15434 // Gather declarations for the data members used as counters.
15435 for (Expr *CounterRef : LoopHelper.Counters) {
15436 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
15437 if (isa<OMPCapturedExprDecl>(CounterDecl))
15438 PreInits.push_back(CounterDecl);
15439 }
15440
15441 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15442 QualType IVTy = IterationVarRef->getType();
15443 assert(LoopHelper.Counters.size() == 1 &&
15444 "Expecting a single-dimensional loop iteration space");
15445 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15446
15447 // Determine the unroll factor.
15448 uint64_t Factor;
15449 SourceLocation FactorLoc;
15450 if (Expr *FactorVal = PartialClause->getFactor()) {
15451 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15452 FactorLoc = FactorVal->getExprLoc();
15453 } else {
15454 // TODO: Use a better profitability model.
15455 Factor = 2;
15456 }
15457 assert(Factor > 0 && "Expected positive unroll factor");
15458 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
15460 getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor),
15461 IVTy, FactorLoc);
15462 };
15463
15464 // Iteration variable SourceLocations.
15465 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15466 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15467 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15468
15469 // Internal variable names.
15470 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15471 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
15472 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
15473 std::string InnerTripCountName =
15474 (Twine(".unroll_inner.tripcount.") + OrigVarName).str();
15475
15476 // Create the iteration variable for the unrolled loop.
15477 VarDecl *OuterIVDecl =
15478 buildVarDecl(SemaRef, {}, IVTy, OuterIVName, nullptr, OrigVar);
15479 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
15480 return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc);
15481 };
15482
15483 // Iteration variable for the inner loop: Reuse the iteration variable created
15484 // by checkOpenMPLoop.
15485 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15486 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(InnerIVName));
15487 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
15488 return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc);
15489 };
15490
15491 // Make a copy of the NumIterations expression for each use: By the AST
15492 // constraints, every expression object in a DeclContext must be unique.
15493 CaptureVars CopyTransformer(SemaRef);
15494 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15495 return AssertSuccess(
15496 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15497 };
15498
15499 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15500 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(MakeOuterRef());
15501 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(),
15502 /*DirectInit=*/false);
15503 StmtResult InnerInit = new (Context)
15504 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15505 if (!InnerInit.isUsable())
15506 return StmtError();
15507
15508 // Inner For cond-expression:
15509 // \code
15510 // .unroll_inner.iv < .unrolled.iv + Factor &&
15511 // .unroll_inner.iv < NumIterations
15512 // \endcode
15513 // This conjunction of two conditions allows ScalarEvolution to derive the
15514 // maximum trip count of the inner loop.
15515 ExprResult EndOfTile =
15516 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15517 MakeOuterRef(), MakeFactorExpr());
15518 if (!EndOfTile.isUsable())
15519 return StmtError();
15520 ExprResult InnerCond1 =
15521 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15522 MakeInnerRef(), EndOfTile.get());
15523 if (!InnerCond1.isUsable())
15524 return StmtError();
15525 ExprResult InnerCond2 =
15526 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15527 MakeInnerRef(), MakeNumIterations());
15528 if (!InnerCond2.isUsable())
15529 return StmtError();
15530 ExprResult InnerCond =
15531 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15532 InnerCond1.get(), InnerCond2.get());
15533 if (!InnerCond.isUsable())
15534 return StmtError();
15535
15536 // Inner For incr-statement: ++.unroll_inner.iv
15537 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
15538 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
15539 if (!InnerIncr.isUsable())
15540 return StmtError();
15541
15542 // Inner For statement.
15543 SmallVector<Stmt *> InnerBodyStmts;
15544 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15545 InnerBodyStmts.push_back(Body);
15546 CompoundStmt *InnerBody =
15548 Body->getBeginLoc(), Body->getEndLoc());
15549 ForStmt *InnerFor = new (Context)
15550 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15551 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15552 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15553
15554 // Unroll metadata for the inner loop.
15555 // This needs to take into account the remainder portion of the unrolled loop,
15556 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15557 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15558 // the maximum trip count, which will also generate a remainder loop. Just
15559 // `unroll(enable)` (which could have been useful if the user has not
15560 // specified a concrete factor; even though the outer loop cannot be
15561 // influenced anymore, would avoid more code bloat than necessary) will refuse
15562 // the loop because "Won't unroll; remainder loop could not be generated when
15563 // assuming runtime trip count". Even if it did work, it must not choose a
15564 // larger unroll factor than the maximum loop length, or it would always just
15565 // execute the remainder loop.
15566 LoopHintAttr *UnrollHintAttr =
15567 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15568 LoopHintAttr::Numeric, MakeFactorExpr());
15569 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
15570 getASTContext(), StartLoc, {UnrollHintAttr}, InnerFor);
15571
15572 // Outer For init-statement: auto .unrolled.iv = 0
15574 OuterIVDecl,
15575 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15576 /*DirectInit=*/false);
15577 StmtResult OuterInit = new (Context)
15578 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15579 if (!OuterInit.isUsable())
15580 return StmtError();
15581
15582 // Outer For cond-expression: .unrolled.iv < NumIterations
15583 ExprResult OuterConde =
15584 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15585 MakeOuterRef(), MakeNumIterations());
15586 if (!OuterConde.isUsable())
15587 return StmtError();
15588
15589 // Outer For incr-statement: .unrolled.iv += Factor
15590 ExprResult OuterIncr =
15591 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15592 MakeOuterRef(), MakeFactorExpr());
15593 if (!OuterIncr.isUsable())
15594 return StmtError();
15595
15596 // Outer For statement.
15597 ForStmt *OuterFor = new (Context)
15598 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15599 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15600 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15601
15602 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15603 NumGeneratedLoops, OuterFor,
15604 buildPreInits(Context, PreInits));
15605}
15606
15608 Expr *Expr,
15609 SourceLocation StartLoc,
15610 SourceLocation LParenLoc,
15611 SourceLocation EndLoc) {
15612 OMPClause *Res = nullptr;
15613 switch (Kind) {
15614 case OMPC_final:
15615 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
15616 break;
15617 case OMPC_num_threads:
15618 Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
15619 break;
15620 case OMPC_safelen:
15621 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
15622 break;
15623 case OMPC_simdlen:
15624 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
15625 break;
15626 case OMPC_allocator:
15627 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
15628 break;
15629 case OMPC_collapse:
15630 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
15631 break;
15632 case OMPC_ordered:
15633 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
15634 break;
15635 case OMPC_num_teams:
15636 Res = ActOnOpenMPNumTeamsClause(Expr, StartLoc, LParenLoc, EndLoc);
15637 break;
15638 case OMPC_thread_limit:
15639 Res = ActOnOpenMPThreadLimitClause(Expr, StartLoc, LParenLoc, EndLoc);
15640 break;
15641 case OMPC_priority:
15642 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
15643 break;
15644 case OMPC_hint:
15645 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
15646 break;
15647 case OMPC_depobj:
15648 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
15649 break;
15650 case OMPC_detach:
15651 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
15652 break;
15653 case OMPC_novariants:
15654 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
15655 break;
15656 case OMPC_nocontext:
15657 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
15658 break;
15659 case OMPC_filter:
15660 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
15661 break;
15662 case OMPC_partial:
15663 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
15664 break;
15665 case OMPC_message:
15666 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
15667 break;
15668 case OMPC_align:
15669 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
15670 break;
15671 case OMPC_ompx_dyn_cgroup_mem:
15672 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
15673 break;
15674 case OMPC_grainsize:
15675 case OMPC_num_tasks:
15676 case OMPC_device:
15677 case OMPC_if:
15678 case OMPC_default:
15679 case OMPC_proc_bind:
15680 case OMPC_schedule:
15681 case OMPC_private:
15682 case OMPC_firstprivate:
15683 case OMPC_lastprivate:
15684 case OMPC_shared:
15685 case OMPC_reduction:
15686 case OMPC_task_reduction:
15687 case OMPC_in_reduction:
15688 case OMPC_linear:
15689 case OMPC_aligned:
15690 case OMPC_copyin:
15691 case OMPC_copyprivate:
15692 case OMPC_nowait:
15693 case OMPC_untied:
15694 case OMPC_mergeable:
15695 case OMPC_threadprivate:
15696 case OMPC_sizes:
15697 case OMPC_allocate:
15698 case OMPC_flush:
15699 case OMPC_read:
15700 case OMPC_write:
15701 case OMPC_update:
15702 case OMPC_capture:
15703 case OMPC_compare:
15704 case OMPC_seq_cst:
15705 case OMPC_acq_rel:
15706 case OMPC_acquire:
15707 case OMPC_release:
15708 case OMPC_relaxed:
15709 case OMPC_depend:
15710 case OMPC_threads:
15711 case OMPC_simd:
15712 case OMPC_map:
15713 case OMPC_nogroup:
15714 case OMPC_dist_schedule:
15715 case OMPC_defaultmap:
15716 case OMPC_unknown:
15717 case OMPC_uniform:
15718 case OMPC_to:
15719 case OMPC_from:
15720 case OMPC_use_device_ptr:
15721 case OMPC_use_device_addr:
15722 case OMPC_is_device_ptr:
15723 case OMPC_unified_address:
15724 case OMPC_unified_shared_memory:
15725 case OMPC_reverse_offload:
15726 case OMPC_dynamic_allocators:
15727 case OMPC_atomic_default_mem_order:
15728 case OMPC_device_type:
15729 case OMPC_match:
15730 case OMPC_nontemporal:
15731 case OMPC_order:
15732 case OMPC_at:
15733 case OMPC_severity:
15734 case OMPC_destroy:
15735 case OMPC_inclusive:
15736 case OMPC_exclusive:
15737 case OMPC_uses_allocators:
15738 case OMPC_affinity:
15739 case OMPC_when:
15740 case OMPC_bind:
15741 default:
15742 llvm_unreachable("Clause is not allowed.");
15743 }
15744 return Res;
15745}
15746
15747// An OpenMP directive such as 'target parallel' has two captured regions:
15748// for the 'target' and 'parallel' respectively. This function returns
15749// the region in which to capture expressions associated with a clause.
15750// A return value of OMPD_unknown signifies that the expression should not
15751// be captured.
15753 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15754 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15755 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15756 switch (CKind) {
15757 case OMPC_if:
15758 switch (DKind) {
15759 case OMPD_target_parallel_for_simd:
15760 if (OpenMPVersion >= 50 &&
15761 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15762 CaptureRegion = OMPD_parallel;
15763 break;
15764 }
15765 [[fallthrough]];
15766 case OMPD_target_parallel:
15767 case OMPD_target_parallel_for:
15768 case OMPD_target_parallel_loop:
15769 // If this clause applies to the nested 'parallel' region, capture within
15770 // the 'target' region, otherwise do not capture.
15771 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15772 CaptureRegion = OMPD_target;
15773 break;
15774 case OMPD_teams_loop:
15775 case OMPD_target_teams_loop:
15776 // For [target] teams loop, assume capture region is 'teams' so it's
15777 // available for codegen later to use if/when necessary.
15778 CaptureRegion = OMPD_teams;
15779 break;
15780 case OMPD_target_teams_distribute_parallel_for_simd:
15781 if (OpenMPVersion >= 50 &&
15782 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15783 CaptureRegion = OMPD_parallel;
15784 break;
15785 }
15786 [[fallthrough]];
15787 case OMPD_target_teams_distribute_parallel_for:
15788 // If this clause applies to the nested 'parallel' region, capture within
15789 // the 'teams' region, otherwise do not capture.
15790 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15791 CaptureRegion = OMPD_teams;
15792 break;
15793 case OMPD_teams_distribute_parallel_for_simd:
15794 if (OpenMPVersion >= 50 &&
15795 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15796 CaptureRegion = OMPD_parallel;
15797 break;
15798 }
15799 [[fallthrough]];
15800 case OMPD_teams_distribute_parallel_for:
15801 CaptureRegion = OMPD_teams;
15802 break;
15803 case OMPD_target_update:
15804 case OMPD_target_enter_data:
15805 case OMPD_target_exit_data:
15806 CaptureRegion = OMPD_task;
15807 break;
15808 case OMPD_parallel_masked_taskloop:
15809 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15810 CaptureRegion = OMPD_parallel;
15811 break;
15812 case OMPD_parallel_master_taskloop:
15813 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15814 CaptureRegion = OMPD_parallel;
15815 break;
15816 case OMPD_parallel_masked_taskloop_simd:
15817 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15818 NameModifier == OMPD_taskloop) {
15819 CaptureRegion = OMPD_parallel;
15820 break;
15821 }
15822 if (OpenMPVersion <= 45)
15823 break;
15824 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15825 CaptureRegion = OMPD_taskloop;
15826 break;
15827 case OMPD_parallel_master_taskloop_simd:
15828 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15829 NameModifier == OMPD_taskloop) {
15830 CaptureRegion = OMPD_parallel;
15831 break;
15832 }
15833 if (OpenMPVersion <= 45)
15834 break;
15835 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15836 CaptureRegion = OMPD_taskloop;
15837 break;
15838 case OMPD_parallel_for_simd:
15839 if (OpenMPVersion <= 45)
15840 break;
15841 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15842 CaptureRegion = OMPD_parallel;
15843 break;
15844 case OMPD_taskloop_simd:
15845 case OMPD_master_taskloop_simd:
15846 case OMPD_masked_taskloop_simd:
15847 if (OpenMPVersion <= 45)
15848 break;
15849 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15850 CaptureRegion = OMPD_taskloop;
15851 break;
15852 case OMPD_distribute_parallel_for_simd:
15853 if (OpenMPVersion <= 45)
15854 break;
15855 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15856 CaptureRegion = OMPD_parallel;
15857 break;
15858 case OMPD_target_simd:
15859 if (OpenMPVersion >= 50 &&
15860 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15861 CaptureRegion = OMPD_target;
15862 break;
15863 case OMPD_teams_distribute_simd:
15864 case OMPD_target_teams_distribute_simd:
15865 if (OpenMPVersion >= 50 &&
15866 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15867 CaptureRegion = OMPD_teams;
15868 break;
15869 case OMPD_cancel:
15870 case OMPD_parallel:
15871 case OMPD_parallel_master:
15872 case OMPD_parallel_masked:
15873 case OMPD_parallel_sections:
15874 case OMPD_parallel_for:
15875 case OMPD_parallel_loop:
15876 case OMPD_target:
15877 case OMPD_target_teams:
15878 case OMPD_target_teams_distribute:
15879 case OMPD_distribute_parallel_for:
15880 case OMPD_task:
15881 case OMPD_taskloop:
15882 case OMPD_master_taskloop:
15883 case OMPD_masked_taskloop:
15884 case OMPD_target_data:
15885 case OMPD_simd:
15886 case OMPD_for_simd:
15887 case OMPD_distribute_simd:
15888 // Do not capture if-clause expressions.
15889 break;
15890 case OMPD_threadprivate:
15891 case OMPD_allocate:
15892 case OMPD_taskyield:
15893 case OMPD_error:
15894 case OMPD_barrier:
15895 case OMPD_taskwait:
15896 case OMPD_cancellation_point:
15897 case OMPD_flush:
15898 case OMPD_depobj:
15899 case OMPD_scan:
15900 case OMPD_declare_reduction:
15901 case OMPD_declare_mapper:
15902 case OMPD_declare_simd:
15903 case OMPD_declare_variant:
15904 case OMPD_begin_declare_variant:
15905 case OMPD_end_declare_variant:
15906 case OMPD_declare_target:
15907 case OMPD_end_declare_target:
15908 case OMPD_loop:
15909 case OMPD_teams:
15910 case OMPD_tile:
15911 case OMPD_unroll:
15912 case OMPD_for:
15913 case OMPD_sections:
15914 case OMPD_section:
15915 case OMPD_single:
15916 case OMPD_master:
15917 case OMPD_masked:
15918 case OMPD_critical:
15919 case OMPD_taskgroup:
15920 case OMPD_distribute:
15921 case OMPD_ordered:
15922 case OMPD_atomic:
15923 case OMPD_teams_distribute:
15924 case OMPD_requires:
15925 case OMPD_metadirective:
15926 llvm_unreachable("Unexpected OpenMP directive with if-clause");
15927 case OMPD_unknown:
15928 default:
15929 llvm_unreachable("Unknown OpenMP directive");
15930 }
15931 break;
15932 case OMPC_num_threads:
15933 switch (DKind) {
15934 case OMPD_target_parallel:
15935 case OMPD_target_parallel_for:
15936 case OMPD_target_parallel_for_simd:
15937 case OMPD_target_parallel_loop:
15938 CaptureRegion = OMPD_target;
15939 break;
15940 case OMPD_teams_distribute_parallel_for:
15941 case OMPD_teams_distribute_parallel_for_simd:
15942 case OMPD_target_teams_distribute_parallel_for:
15943 case OMPD_target_teams_distribute_parallel_for_simd:
15944 CaptureRegion = OMPD_teams;
15945 break;
15946 case OMPD_parallel:
15947 case OMPD_parallel_master:
15948 case OMPD_parallel_masked:
15949 case OMPD_parallel_sections:
15950 case OMPD_parallel_for:
15951 case OMPD_parallel_for_simd:
15952 case OMPD_parallel_loop:
15953 case OMPD_distribute_parallel_for:
15954 case OMPD_distribute_parallel_for_simd:
15955 case OMPD_parallel_master_taskloop:
15956 case OMPD_parallel_masked_taskloop:
15957 case OMPD_parallel_master_taskloop_simd:
15958 case OMPD_parallel_masked_taskloop_simd:
15959 // Do not capture num_threads-clause expressions.
15960 break;
15961 case OMPD_target_data:
15962 case OMPD_target_enter_data:
15963 case OMPD_target_exit_data:
15964 case OMPD_target_update:
15965 case OMPD_target:
15966 case OMPD_target_simd:
15967 case OMPD_target_teams:
15968 case OMPD_target_teams_distribute:
15969 case OMPD_target_teams_distribute_simd:
15970 case OMPD_cancel:
15971 case OMPD_task:
15972 case OMPD_taskloop:
15973 case OMPD_taskloop_simd:
15974 case OMPD_master_taskloop:
15975 case OMPD_masked_taskloop:
15976 case OMPD_master_taskloop_simd:
15977 case OMPD_masked_taskloop_simd:
15978 case OMPD_threadprivate:
15979 case OMPD_allocate:
15980 case OMPD_taskyield:
15981 case OMPD_error:
15982 case OMPD_barrier:
15983 case OMPD_taskwait:
15984 case OMPD_cancellation_point:
15985 case OMPD_flush:
15986 case OMPD_depobj:
15987 case OMPD_scan:
15988 case OMPD_declare_reduction:
15989 case OMPD_declare_mapper:
15990 case OMPD_declare_simd:
15991 case OMPD_declare_variant:
15992 case OMPD_begin_declare_variant:
15993 case OMPD_end_declare_variant:
15994 case OMPD_declare_target:
15995 case OMPD_end_declare_target:
15996 case OMPD_loop:
15997 case OMPD_teams_loop:
15998 case OMPD_target_teams_loop:
15999 case OMPD_teams:
16000 case OMPD_simd:
16001 case OMPD_tile:
16002 case OMPD_unroll:
16003 case OMPD_for:
16004 case OMPD_for_simd:
16005 case OMPD_sections:
16006 case OMPD_section:
16007 case OMPD_single:
16008 case OMPD_master:
16009 case OMPD_masked:
16010 case OMPD_critical:
16011 case OMPD_taskgroup:
16012 case OMPD_distribute:
16013 case OMPD_ordered:
16014 case OMPD_atomic:
16015 case OMPD_distribute_simd:
16016 case OMPD_teams_distribute:
16017 case OMPD_teams_distribute_simd:
16018 case OMPD_requires:
16019 case OMPD_metadirective:
16020 llvm_unreachable("Unexpected OpenMP directive with num_threads-clause");
16021 case OMPD_unknown:
16022 default:
16023 llvm_unreachable("Unknown OpenMP directive");
16024 }
16025 break;
16026 case OMPC_num_teams:
16027 switch (DKind) {
16028 case OMPD_target_teams:
16029 case OMPD_target_teams_distribute:
16030 case OMPD_target_teams_distribute_simd:
16031 case OMPD_target_teams_distribute_parallel_for:
16032 case OMPD_target_teams_distribute_parallel_for_simd:
16033 case OMPD_target_teams_loop:
16034 CaptureRegion = OMPD_target;
16035 break;
16036 case OMPD_teams_distribute_parallel_for:
16037 case OMPD_teams_distribute_parallel_for_simd:
16038 case OMPD_teams:
16039 case OMPD_teams_distribute:
16040 case OMPD_teams_distribute_simd:
16041 case OMPD_teams_loop:
16042 // Do not capture num_teams-clause expressions.
16043 break;
16044 case OMPD_distribute_parallel_for:
16045 case OMPD_distribute_parallel_for_simd:
16046 case OMPD_task:
16047 case OMPD_taskloop:
16048 case OMPD_taskloop_simd:
16049 case OMPD_master_taskloop:
16050 case OMPD_masked_taskloop:
16051 case OMPD_master_taskloop_simd:
16052 case OMPD_masked_taskloop_simd:
16053 case OMPD_parallel_master_taskloop:
16054 case OMPD_parallel_masked_taskloop:
16055 case OMPD_parallel_master_taskloop_simd:
16056 case OMPD_parallel_masked_taskloop_simd:
16057 case OMPD_target_data:
16058 case OMPD_target_enter_data:
16059 case OMPD_target_exit_data:
16060 case OMPD_target_update:
16061 case OMPD_cancel:
16062 case OMPD_parallel:
16063 case OMPD_parallel_master:
16064 case OMPD_parallel_masked:
16065 case OMPD_parallel_sections:
16066 case OMPD_parallel_for:
16067 case OMPD_parallel_for_simd:
16068 case OMPD_parallel_loop:
16069 case OMPD_target:
16070 case OMPD_target_simd:
16071 case OMPD_target_parallel:
16072 case OMPD_target_parallel_for:
16073 case OMPD_target_parallel_for_simd:
16074 case OMPD_target_parallel_loop:
16075 case OMPD_threadprivate:
16076 case OMPD_allocate:
16077 case OMPD_taskyield:
16078 case OMPD_error:
16079 case OMPD_barrier:
16080 case OMPD_taskwait:
16081 case OMPD_cancellation_point:
16082 case OMPD_flush:
16083 case OMPD_depobj:
16084 case OMPD_scan:
16085 case OMPD_declare_reduction:
16086 case OMPD_declare_mapper:
16087 case OMPD_declare_simd:
16088 case OMPD_declare_variant:
16089 case OMPD_begin_declare_variant:
16090 case OMPD_end_declare_variant:
16091 case OMPD_declare_target:
16092 case OMPD_end_declare_target:
16093 case OMPD_loop:
16094 case OMPD_simd:
16095 case OMPD_tile:
16096 case OMPD_unroll:
16097 case OMPD_for:
16098 case OMPD_for_simd:
16099 case OMPD_sections:
16100 case OMPD_section:
16101 case OMPD_single:
16102 case OMPD_master:
16103 case OMPD_masked:
16104 case OMPD_critical:
16105 case OMPD_taskgroup:
16106 case OMPD_distribute:
16107 case OMPD_ordered:
16108 case OMPD_atomic:
16109 case OMPD_distribute_simd:
16110 case OMPD_requires:
16111 case OMPD_metadirective:
16112 llvm_unreachable("Unexpected OpenMP directive with num_teams-clause");
16113 case OMPD_unknown:
16114 default:
16115 llvm_unreachable("Unknown OpenMP directive");
16116 }
16117 break;
16118 case OMPC_thread_limit:
16119 switch (DKind) {
16120 case OMPD_target:
16121 case OMPD_target_teams:
16122 case OMPD_target_teams_distribute:
16123 case OMPD_target_teams_distribute_simd:
16124 case OMPD_target_teams_distribute_parallel_for:
16125 case OMPD_target_teams_distribute_parallel_for_simd:
16126 case OMPD_target_teams_loop:
16127 case OMPD_target_simd:
16128 case OMPD_target_parallel:
16129 case OMPD_target_parallel_for:
16130 case OMPD_target_parallel_for_simd:
16131 case OMPD_target_parallel_loop:
16132 CaptureRegion = OMPD_target;
16133 break;
16134 case OMPD_teams_distribute_parallel_for:
16135 case OMPD_teams_distribute_parallel_for_simd:
16136 case OMPD_teams:
16137 case OMPD_teams_distribute:
16138 case OMPD_teams_distribute_simd:
16139 case OMPD_teams_loop:
16140 // Do not capture thread_limit-clause expressions.
16141 break;
16142 case OMPD_distribute_parallel_for:
16143 case OMPD_distribute_parallel_for_simd:
16144 case OMPD_task:
16145 case OMPD_taskloop:
16146 case OMPD_taskloop_simd:
16147 case OMPD_master_taskloop:
16148 case OMPD_masked_taskloop:
16149 case OMPD_master_taskloop_simd:
16150 case OMPD_masked_taskloop_simd:
16151 case OMPD_parallel_master_taskloop:
16152 case OMPD_parallel_masked_taskloop:
16153 case OMPD_parallel_master_taskloop_simd:
16154 case OMPD_parallel_masked_taskloop_simd:
16155 case OMPD_target_data:
16156 case OMPD_target_enter_data:
16157 case OMPD_target_exit_data:
16158 case OMPD_target_update:
16159 case OMPD_cancel:
16160 case OMPD_parallel:
16161 case OMPD_parallel_master:
16162 case OMPD_parallel_masked:
16163 case OMPD_parallel_sections:
16164 case OMPD_parallel_for:
16165 case OMPD_parallel_for_simd:
16166 case OMPD_parallel_loop:
16167 case OMPD_threadprivate:
16168 case OMPD_allocate:
16169 case OMPD_taskyield:
16170 case OMPD_error:
16171 case OMPD_barrier:
16172 case OMPD_taskwait:
16173 case OMPD_cancellation_point:
16174 case OMPD_flush:
16175 case OMPD_depobj:
16176 case OMPD_scan:
16177 case OMPD_declare_reduction:
16178 case OMPD_declare_mapper:
16179 case OMPD_declare_simd:
16180 case OMPD_declare_variant:
16181 case OMPD_begin_declare_variant:
16182 case OMPD_end_declare_variant:
16183 case OMPD_declare_target:
16184 case OMPD_end_declare_target:
16185 case OMPD_loop:
16186 case OMPD_simd:
16187 case OMPD_tile:
16188 case OMPD_unroll:
16189 case OMPD_for:
16190 case OMPD_for_simd:
16191 case OMPD_sections:
16192 case OMPD_section:
16193 case OMPD_single:
16194 case OMPD_master:
16195 case OMPD_masked:
16196 case OMPD_critical:
16197 case OMPD_taskgroup:
16198 case OMPD_distribute:
16199 case OMPD_ordered:
16200 case OMPD_atomic:
16201 case OMPD_distribute_simd:
16202 case OMPD_requires:
16203 case OMPD_metadirective:
16204 llvm_unreachable("Unexpected OpenMP directive with thread_limit-clause");
16205 case OMPD_unknown:
16206 default:
16207 llvm_unreachable("Unknown OpenMP directive");
16208 }
16209 break;
16210 case OMPC_schedule:
16211 switch (DKind) {
16212 case OMPD_parallel_for:
16213 case OMPD_parallel_for_simd:
16214 case OMPD_distribute_parallel_for:
16215 case OMPD_distribute_parallel_for_simd:
16216 case OMPD_teams_distribute_parallel_for:
16217 case OMPD_teams_distribute_parallel_for_simd:
16218 case OMPD_target_parallel_for:
16219 case OMPD_target_parallel_for_simd:
16220 case OMPD_target_teams_distribute_parallel_for:
16221 case OMPD_target_teams_distribute_parallel_for_simd:
16222 CaptureRegion = OMPD_parallel;
16223 break;
16224 case OMPD_for:
16225 case OMPD_for_simd:
16226 // Do not capture schedule-clause expressions.
16227 break;
16228 case OMPD_task:
16229 case OMPD_taskloop:
16230 case OMPD_taskloop_simd:
16231 case OMPD_master_taskloop:
16232 case OMPD_masked_taskloop:
16233 case OMPD_master_taskloop_simd:
16234 case OMPD_masked_taskloop_simd:
16235 case OMPD_parallel_master_taskloop:
16236 case OMPD_parallel_masked_taskloop:
16237 case OMPD_parallel_master_taskloop_simd:
16238 case OMPD_parallel_masked_taskloop_simd:
16239 case OMPD_target_data:
16240 case OMPD_target_enter_data:
16241 case OMPD_target_exit_data:
16242 case OMPD_target_update:
16243 case OMPD_teams:
16244 case OMPD_teams_distribute:
16245 case OMPD_teams_distribute_simd:
16246 case OMPD_target_teams_distribute:
16247 case OMPD_target_teams_distribute_simd:
16248 case OMPD_target:
16249 case OMPD_target_simd:
16250 case OMPD_target_parallel:
16251 case OMPD_cancel:
16252 case OMPD_parallel:
16253 case OMPD_parallel_master:
16254 case OMPD_parallel_masked:
16255 case OMPD_parallel_sections:
16256 case OMPD_threadprivate:
16257 case OMPD_allocate:
16258 case OMPD_taskyield:
16259 case OMPD_error:
16260 case OMPD_barrier:
16261 case OMPD_taskwait:
16262 case OMPD_cancellation_point:
16263 case OMPD_flush:
16264 case OMPD_depobj:
16265 case OMPD_scan:
16266 case OMPD_declare_reduction:
16267 case OMPD_declare_mapper:
16268 case OMPD_declare_simd:
16269 case OMPD_declare_variant:
16270 case OMPD_begin_declare_variant:
16271 case OMPD_end_declare_variant:
16272 case OMPD_declare_target:
16273 case OMPD_end_declare_target:
16274 case OMPD_loop:
16275 case OMPD_teams_loop:
16276 case OMPD_target_teams_loop:
16277 case OMPD_parallel_loop:
16278 case OMPD_target_parallel_loop:
16279 case OMPD_simd:
16280 case OMPD_tile:
16281 case OMPD_unroll:
16282 case OMPD_sections:
16283 case OMPD_section:
16284 case OMPD_single:
16285 case OMPD_master:
16286 case OMPD_masked:
16287 case OMPD_critical:
16288 case OMPD_taskgroup:
16289 case OMPD_distribute:
16290 case OMPD_ordered:
16291 case OMPD_atomic:
16292 case OMPD_distribute_simd:
16293 case OMPD_target_teams:
16294 case OMPD_requires:
16295 case OMPD_metadirective:
16296 llvm_unreachable("Unexpected OpenMP directive with schedule clause");
16297 case OMPD_unknown:
16298 default:
16299 llvm_unreachable("Unknown OpenMP directive");
16300 }
16301 break;
16302 case OMPC_dist_schedule:
16303 switch (DKind) {
16304 case OMPD_teams_distribute_parallel_for:
16305 case OMPD_teams_distribute_parallel_for_simd:
16306 case OMPD_teams_distribute:
16307 case OMPD_teams_distribute_simd:
16308 case OMPD_target_teams_distribute_parallel_for:
16309 case OMPD_target_teams_distribute_parallel_for_simd:
16310 case OMPD_target_teams_distribute:
16311 case OMPD_target_teams_distribute_simd:
16312 CaptureRegion = OMPD_teams;
16313 break;
16314 case OMPD_distribute_parallel_for:
16315 case OMPD_distribute_parallel_for_simd:
16316 case OMPD_distribute:
16317 case OMPD_distribute_simd:
16318 // Do not capture dist_schedule-clause expressions.
16319 break;
16320 case OMPD_parallel_for:
16321 case OMPD_parallel_for_simd:
16322 case OMPD_target_parallel_for_simd:
16323 case OMPD_target_parallel_for:
16324 case OMPD_task:
16325 case OMPD_taskloop:
16326 case OMPD_taskloop_simd:
16327 case OMPD_master_taskloop:
16328 case OMPD_masked_taskloop:
16329 case OMPD_master_taskloop_simd:
16330 case OMPD_masked_taskloop_simd:
16331 case OMPD_parallel_master_taskloop:
16332 case OMPD_parallel_masked_taskloop:
16333 case OMPD_parallel_master_taskloop_simd:
16334 case OMPD_parallel_masked_taskloop_simd:
16335 case OMPD_target_data:
16336 case OMPD_target_enter_data:
16337 case OMPD_target_exit_data:
16338 case OMPD_target_update:
16339 case OMPD_teams:
16340 case OMPD_target:
16341 case OMPD_target_simd:
16342 case OMPD_target_parallel:
16343 case OMPD_cancel:
16344 case OMPD_parallel:
16345 case OMPD_parallel_master:
16346 case OMPD_parallel_masked:
16347 case OMPD_parallel_sections:
16348 case OMPD_threadprivate:
16349 case OMPD_allocate:
16350 case OMPD_taskyield:
16351 case OMPD_error:
16352 case OMPD_barrier:
16353 case OMPD_taskwait:
16354 case OMPD_cancellation_point:
16355 case OMPD_flush:
16356 case OMPD_depobj:
16357 case OMPD_scan:
16358 case OMPD_declare_reduction:
16359 case OMPD_declare_mapper:
16360 case OMPD_declare_simd:
16361 case OMPD_declare_variant:
16362 case OMPD_begin_declare_variant:
16363 case OMPD_end_declare_variant:
16364 case OMPD_declare_target:
16365 case OMPD_end_declare_target:
16366 case OMPD_loop:
16367 case OMPD_teams_loop:
16368 case OMPD_target_teams_loop:
16369 case OMPD_parallel_loop:
16370 case OMPD_target_parallel_loop:
16371 case OMPD_simd:
16372 case OMPD_tile:
16373 case OMPD_unroll:
16374 case OMPD_for:
16375 case OMPD_for_simd:
16376 case OMPD_sections:
16377 case OMPD_section:
16378 case OMPD_single:
16379 case OMPD_master:
16380 case OMPD_masked:
16381 case OMPD_critical:
16382 case OMPD_taskgroup:
16383 case OMPD_ordered:
16384 case OMPD_atomic:
16385 case OMPD_target_teams:
16386 case OMPD_requires:
16387 case OMPD_metadirective:
16388 llvm_unreachable("Unexpected OpenMP directive with dist_schedule clause");
16389 case OMPD_unknown:
16390 default:
16391 llvm_unreachable("Unknown OpenMP directive");
16392 }
16393 break;
16394 case OMPC_ompx_dyn_cgroup_mem:
16395 switch (DKind) {
16396 case OMPD_target:
16397 case OMPD_target_simd:
16398 case OMPD_target_teams:
16399 case OMPD_target_parallel:
16400 case OMPD_target_teams_distribute:
16401 case OMPD_target_teams_distribute_simd:
16402 case OMPD_target_parallel_for:
16403 case OMPD_target_parallel_for_simd:
16404 case OMPD_target_parallel_loop:
16405 case OMPD_target_teams_distribute_parallel_for:
16406 case OMPD_target_teams_distribute_parallel_for_simd:
16407 case OMPD_target_teams_loop:
16408 CaptureRegion = OMPD_target;
16409 break;
16410 default:
16411 llvm_unreachable("Unknown OpenMP directive");
16412 }
16413 break;
16414 case OMPC_device:
16415 switch (DKind) {
16416 case OMPD_target_update:
16417 case OMPD_target_enter_data:
16418 case OMPD_target_exit_data:
16419 case OMPD_target:
16420 case OMPD_target_simd:
16421 case OMPD_target_teams:
16422 case OMPD_target_parallel:
16423 case OMPD_target_teams_distribute:
16424 case OMPD_target_teams_distribute_simd:
16425 case OMPD_target_parallel_for:
16426 case OMPD_target_parallel_for_simd:
16427 case OMPD_target_parallel_loop:
16428 case OMPD_target_teams_distribute_parallel_for:
16429 case OMPD_target_teams_distribute_parallel_for_simd:
16430 case OMPD_target_teams_loop:
16431 case OMPD_dispatch:
16432 CaptureRegion = OMPD_task;
16433 break;
16434 case OMPD_target_data:
16435 case OMPD_interop:
16436 // Do not capture device-clause expressions.
16437 break;
16438 case OMPD_teams_distribute_parallel_for:
16439 case OMPD_teams_distribute_parallel_for_simd:
16440 case OMPD_teams:
16441 case OMPD_teams_distribute:
16442 case OMPD_teams_distribute_simd:
16443 case OMPD_distribute_parallel_for:
16444 case OMPD_distribute_parallel_for_simd:
16445 case OMPD_task:
16446 case OMPD_taskloop:
16447 case OMPD_taskloop_simd:
16448 case OMPD_master_taskloop:
16449 case OMPD_masked_taskloop:
16450 case OMPD_master_taskloop_simd:
16451 case OMPD_masked_taskloop_simd:
16452 case OMPD_parallel_master_taskloop:
16453 case OMPD_parallel_masked_taskloop:
16454 case OMPD_parallel_master_taskloop_simd:
16455 case OMPD_parallel_masked_taskloop_simd:
16456 case OMPD_cancel:
16457 case OMPD_parallel:
16458 case OMPD_parallel_master:
16459 case OMPD_parallel_masked:
16460 case OMPD_parallel_sections:
16461 case OMPD_parallel_for:
16462 case OMPD_parallel_for_simd:
16463 case OMPD_threadprivate:
16464 case OMPD_allocate:
16465 case OMPD_taskyield:
16466 case OMPD_error:
16467 case OMPD_barrier:
16468 case OMPD_taskwait:
16469 case OMPD_cancellation_point:
16470 case OMPD_flush:
16471 case OMPD_depobj:
16472 case OMPD_scan:
16473 case OMPD_declare_reduction:
16474 case OMPD_declare_mapper:
16475 case OMPD_declare_simd:
16476 case OMPD_declare_variant:
16477 case OMPD_begin_declare_variant:
16478 case OMPD_end_declare_variant:
16479 case OMPD_declare_target:
16480 case OMPD_end_declare_target:
16481 case OMPD_loop:
16482 case OMPD_teams_loop:
16483 case OMPD_parallel_loop:
16484 case OMPD_simd:
16485 case OMPD_tile:
16486 case OMPD_unroll:
16487 case OMPD_for:
16488 case OMPD_for_simd:
16489 case OMPD_sections:
16490 case OMPD_section:
16491 case OMPD_single:
16492 case OMPD_master:
16493 case OMPD_masked:
16494 case OMPD_critical:
16495 case OMPD_taskgroup:
16496 case OMPD_distribute:
16497 case OMPD_ordered:
16498 case OMPD_atomic:
16499 case OMPD_distribute_simd:
16500 case OMPD_requires:
16501 case OMPD_metadirective:
16502 llvm_unreachable("Unexpected OpenMP directive with device-clause");
16503 case OMPD_unknown:
16504 default:
16505 llvm_unreachable("Unknown OpenMP directive");
16506 }
16507 break;
16508 case OMPC_grainsize:
16509 case OMPC_num_tasks:
16510 case OMPC_final:
16511 case OMPC_priority:
16512 switch (DKind) {
16513 case OMPD_task:
16514 case OMPD_taskloop:
16515 case OMPD_taskloop_simd:
16516 case OMPD_master_taskloop:
16517 case OMPD_masked_taskloop:
16518 case OMPD_master_taskloop_simd:
16519 case OMPD_masked_taskloop_simd:
16520 break;
16521 case OMPD_parallel_masked_taskloop:
16522 case OMPD_parallel_masked_taskloop_simd:
16523 case OMPD_parallel_master_taskloop:
16524 case OMPD_parallel_master_taskloop_simd:
16525 CaptureRegion = OMPD_parallel;
16526 break;
16527 case OMPD_target_update:
16528 case OMPD_target_enter_data:
16529 case OMPD_target_exit_data:
16530 case OMPD_target:
16531 case OMPD_target_simd:
16532 case OMPD_target_teams:
16533 case OMPD_target_parallel:
16534 case OMPD_target_teams_distribute:
16535 case OMPD_target_teams_distribute_simd:
16536 case OMPD_target_parallel_for:
16537 case OMPD_target_parallel_for_simd:
16538 case OMPD_target_teams_distribute_parallel_for:
16539 case OMPD_target_teams_distribute_parallel_for_simd:
16540 case OMPD_target_data:
16541 case OMPD_teams_distribute_parallel_for:
16542 case OMPD_teams_distribute_parallel_for_simd:
16543 case OMPD_teams:
16544 case OMPD_teams_distribute:
16545 case OMPD_teams_distribute_simd:
16546 case OMPD_distribute_parallel_for:
16547 case OMPD_distribute_parallel_for_simd:
16548 case OMPD_cancel:
16549 case OMPD_parallel:
16550 case OMPD_parallel_master:
16551 case OMPD_parallel_masked:
16552 case OMPD_parallel_sections:
16553 case OMPD_parallel_for:
16554 case OMPD_parallel_for_simd:
16555 case OMPD_threadprivate:
16556 case OMPD_allocate:
16557 case OMPD_taskyield:
16558 case OMPD_error:
16559 case OMPD_barrier:
16560 case OMPD_taskwait:
16561 case OMPD_cancellation_point:
16562 case OMPD_flush:
16563 case OMPD_depobj:
16564 case OMPD_scan:
16565 case OMPD_declare_reduction:
16566 case OMPD_declare_mapper:
16567 case OMPD_declare_simd:
16568 case OMPD_declare_variant:
16569 case OMPD_begin_declare_variant:
16570 case OMPD_end_declare_variant:
16571 case OMPD_declare_target:
16572 case OMPD_end_declare_target:
16573 case OMPD_loop:
16574 case OMPD_teams_loop:
16575 case OMPD_target_teams_loop:
16576 case OMPD_parallel_loop:
16577 case OMPD_target_parallel_loop:
16578 case OMPD_simd:
16579 case OMPD_tile:
16580 case OMPD_unroll:
16581 case OMPD_for:
16582 case OMPD_for_simd:
16583 case OMPD_sections:
16584 case OMPD_section:
16585 case OMPD_single:
16586 case OMPD_master:
16587 case OMPD_masked:
16588 case OMPD_critical:
16589 case OMPD_taskgroup:
16590 case OMPD_distribute:
16591 case OMPD_ordered:
16592 case OMPD_atomic:
16593 case OMPD_distribute_simd:
16594 case OMPD_requires:
16595 case OMPD_metadirective:
16596 llvm_unreachable("Unexpected OpenMP directive with grainsize-clause");
16597 case OMPD_unknown:
16598 default:
16599 llvm_unreachable("Unknown OpenMP directive");
16600 }
16601 break;
16602 case OMPC_novariants:
16603 case OMPC_nocontext:
16604 switch (DKind) {
16605 case OMPD_dispatch:
16606 CaptureRegion = OMPD_task;
16607 break;
16608 default:
16609 llvm_unreachable("Unexpected OpenMP directive");
16610 }
16611 break;
16612 case OMPC_filter:
16613 // Do not capture filter-clause expressions.
16614 break;
16615 case OMPC_when:
16616 if (DKind == OMPD_metadirective) {
16617 CaptureRegion = OMPD_metadirective;
16618 } else if (DKind == OMPD_unknown) {
16619 llvm_unreachable("Unknown OpenMP directive");
16620 } else {
16621 llvm_unreachable("Unexpected OpenMP directive with when clause");
16622 }
16623 break;
16624 case OMPC_firstprivate:
16625 case OMPC_lastprivate:
16626 case OMPC_reduction:
16627 case OMPC_task_reduction:
16628 case OMPC_in_reduction:
16629 case OMPC_linear:
16630 case OMPC_default:
16631 case OMPC_proc_bind:
16632 case OMPC_safelen:
16633 case OMPC_simdlen:
16634 case OMPC_sizes:
16635 case OMPC_allocator:
16636 case OMPC_collapse:
16637 case OMPC_private:
16638 case OMPC_shared:
16639 case OMPC_aligned:
16640 case OMPC_copyin:
16641 case OMPC_copyprivate:
16642 case OMPC_ordered:
16643 case OMPC_nowait:
16644 case OMPC_untied:
16645 case OMPC_mergeable:
16646 case OMPC_threadprivate:
16647 case OMPC_allocate:
16648 case OMPC_flush:
16649 case OMPC_depobj:
16650 case OMPC_read:
16651 case OMPC_write:
16652 case OMPC_update:
16653 case OMPC_capture:
16654 case OMPC_compare:
16655 case OMPC_seq_cst:
16656 case OMPC_acq_rel:
16657 case OMPC_acquire:
16658 case OMPC_release:
16659 case OMPC_relaxed:
16660 case OMPC_depend:
16661 case OMPC_threads:
16662 case OMPC_simd:
16663 case OMPC_map:
16664 case OMPC_nogroup:
16665 case OMPC_hint:
16666 case OMPC_defaultmap:
16667 case OMPC_unknown:
16668 case OMPC_uniform:
16669 case OMPC_to:
16670 case OMPC_from:
16671 case OMPC_use_device_ptr:
16672 case OMPC_use_device_addr:
16673 case OMPC_is_device_ptr:
16674 case OMPC_unified_address:
16675 case OMPC_unified_shared_memory:
16676 case OMPC_reverse_offload:
16677 case OMPC_dynamic_allocators:
16678 case OMPC_atomic_default_mem_order:
16679 case OMPC_device_type:
16680 case OMPC_match:
16681 case OMPC_nontemporal:
16682 case OMPC_order:
16683 case OMPC_at:
16684 case OMPC_severity:
16685 case OMPC_message:
16686 case OMPC_destroy:
16687 case OMPC_detach:
16688 case OMPC_inclusive:
16689 case OMPC_exclusive:
16690 case OMPC_uses_allocators:
16691 case OMPC_affinity:
16692 case OMPC_bind:
16693 default:
16694 llvm_unreachable("Unexpected OpenMP clause.");
16695 }
16696 return CaptureRegion;
16697}
16698
16700 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
16701 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
16702 SourceLocation ColonLoc, SourceLocation EndLoc) {
16703 Expr *ValExpr = Condition;
16704 Stmt *HelperValStmt = nullptr;
16705 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16706 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16707 !Condition->isInstantiationDependent() &&
16708 !Condition->containsUnexpandedParameterPack()) {
16710 if (Val.isInvalid())
16711 return nullptr;
16712
16713 ValExpr = Val.get();
16714
16715 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16716 CaptureRegion = getOpenMPCaptureRegionForClause(
16717 DKind, OMPC_if, getLangOpts().OpenMP, NameModifier);
16718 if (CaptureRegion != OMPD_unknown &&
16720 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16721 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16722 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16723 HelperValStmt = buildPreInits(getASTContext(), Captures);
16724 }
16725 }
16726
16727 return new (getASTContext())
16728 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16729 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16730}
16731
16733 SourceLocation StartLoc,
16734 SourceLocation LParenLoc,
16735 SourceLocation EndLoc) {
16736 Expr *ValExpr = Condition;
16737 Stmt *HelperValStmt = nullptr;
16738 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16739 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16740 !Condition->isInstantiationDependent() &&
16741 !Condition->containsUnexpandedParameterPack()) {
16743 if (Val.isInvalid())
16744 return nullptr;
16745
16746 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
16747
16748 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16749 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final,
16750 getLangOpts().OpenMP);
16751 if (CaptureRegion != OMPD_unknown &&
16753 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16754 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16755 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16756 HelperValStmt = buildPreInits(getASTContext(), Captures);
16757 }
16758 }
16759
16760 return new (getASTContext()) OMPFinalClause(
16761 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16762}
16763
16766 Expr *Op) {
16767 if (!Op)
16768 return ExprError();
16769
16770 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
16771 public:
16772 IntConvertDiagnoser()
16773 : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {}
16774 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
16775 QualType T) override {
16776 return S.Diag(Loc, diag::err_omp_not_integral) << T;
16777 }
16778 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
16779 QualType T) override {
16780 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
16781 }
16782 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
16783 QualType T,
16784 QualType ConvTy) override {
16785 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
16786 }
16787 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
16788 QualType ConvTy) override {
16789 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16790 << ConvTy->isEnumeralType() << ConvTy;
16791 }
16792 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
16793 QualType T) override {
16794 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
16795 }
16796 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
16797 QualType ConvTy) override {
16798 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16799 << ConvTy->isEnumeralType() << ConvTy;
16800 }
16801 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
16802 QualType) override {
16803 llvm_unreachable("conversion functions are permitted");
16804 }
16805 } ConvertDiagnoser;
16806 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16807}
16808
16809static bool
16811 bool StrictlyPositive, bool BuildCapture = false,
16812 OpenMPDirectiveKind DKind = OMPD_unknown,
16813 OpenMPDirectiveKind *CaptureRegion = nullptr,
16814 Stmt **HelperValStmt = nullptr) {
16815 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
16816 !ValExpr->isInstantiationDependent()) {
16817 SourceLocation Loc = ValExpr->getExprLoc();
16819 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
16820 if (Value.isInvalid())
16821 return false;
16822
16823 ValExpr = Value.get();
16824 // The expression must evaluate to a non-negative integer value.
16825 if (std::optional<llvm::APSInt> Result =
16826 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
16827 if (Result->isSigned() &&
16828 !((!StrictlyPositive && Result->isNonNegative()) ||
16829 (StrictlyPositive && Result->isStrictlyPositive()))) {
16830 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
16831 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16832 << ValExpr->getSourceRange();
16833 return false;
16834 }
16835 }
16836 if (!BuildCapture)
16837 return true;
16838 *CaptureRegion =
16839 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
16840 if (*CaptureRegion != OMPD_unknown &&
16841 !SemaRef.CurContext->isDependentContext()) {
16842 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16843 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16844 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16845 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
16846 }
16847 }
16848 return true;
16849}
16850
16852 SourceLocation StartLoc,
16853 SourceLocation LParenLoc,
16854 SourceLocation EndLoc) {
16855 Expr *ValExpr = NumThreads;
16856 Stmt *HelperValStmt = nullptr;
16857
16858 // OpenMP [2.5, Restrictions]
16859 // The num_threads expression must evaluate to a positive integer value.
16860 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads,
16861 /*StrictlyPositive=*/true))
16862 return nullptr;
16863
16864 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16866 DKind, OMPC_num_threads, getLangOpts().OpenMP);
16867 if (CaptureRegion != OMPD_unknown &&
16869 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16870 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16871 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16872 HelperValStmt = buildPreInits(getASTContext(), Captures);
16873 }
16874
16875 return new (getASTContext()) OMPNumThreadsClause(
16876 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16877}
16878
16880 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
16881 bool SuppressExprDiags) {
16882 if (!E)
16883 return ExprError();
16884 if (E->isValueDependent() || E->isTypeDependent() ||
16886 return E;
16887
16888 llvm::APSInt Result;
16889 ExprResult ICE;
16890 if (SuppressExprDiags) {
16891 // Use a custom diagnoser that suppresses 'note' diagnostics about the
16892 // expression.
16893 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
16894 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
16896 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
16897 llvm_unreachable("Diagnostic suppressed");
16898 }
16899 } Diagnoser;
16900 ICE = SemaRef.VerifyIntegerConstantExpression(E, &Result, Diagnoser,
16902 } else {
16904 /*FIXME*/ Sema::AllowFold);
16905 }
16906 if (ICE.isInvalid())
16907 return ExprError();
16908
16909 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
16910 (!StrictlyPositive && !Result.isNonNegative())) {
16911 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
16912 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16913 << E->getSourceRange();
16914 return ExprError();
16915 }
16916 if ((CKind == OMPC_aligned || CKind == OMPC_align) && !Result.isPowerOf2()) {
16917 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
16918 << E->getSourceRange();
16919 return ExprError();
16920 }
16921 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
16922 DSAStack->setAssociatedLoops(Result.getExtValue());
16923 else if (CKind == OMPC_ordered)
16924 DSAStack->setAssociatedLoops(Result.getExtValue());
16925 return ICE;
16926}
16927
16929 SourceLocation StartLoc,
16930 SourceLocation LParenLoc,
16931 SourceLocation EndLoc) {
16932 // OpenMP [2.8.1, simd construct, Description]
16933 // The parameter of the safelen clause must be a constant
16934 // positive integer expression.
16935 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
16936 if (Safelen.isInvalid())
16937 return nullptr;
16938 return new (getASTContext())
16939 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
16940}
16941
16943 SourceLocation StartLoc,
16944 SourceLocation LParenLoc,
16945 SourceLocation EndLoc) {
16946 // OpenMP [2.8.1, simd construct, Description]
16947 // The parameter of the simdlen clause must be a constant
16948 // positive integer expression.
16949 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
16950 if (Simdlen.isInvalid())
16951 return nullptr;
16952 return new (getASTContext())
16953 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
16954}
16955
16956/// Tries to find omp_allocator_handle_t type.
16958 DSAStackTy *Stack) {
16959 if (!Stack->getOMPAllocatorHandleT().isNull())
16960 return true;
16961
16962 // Set the allocator handle type.
16963 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
16964 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
16965 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
16966 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16967 << "omp_allocator_handle_t";
16968 return false;
16969 }
16970 QualType AllocatorHandleEnumTy = PT.get();
16971 AllocatorHandleEnumTy.addConst();
16972 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
16973
16974 // Fill the predefined allocator map.
16975 bool ErrorFound = false;
16976 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
16977 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
16978 StringRef Allocator =
16979 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
16980 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
16981 auto *VD = dyn_cast_or_null<ValueDecl>(
16982 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
16983 if (!VD) {
16984 ErrorFound = true;
16985 break;
16986 }
16987 QualType AllocatorType =
16989 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
16990 if (!Res.isUsable()) {
16991 ErrorFound = true;
16992 break;
16993 }
16994 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
16996 /* AllowExplicit */ true);
16997 if (!Res.isUsable()) {
16998 ErrorFound = true;
16999 break;
17000 }
17001 Stack->setAllocator(AllocatorKind, Res.get());
17002 }
17003 if (ErrorFound) {
17004 S.Diag(Loc, diag::err_omp_implied_type_not_found)
17005 << "omp_allocator_handle_t";
17006 return false;
17007 }
17008
17009 return true;
17010}
17011
17013 SourceLocation StartLoc,
17014 SourceLocation LParenLoc,
17015 SourceLocation EndLoc) {
17016 // OpenMP [2.11.3, allocate Directive, Description]
17017 // allocator is an expression of omp_allocator_handle_t type.
17019 return nullptr;
17020
17022 if (Allocator.isInvalid())
17023 return nullptr;
17025 Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
17027 /*AllowExplicit=*/true);
17028 if (Allocator.isInvalid())
17029 return nullptr;
17030 return new (getASTContext())
17031 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
17032}
17033
17035 SourceLocation StartLoc,
17036 SourceLocation LParenLoc,
17037 SourceLocation EndLoc) {
17038 // OpenMP [2.7.1, loop construct, Description]
17039 // OpenMP [2.8.1, simd construct, Description]
17040 // OpenMP [2.9.6, distribute construct, Description]
17041 // The parameter of the collapse clause must be a constant
17042 // positive integer expression.
17043 ExprResult NumForLoopsResult =
17044 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
17045 if (NumForLoopsResult.isInvalid())
17046 return nullptr;
17047 return new (getASTContext())
17048 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
17049}
17050
17052 SourceLocation EndLoc,
17053 SourceLocation LParenLoc,
17054 Expr *NumForLoops) {
17055 // OpenMP [2.7.1, loop construct, Description]
17056 // OpenMP [2.8.1, simd construct, Description]
17057 // OpenMP [2.9.6, distribute construct, Description]
17058 // The parameter of the ordered clause must be a constant
17059 // positive integer expression if any.
17060 if (NumForLoops && LParenLoc.isValid()) {
17061 ExprResult NumForLoopsResult =
17062 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
17063 if (NumForLoopsResult.isInvalid())
17064 return nullptr;
17065 NumForLoops = NumForLoopsResult.get();
17066 } else {
17067 NumForLoops = nullptr;
17068 }
17069 auto *Clause =
17071 NumForLoops ? DSAStack->getAssociatedLoops() : 0,
17072 StartLoc, LParenLoc, EndLoc);
17073 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
17074 return Clause;
17075}
17076
17078 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
17079 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17080 OMPClause *Res = nullptr;
17081 switch (Kind) {
17082 case OMPC_default:
17083 Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument),
17084 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17085 break;
17086 case OMPC_proc_bind:
17087 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
17088 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17089 break;
17090 case OMPC_atomic_default_mem_order:
17092 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
17093 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17094 break;
17095 case OMPC_fail:
17097 static_cast<OpenMPClauseKind>(Argument),
17098 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17099 break;
17100 case OMPC_update:
17101 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
17102 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17103 break;
17104 case OMPC_bind:
17105 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
17106 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17107 break;
17108 case OMPC_at:
17109 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
17110 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17111 break;
17112 case OMPC_severity:
17114 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
17115 LParenLoc, EndLoc);
17116 break;
17117 case OMPC_if:
17118 case OMPC_final:
17119 case OMPC_num_threads:
17120 case OMPC_safelen:
17121 case OMPC_simdlen:
17122 case OMPC_sizes:
17123 case OMPC_allocator:
17124 case OMPC_collapse:
17125 case OMPC_schedule:
17126 case OMPC_private:
17127 case OMPC_firstprivate:
17128 case OMPC_lastprivate:
17129 case OMPC_shared:
17130 case OMPC_reduction:
17131 case OMPC_task_reduction:
17132 case OMPC_in_reduction:
17133 case OMPC_linear:
17134 case OMPC_aligned:
17135 case OMPC_copyin:
17136 case OMPC_copyprivate:
17137 case OMPC_ordered:
17138 case OMPC_nowait:
17139 case OMPC_untied:
17140 case OMPC_mergeable:
17141 case OMPC_threadprivate:
17142 case OMPC_allocate:
17143 case OMPC_flush:
17144 case OMPC_depobj:
17145 case OMPC_read:
17146 case OMPC_write:
17147 case OMPC_capture:
17148 case OMPC_compare:
17149 case OMPC_seq_cst:
17150 case OMPC_acq_rel:
17151 case OMPC_acquire:
17152 case OMPC_release:
17153 case OMPC_relaxed:
17154 case OMPC_depend:
17155 case OMPC_device:
17156 case OMPC_threads:
17157 case OMPC_simd:
17158 case OMPC_map:
17159 case OMPC_num_teams:
17160 case OMPC_thread_limit:
17161 case OMPC_priority:
17162 case OMPC_grainsize:
17163 case OMPC_nogroup:
17164 case OMPC_num_tasks:
17165 case OMPC_hint:
17166 case OMPC_dist_schedule:
17167 case OMPC_defaultmap:
17168 case OMPC_unknown:
17169 case OMPC_uniform:
17170 case OMPC_to:
17171 case OMPC_from:
17172 case OMPC_use_device_ptr:
17173 case OMPC_use_device_addr:
17174 case OMPC_is_device_ptr:
17175 case OMPC_has_device_addr:
17176 case OMPC_unified_address:
17177 case OMPC_unified_shared_memory:
17178 case OMPC_reverse_offload:
17179 case OMPC_dynamic_allocators:
17180 case OMPC_device_type:
17181 case OMPC_match:
17182 case OMPC_nontemporal:
17183 case OMPC_destroy:
17184 case OMPC_novariants:
17185 case OMPC_nocontext:
17186 case OMPC_detach:
17187 case OMPC_inclusive:
17188 case OMPC_exclusive:
17189 case OMPC_uses_allocators:
17190 case OMPC_affinity:
17191 case OMPC_when:
17192 case OMPC_message:
17193 default:
17194 llvm_unreachable("Clause is not allowed.");
17195 }
17196 return Res;
17197}
17198
17199static std::string
17201 ArrayRef<unsigned> Exclude = std::nullopt) {
17202 SmallString<256> Buffer;
17203 llvm::raw_svector_ostream Out(Buffer);
17204 unsigned Skipped = Exclude.size();
17205 for (unsigned I = First; I < Last; ++I) {
17206 if (llvm::is_contained(Exclude, I)) {
17207 --Skipped;
17208 continue;
17209 }
17210 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
17211 if (I + Skipped + 2 == Last)
17212 Out << " or ";
17213 else if (I + Skipped + 1 != Last)
17214 Out << ", ";
17215 }
17216 return std::string(Out.str());
17217}
17218
17220 SourceLocation KindKwLoc,
17221 SourceLocation StartLoc,
17222 SourceLocation LParenLoc,
17223 SourceLocation EndLoc) {
17224 if (Kind == OMP_DEFAULT_unknown) {
17225 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17226 << getListOfPossibleValues(OMPC_default, /*First=*/0,
17227 /*Last=*/unsigned(OMP_DEFAULT_unknown))
17228 << getOpenMPClauseName(OMPC_default);
17229 return nullptr;
17230 }
17231
17232 switch (Kind) {
17233 case OMP_DEFAULT_none:
17234 DSAStack->setDefaultDSANone(KindKwLoc);
17235 break;
17236 case OMP_DEFAULT_shared:
17237 DSAStack->setDefaultDSAShared(KindKwLoc);
17238 break;
17239 case OMP_DEFAULT_firstprivate:
17240 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
17241 break;
17242 case OMP_DEFAULT_private:
17243 DSAStack->setDefaultDSAPrivate(KindKwLoc);
17244 break;
17245 default:
17246 llvm_unreachable("DSA unexpected in OpenMP default clause");
17247 }
17248
17249 return new (getASTContext())
17250 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17251}
17252
17254 SourceLocation KindKwLoc,
17255 SourceLocation StartLoc,
17256 SourceLocation LParenLoc,
17257 SourceLocation EndLoc) {
17258 if (Kind == OMP_PROC_BIND_unknown) {
17259 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17260 << getListOfPossibleValues(OMPC_proc_bind,
17261 /*First=*/unsigned(OMP_PROC_BIND_master),
17262 /*Last=*/
17263 unsigned(getLangOpts().OpenMP > 50
17264 ? OMP_PROC_BIND_primary
17265 : OMP_PROC_BIND_spread) +
17266 1)
17267 << getOpenMPClauseName(OMPC_proc_bind);
17268 return nullptr;
17269 }
17270 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
17271 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17272 << getListOfPossibleValues(OMPC_proc_bind,
17273 /*First=*/unsigned(OMP_PROC_BIND_master),
17274 /*Last=*/
17275 unsigned(OMP_PROC_BIND_spread) + 1)
17276 << getOpenMPClauseName(OMPC_proc_bind);
17277 return new (getASTContext())
17278 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17279}
17280
17283 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17285 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17287 OMPC_atomic_default_mem_order, /*First=*/0,
17289 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
17290 return nullptr;
17291 }
17293 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17294}
17295
17297 SourceLocation KindKwLoc,
17298 SourceLocation StartLoc,
17299 SourceLocation LParenLoc,
17300 SourceLocation EndLoc) {
17301 if (Kind == OMPC_AT_unknown) {
17302 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17303 << getListOfPossibleValues(OMPC_at, /*First=*/0,
17304 /*Last=*/OMPC_AT_unknown)
17305 << getOpenMPClauseName(OMPC_at);
17306 return nullptr;
17307 }
17308 return new (getASTContext())
17309 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17310}
17311
17313 SourceLocation KindKwLoc,
17314 SourceLocation StartLoc,
17315 SourceLocation LParenLoc,
17316 SourceLocation EndLoc) {
17317 if (Kind == OMPC_SEVERITY_unknown) {
17318 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17319 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
17320 /*Last=*/OMPC_SEVERITY_unknown)
17321 << getOpenMPClauseName(OMPC_severity);
17322 return nullptr;
17323 }
17324 return new (getASTContext())
17325 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17326}
17327
17329 SourceLocation StartLoc,
17330 SourceLocation LParenLoc,
17331 SourceLocation EndLoc) {
17332 assert(ME && "NULL expr in Message clause");
17333 if (!isa<StringLiteral>(ME)) {
17334 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
17335 << getOpenMPClauseName(OMPC_message);
17336 return nullptr;
17337 }
17338 return new (getASTContext())
17339 OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc);
17340}
17341
17344 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
17345 SourceLocation KindLoc, SourceLocation EndLoc) {
17346 if (Kind != OMPC_ORDER_concurrent ||
17347 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
17348 // Kind should be concurrent,
17349 // Modifiers introduced in OpenMP 5.1
17350 static_assert(OMPC_ORDER_unknown > 0,
17351 "OMPC_ORDER_unknown not greater than 0");
17352
17353 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17354 << getListOfPossibleValues(OMPC_order,
17355 /*First=*/0,
17356 /*Last=*/OMPC_ORDER_unknown)
17357 << getOpenMPClauseName(OMPC_order);
17358 return nullptr;
17359 }
17360 if (getLangOpts().OpenMP >= 51) {
17361 if (Modifier == OMPC_ORDER_MODIFIER_unknown && MLoc.isValid()) {
17362 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17363 << getListOfPossibleValues(OMPC_order,
17364 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
17365 /*Last=*/OMPC_ORDER_MODIFIER_last)
17366 << getOpenMPClauseName(OMPC_order);
17367 } else {
17368 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
17369 if (DSAStack->getCurScope()) {
17370 // mark the current scope with 'order' flag
17371 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
17372 DSAStack->getCurScope()->setFlags(existingFlags |
17374 }
17375 }
17376 }
17377 return new (getASTContext()) OMPOrderClause(
17378 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
17379}
17380
17382 SourceLocation KindKwLoc,
17383 SourceLocation StartLoc,
17384 SourceLocation LParenLoc,
17385 SourceLocation EndLoc) {
17386 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
17387 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
17388 SmallVector<unsigned> Except = {
17389 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
17390 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
17391 if (getLangOpts().OpenMP < 51)
17392 Except.push_back(OMPC_DEPEND_inoutset);
17393 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17394 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
17395 /*Last=*/OMPC_DEPEND_unknown, Except)
17396 << getOpenMPClauseName(OMPC_update);
17397 return nullptr;
17398 }
17399 return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc,
17400 KindKwLoc, Kind, EndLoc);
17401}
17402
17404 SourceLocation StartLoc,
17405 SourceLocation LParenLoc,
17406 SourceLocation EndLoc) {
17407 for (Expr *SizeExpr : SizeExprs) {
17409 SizeExpr, OMPC_sizes, /*StrictlyPositive=*/true);
17410 if (!NumForLoopsResult.isUsable())
17411 return nullptr;
17412 }
17413
17414 DSAStack->setAssociatedLoops(SizeExprs.size());
17415 return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17416 SizeExprs);
17417}
17418
17420 SourceLocation EndLoc) {
17421 return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc);
17422}
17423
17425 SourceLocation StartLoc,
17426 SourceLocation LParenLoc,
17427 SourceLocation EndLoc) {
17428 if (FactorExpr) {
17429 // If an argument is specified, it must be a constant (or an unevaluated
17430 // template expression).
17432 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
17433 if (FactorResult.isInvalid())
17434 return nullptr;
17435 FactorExpr = FactorResult.get();
17436 }
17437
17438 return OMPPartialClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17439 FactorExpr);
17440}
17441
17443 SourceLocation LParenLoc,
17444 SourceLocation EndLoc) {
17445 ExprResult AlignVal;
17446 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
17447 if (AlignVal.isInvalid())
17448 return nullptr;
17449 return OMPAlignClause::Create(getASTContext(), AlignVal.get(), StartLoc,
17450 LParenLoc, EndLoc);
17451}
17452
17455 SourceLocation StartLoc, SourceLocation LParenLoc,
17456 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
17457 SourceLocation EndLoc) {
17458 OMPClause *Res = nullptr;
17459 switch (Kind) {
17460 case OMPC_schedule:
17461 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
17462 assert(Argument.size() == NumberOfElements &&
17463 ArgumentLoc.size() == NumberOfElements);
17465 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
17466 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
17467 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
17468 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
17469 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
17470 break;
17471 case OMPC_if:
17472 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17473 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
17474 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
17475 DelimLoc, EndLoc);
17476 break;
17477 case OMPC_dist_schedule:
17479 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
17480 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
17481 break;
17482 case OMPC_defaultmap:
17483 enum { Modifier, DefaultmapKind };
17485 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
17486 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
17487 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
17488 EndLoc);
17489 break;
17490 case OMPC_order:
17491 enum { OrderModifier, OrderKind };
17493 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
17494 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
17495 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
17496 break;
17497 case OMPC_device:
17498 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17500 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
17501 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17502 break;
17503 case OMPC_grainsize:
17504 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17505 "Modifier for grainsize clause and its location are expected.");
17507 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
17508 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17509 break;
17510 case OMPC_num_tasks:
17511 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17512 "Modifier for num_tasks clause and its location are expected.");
17514 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
17515 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17516 break;
17517 case OMPC_final:
17518 case OMPC_num_threads:
17519 case OMPC_safelen:
17520 case OMPC_simdlen:
17521 case OMPC_sizes:
17522 case OMPC_allocator:
17523 case OMPC_collapse:
17524 case OMPC_default:
17525 case OMPC_proc_bind:
17526 case OMPC_private:
17527 case OMPC_firstprivate:
17528 case OMPC_lastprivate:
17529 case OMPC_shared:
17530 case OMPC_reduction:
17531 case OMPC_task_reduction:
17532 case OMPC_in_reduction:
17533 case OMPC_linear:
17534 case OMPC_aligned:
17535 case OMPC_copyin:
17536 case OMPC_copyprivate:
17537 case OMPC_ordered:
17538 case OMPC_nowait:
17539 case OMPC_untied:
17540 case OMPC_mergeable:
17541 case OMPC_threadprivate:
17542 case OMPC_allocate:
17543 case OMPC_flush:
17544 case OMPC_depobj:
17545 case OMPC_read:
17546 case OMPC_write:
17547 case OMPC_update:
17548 case OMPC_capture:
17549 case OMPC_compare:
17550 case OMPC_seq_cst:
17551 case OMPC_acq_rel:
17552 case OMPC_acquire:
17553 case OMPC_release:
17554 case OMPC_relaxed:
17555 case OMPC_depend:
17556 case OMPC_threads:
17557 case OMPC_simd:
17558 case OMPC_map:
17559 case OMPC_num_teams:
17560 case OMPC_thread_limit:
17561 case OMPC_priority:
17562 case OMPC_nogroup:
17563 case OMPC_hint:
17564 case OMPC_unknown:
17565 case OMPC_uniform:
17566 case OMPC_to:
17567 case OMPC_from:
17568 case OMPC_use_device_ptr:
17569 case OMPC_use_device_addr:
17570 case OMPC_is_device_ptr:
17571 case OMPC_has_device_addr:
17572 case OMPC_unified_address:
17573 case OMPC_unified_shared_memory:
17574 case OMPC_reverse_offload:
17575 case OMPC_dynamic_allocators:
17576 case OMPC_atomic_default_mem_order:
17577 case OMPC_device_type:
17578 case OMPC_match:
17579 case OMPC_nontemporal:
17580 case OMPC_at:
17581 case OMPC_severity:
17582 case OMPC_message:
17583 case OMPC_destroy:
17584 case OMPC_novariants:
17585 case OMPC_nocontext:
17586 case OMPC_detach:
17587 case OMPC_inclusive:
17588 case OMPC_exclusive:
17589 case OMPC_uses_allocators:
17590 case OMPC_affinity:
17591 case OMPC_when:
17592 case OMPC_bind:
17593 default:
17594 llvm_unreachable("Clause is not allowed.");
17595 }
17596 return Res;
17597}
17598
17601 SourceLocation M1Loc, SourceLocation M2Loc) {
17602 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
17603 SmallVector<unsigned, 2> Excluded;
17605 Excluded.push_back(M2);
17606 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
17607 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
17608 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
17609 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
17610 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
17611 << getListOfPossibleValues(OMPC_schedule,
17612 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
17614 Excluded)
17615 << getOpenMPClauseName(OMPC_schedule);
17616 return true;
17617 }
17618 return false;
17619}
17620
17623 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
17624 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
17625 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
17626 if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) ||
17627 checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc))
17628 return nullptr;
17629 // OpenMP, 2.7.1, Loop Construct, Restrictions
17630 // Either the monotonic modifier or the nonmonotonic modifier can be specified
17631 // but not both.
17632 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
17633 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
17634 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
17635 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
17636 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
17637 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
17638 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
17639 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
17640 return nullptr;
17641 }
17642 if (Kind == OMPC_SCHEDULE_unknown) {
17643 std::string Values;
17644 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
17645 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
17646 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17648 Exclude);
17649 } else {
17650 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17651 /*Last=*/OMPC_SCHEDULE_unknown);
17652 }
17653 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17654 << Values << getOpenMPClauseName(OMPC_schedule);
17655 return nullptr;
17656 }
17657 // OpenMP, 2.7.1, Loop Construct, Restrictions
17658 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
17659 // schedule(guided).
17660 // OpenMP 5.0 does not have this restriction.
17661 if (getLangOpts().OpenMP < 50 &&
17662 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
17663 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
17664 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
17665 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
17666 diag::err_omp_schedule_nonmonotonic_static);
17667 return nullptr;
17668 }
17669 Expr *ValExpr = ChunkSize;
17670 Stmt *HelperValStmt = nullptr;
17671 if (ChunkSize) {
17672 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
17673 !ChunkSize->isInstantiationDependent() &&
17674 !ChunkSize->containsUnexpandedParameterPack()) {
17675 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
17676 ExprResult Val =
17677 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
17678 if (Val.isInvalid())
17679 return nullptr;
17680
17681 ValExpr = Val.get();
17682
17683 // OpenMP [2.7.1, Restrictions]
17684 // chunk_size must be a loop invariant integer expression with a positive
17685 // value.
17686 if (std::optional<llvm::APSInt> Result =
17688 if (Result->isSigned() && !Result->isStrictlyPositive()) {
17689 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
17690 << "schedule" << 1 << ChunkSize->getSourceRange();
17691 return nullptr;
17692 }
17694 DSAStack->getCurrentDirective(), OMPC_schedule,
17695 getLangOpts().OpenMP) != OMPD_unknown &&
17697 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17698 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17699 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17700 HelperValStmt = buildPreInits(getASTContext(), Captures);
17701 }
17702 }
17703 }
17704
17705 return new (getASTContext())
17706 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
17707 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
17708}
17709
17711 SourceLocation StartLoc,
17712 SourceLocation EndLoc) {
17713 OMPClause *Res = nullptr;
17714 switch (Kind) {
17715 case OMPC_ordered:
17716 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
17717 break;
17718 case OMPC_nowait:
17719 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
17720 break;
17721 case OMPC_untied:
17722 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
17723 break;
17724 case OMPC_mergeable:
17725 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
17726 break;
17727 case OMPC_read:
17728 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
17729 break;
17730 case OMPC_write:
17731 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
17732 break;
17733 case OMPC_update:
17734 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
17735 break;
17736 case OMPC_capture:
17737 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
17738 break;
17739 case OMPC_compare:
17740 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
17741 break;
17742 case OMPC_fail:
17743 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
17744 break;
17745 case OMPC_seq_cst:
17746 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
17747 break;
17748 case OMPC_acq_rel:
17749 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
17750 break;
17751 case OMPC_acquire:
17752 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
17753 break;
17754 case OMPC_release:
17755 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
17756 break;
17757 case OMPC_relaxed:
17758 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
17759 break;
17760 case OMPC_weak:
17761 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
17762 break;
17763 case OMPC_threads:
17764 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
17765 break;
17766 case OMPC_simd:
17767 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
17768 break;
17769 case OMPC_nogroup:
17770 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
17771 break;
17772 case OMPC_unified_address:
17773 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
17774 break;
17775 case OMPC_unified_shared_memory:
17776 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17777 break;
17778 case OMPC_reverse_offload:
17779 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
17780 break;
17781 case OMPC_dynamic_allocators:
17782 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
17783 break;
17784 case OMPC_destroy:
17785 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
17786 /*LParenLoc=*/SourceLocation(),
17787 /*VarLoc=*/SourceLocation(), EndLoc);
17788 break;
17789 case OMPC_full:
17790 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
17791 break;
17792 case OMPC_partial:
17793 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
17794 break;
17795 case OMPC_ompx_bare:
17796 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
17797 break;
17798 case OMPC_if:
17799 case OMPC_final:
17800 case OMPC_num_threads:
17801 case OMPC_safelen:
17802 case OMPC_simdlen:
17803 case OMPC_sizes:
17804 case OMPC_allocator:
17805 case OMPC_collapse:
17806 case OMPC_schedule:
17807 case OMPC_private:
17808 case OMPC_firstprivate:
17809 case OMPC_lastprivate:
17810 case OMPC_shared:
17811 case OMPC_reduction:
17812 case OMPC_task_reduction:
17813 case OMPC_in_reduction:
17814 case OMPC_linear:
17815 case OMPC_aligned:
17816 case OMPC_copyin:
17817 case OMPC_copyprivate:
17818 case OMPC_default:
17819 case OMPC_proc_bind:
17820 case OMPC_threadprivate:
17821 case OMPC_allocate:
17822 case OMPC_flush:
17823 case OMPC_depobj:
17824 case OMPC_depend:
17825 case OMPC_device:
17826 case OMPC_map:
17827 case OMPC_num_teams:
17828 case OMPC_thread_limit:
17829 case OMPC_priority:
17830 case OMPC_grainsize:
17831 case OMPC_num_tasks:
17832 case OMPC_hint:
17833 case OMPC_dist_schedule:
17834 case OMPC_defaultmap:
17835 case OMPC_unknown:
17836 case OMPC_uniform:
17837 case OMPC_to:
17838 case OMPC_from:
17839 case OMPC_use_device_ptr:
17840 case OMPC_use_device_addr:
17841 case OMPC_is_device_ptr:
17842 case OMPC_has_device_addr:
17843 case OMPC_atomic_default_mem_order:
17844 case OMPC_device_type:
17845 case OMPC_match:
17846 case OMPC_nontemporal:
17847 case OMPC_order:
17848 case OMPC_at:
17849 case OMPC_severity:
17850 case OMPC_message:
17851 case OMPC_novariants:
17852 case OMPC_nocontext:
17853 case OMPC_detach:
17854 case OMPC_inclusive:
17855 case OMPC_exclusive:
17856 case OMPC_uses_allocators:
17857 case OMPC_affinity:
17858 case OMPC_when:
17859 case OMPC_ompx_dyn_cgroup_mem:
17860 default:
17861 llvm_unreachable("Clause is not allowed.");
17862 }
17863 return Res;
17864}
17865
17867 SourceLocation EndLoc) {
17868 DSAStack->setNowaitRegion();
17869 return new (getASTContext()) OMPNowaitClause(StartLoc, EndLoc);
17870}
17871
17873 SourceLocation EndLoc) {
17874 DSAStack->setUntiedRegion();
17875 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
17876}
17877
17879 SourceLocation EndLoc) {
17880 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
17881}
17882
17884 SourceLocation EndLoc) {
17885 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
17886}
17887
17889 SourceLocation EndLoc) {
17890 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
17891}
17892
17894 SourceLocation EndLoc) {
17895 return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc);
17896}
17897
17899 SourceLocation EndLoc) {
17900 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
17901}
17902
17904 SourceLocation EndLoc) {
17905 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
17906}
17907
17909 SourceLocation EndLoc) {
17910 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
17911}
17912
17914 SourceLocation KindLoc,
17915 SourceLocation StartLoc,
17916 SourceLocation LParenLoc,
17917 SourceLocation EndLoc) {
17918
17920 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
17921 return nullptr;
17922 }
17923 return new (getASTContext())
17924 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
17925}
17926
17928 SourceLocation EndLoc) {
17929 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
17930}
17931
17933 SourceLocation EndLoc) {
17934 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
17935}
17936
17938 SourceLocation EndLoc) {
17939 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
17940}
17941
17943 SourceLocation EndLoc) {
17944 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
17945}
17946
17948 SourceLocation EndLoc) {
17949 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
17950}
17951
17953 SourceLocation EndLoc) {
17954 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
17955}
17956
17958 SourceLocation EndLoc) {
17959 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
17960}
17961
17963 SourceLocation EndLoc) {
17964 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
17965}
17966
17968 SourceLocation EndLoc) {
17969 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
17970}
17971
17973 SourceLocation EndLoc) {
17974 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
17975}
17976
17977OMPClause *
17979 SourceLocation EndLoc) {
17980 return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17981}
17982
17984 SourceLocation EndLoc) {
17985 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
17986}
17987
17988OMPClause *
17990 SourceLocation EndLoc) {
17991 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
17992}
17993
17996 SourceLocation StartLoc,
17997 SourceLocation EndLoc) {
17998
17999 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18000 // At least one action-clause must appear on a directive.
18001 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
18002 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
18003 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
18004 << Expected << getOpenMPDirectiveName(OMPD_interop);
18005 return StmtError();
18006 }
18007
18008 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18009 // A depend clause can only appear on the directive if a targetsync
18010 // interop-type is present or the interop-var was initialized with
18011 // the targetsync interop-type.
18012
18013 // If there is any 'init' clause diagnose if there is no 'init' clause with
18014 // interop-type of 'targetsync'. Cases involving other directives cannot be
18015 // diagnosed.
18016 const OMPDependClause *DependClause = nullptr;
18017 bool HasInitClause = false;
18018 bool IsTargetSync = false;
18019 for (const OMPClause *C : Clauses) {
18020 if (IsTargetSync)
18021 break;
18022 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
18023 HasInitClause = true;
18024 if (InitClause->getIsTargetSync())
18025 IsTargetSync = true;
18026 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
18027 DependClause = DC;
18028 }
18029 }
18030 if (DependClause && HasInitClause && !IsTargetSync) {
18031 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
18032 return StmtError();
18033 }
18034
18035 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18036 // Each interop-var may be specified for at most one action-clause of each
18037 // interop construct.
18039 for (OMPClause *C : Clauses) {
18040 OpenMPClauseKind ClauseKind = C->getClauseKind();
18041 std::pair<ValueDecl *, bool> DeclResult;
18042 SourceLocation ELoc;
18043 SourceRange ERange;
18044
18045 if (ClauseKind == OMPC_init) {
18046 auto *E = cast<OMPInitClause>(C)->getInteropVar();
18047 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18048 } else if (ClauseKind == OMPC_use) {
18049 auto *E = cast<OMPUseClause>(C)->getInteropVar();
18050 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18051 } else if (ClauseKind == OMPC_destroy) {
18052 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
18053 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18054 }
18055
18056 if (DeclResult.first) {
18057 if (!InteropVars.insert(DeclResult.first).second) {
18058 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
18059 << DeclResult.first;
18060 return StmtError();
18061 }
18062 }
18063 }
18064
18065 return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc,
18066 Clauses);
18067}
18068
18069static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
18070 SourceLocation VarLoc,
18071 OpenMPClauseKind Kind) {
18072 SourceLocation ELoc;
18073 SourceRange ERange;
18074 Expr *RefExpr = InteropVarExpr;
18075 auto Res =
18076 getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
18077 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
18078
18079 if (Res.second) {
18080 // It will be analyzed later.
18081 return true;
18082 }
18083
18084 if (!Res.first)
18085 return false;
18086
18087 // Interop variable should be of type omp_interop_t.
18088 bool HasError = false;
18089 QualType InteropType;
18090 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
18091 VarLoc, Sema::LookupOrdinaryName);
18092 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
18093 NamedDecl *ND = Result.getFoundDecl();
18094 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
18095 InteropType = QualType(TD->getTypeForDecl(), 0);
18096 } else {
18097 HasError = true;
18098 }
18099 } else {
18100 HasError = true;
18101 }
18102
18103 if (HasError) {
18104 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
18105 << "omp_interop_t";
18106 return false;
18107 }
18108
18109 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
18110 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
18111 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
18112 return false;
18113 }
18114
18115 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18116 // The interop-var passed to init or destroy must be non-const.
18117 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
18118 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
18119 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
18120 << /*non-const*/ 1;
18121 return false;
18122 }
18123 return true;
18124}
18125
18127 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
18128 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
18129
18130 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init))
18131 return nullptr;
18132
18133 // Check prefer_type values. These foreign-runtime-id values are either
18134 // string literals or constant integral expressions.
18135 for (const Expr *E : InteropInfo.PreferTypes) {
18136 if (E->isValueDependent() || E->isTypeDependent() ||
18138 continue;
18140 continue;
18141 if (isa<StringLiteral>(E))
18142 continue;
18143 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
18144 return nullptr;
18145 }
18146
18147 return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo,
18148 StartLoc, LParenLoc, VarLoc, EndLoc);
18149}
18150
18152 SourceLocation StartLoc,
18153 SourceLocation LParenLoc,
18154 SourceLocation VarLoc,
18155 SourceLocation EndLoc) {
18156
18157 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use))
18158 return nullptr;
18159
18160 return new (getASTContext())
18161 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18162}
18163
18165 SourceLocation StartLoc,
18166 SourceLocation LParenLoc,
18167 SourceLocation VarLoc,
18168 SourceLocation EndLoc) {
18169 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
18170 DSAStack->getCurrentDirective() == OMPD_depobj) {
18171 Diag(StartLoc, diag::err_omp_expected_clause_argument)
18172 << getOpenMPClauseName(OMPC_destroy)
18173 << getOpenMPDirectiveName(OMPD_depobj);
18174 return nullptr;
18175 }
18176 if (InteropVar &&
18177 !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy))
18178 return nullptr;
18179
18180 return new (getASTContext())
18181 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18182}
18183
18185 SourceLocation StartLoc,
18186 SourceLocation LParenLoc,
18187 SourceLocation EndLoc) {
18188 Expr *ValExpr = Condition;
18189 Stmt *HelperValStmt = nullptr;
18190 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18191 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18192 !Condition->isInstantiationDependent() &&
18193 !Condition->containsUnexpandedParameterPack()) {
18195 if (Val.isInvalid())
18196 return nullptr;
18197
18198 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
18199
18200 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18201 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
18202 getLangOpts().OpenMP);
18203 if (CaptureRegion != OMPD_unknown &&
18205 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18206 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18207 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18208 HelperValStmt = buildPreInits(getASTContext(), Captures);
18209 }
18210 }
18211
18212 return new (getASTContext()) OMPNovariantsClause(
18213 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18214}
18215
18217 SourceLocation StartLoc,
18218 SourceLocation LParenLoc,
18219 SourceLocation EndLoc) {
18220 Expr *ValExpr = Condition;
18221 Stmt *HelperValStmt = nullptr;
18222 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18223 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18224 !Condition->isInstantiationDependent() &&
18225 !Condition->containsUnexpandedParameterPack()) {
18227 if (Val.isInvalid())
18228 return nullptr;
18229
18230 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
18231
18232 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18233 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext,
18234 getLangOpts().OpenMP);
18235 if (CaptureRegion != OMPD_unknown &&
18237 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18238 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18239 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18240 HelperValStmt = buildPreInits(getASTContext(), Captures);
18241 }
18242 }
18243
18244 return new (getASTContext()) OMPNocontextClause(
18245 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18246}
18247
18249 SourceLocation StartLoc,
18250 SourceLocation LParenLoc,
18251 SourceLocation EndLoc) {
18252 Expr *ValExpr = ThreadID;
18253 Stmt *HelperValStmt = nullptr;
18254
18255 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18256 OpenMPDirectiveKind CaptureRegion =
18257 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP);
18258 if (CaptureRegion != OMPD_unknown &&
18260 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18261 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18262 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18263 HelperValStmt = buildPreInits(getASTContext(), Captures);
18264 }
18265
18266 return new (getASTContext()) OMPFilterClause(
18267 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18268}
18269
18271 ArrayRef<Expr *> VarList,
18272 const OMPVarListLocTy &Locs,
18274 SourceLocation StartLoc = Locs.StartLoc;
18275 SourceLocation LParenLoc = Locs.LParenLoc;
18276 SourceLocation EndLoc = Locs.EndLoc;
18277 OMPClause *Res = nullptr;
18278 int ExtraModifier = Data.ExtraModifier;
18279 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
18280 SourceLocation ColonLoc = Data.ColonLoc;
18281 switch (Kind) {
18282 case OMPC_private:
18283 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18284 break;
18285 case OMPC_firstprivate:
18286 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18287 break;
18288 case OMPC_lastprivate:
18289 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
18290 "Unexpected lastprivate modifier.");
18292 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
18293 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
18294 break;
18295 case OMPC_shared:
18296 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
18297 break;
18298 case OMPC_reduction:
18299 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
18300 "Unexpected lastprivate modifier.");
18302 VarList, static_cast<OpenMPReductionClauseModifier>(ExtraModifier),
18303 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
18304 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18305 break;
18306 case OMPC_task_reduction:
18308 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18309 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18310 break;
18311 case OMPC_in_reduction:
18313 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18314 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18315 break;
18316 case OMPC_linear:
18317 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
18318 "Unexpected linear modifier.");
18320 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
18321 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
18322 ColonLoc, Data.StepModifierLoc, EndLoc);
18323 break;
18324 case OMPC_aligned:
18325 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
18326 LParenLoc, ColonLoc, EndLoc);
18327 break;
18328 case OMPC_copyin:
18329 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
18330 break;
18331 case OMPC_copyprivate:
18332 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18333 break;
18334 case OMPC_flush:
18335 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
18336 break;
18337 case OMPC_depend:
18338 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
18339 "Unexpected depend modifier.");
18341 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
18342 ColonLoc, Data.OmpAllMemoryLoc},
18343 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
18344 break;
18345 case OMPC_map:
18346 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
18347 "Unexpected map modifier.");
18349 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
18350 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
18351 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
18352 ExtraModifierLoc, ColonLoc, VarList, Locs);
18353 break;
18354 case OMPC_to:
18355 Res =
18356 ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc,
18357 Data.ReductionOrMapperIdScopeSpec,
18358 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
18359 break;
18360 case OMPC_from:
18361 Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc,
18362 Data.ReductionOrMapperIdScopeSpec,
18363 Data.ReductionOrMapperId, ColonLoc, VarList,
18364 Locs);
18365 break;
18366 case OMPC_use_device_ptr:
18367 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
18368 break;
18369 case OMPC_use_device_addr:
18370 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
18371 break;
18372 case OMPC_is_device_ptr:
18373 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
18374 break;
18375 case OMPC_has_device_addr:
18376 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
18377 break;
18378 case OMPC_allocate:
18379 Res = ActOnOpenMPAllocateClause(Data.DepModOrTailExpr, VarList, StartLoc,
18380 LParenLoc, ColonLoc, EndLoc);
18381 break;
18382 case OMPC_nontemporal:
18383 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
18384 break;
18385 case OMPC_inclusive:
18386 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18387 break;
18388 case OMPC_exclusive:
18389 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18390 break;
18391 case OMPC_affinity:
18392 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
18393 Data.DepModOrTailExpr, VarList);
18394 break;
18395 case OMPC_doacross:
18397 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
18398 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
18399 break;
18400 case OMPC_if:
18401 case OMPC_depobj:
18402 case OMPC_final:
18403 case OMPC_num_threads:
18404 case OMPC_safelen:
18405 case OMPC_simdlen:
18406 case OMPC_sizes:
18407 case OMPC_allocator:
18408 case OMPC_collapse:
18409 case OMPC_default:
18410 case OMPC_proc_bind:
18411 case OMPC_schedule:
18412 case OMPC_ordered:
18413 case OMPC_nowait:
18414 case OMPC_untied:
18415 case OMPC_mergeable:
18416 case OMPC_threadprivate:
18417 case OMPC_read:
18418 case OMPC_write:
18419 case OMPC_update:
18420 case OMPC_capture:
18421 case OMPC_compare:
18422 case OMPC_seq_cst:
18423 case OMPC_acq_rel:
18424 case OMPC_acquire:
18425 case OMPC_release:
18426 case OMPC_relaxed:
18427 case OMPC_device:
18428 case OMPC_threads:
18429 case OMPC_simd:
18430 case OMPC_num_teams:
18431 case OMPC_thread_limit:
18432 case OMPC_priority:
18433 case OMPC_grainsize:
18434 case OMPC_nogroup:
18435 case OMPC_num_tasks:
18436 case OMPC_hint:
18437 case OMPC_dist_schedule:
18438 case OMPC_defaultmap:
18439 case OMPC_unknown:
18440 case OMPC_uniform:
18441 case OMPC_unified_address:
18442 case OMPC_unified_shared_memory:
18443 case OMPC_reverse_offload:
18444 case OMPC_dynamic_allocators:
18445 case OMPC_atomic_default_mem_order:
18446 case OMPC_device_type:
18447 case OMPC_match:
18448 case OMPC_order:
18449 case OMPC_at:
18450 case OMPC_severity:
18451 case OMPC_message:
18452 case OMPC_destroy:
18453 case OMPC_novariants:
18454 case OMPC_nocontext:
18455 case OMPC_detach:
18456 case OMPC_uses_allocators:
18457 case OMPC_when:
18458 case OMPC_bind:
18459 default:
18460 llvm_unreachable("Clause is not allowed.");
18461 }
18462 return Res;
18463}
18464
18466 ExprObjectKind OK,
18467 SourceLocation Loc) {
18469 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
18470 if (!Res.isUsable())
18471 return ExprError();
18472 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
18473 Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
18474 if (!Res.isUsable())
18475 return ExprError();
18476 }
18477 if (VK != VK_LValue && Res.get()->isGLValue()) {
18478 Res = SemaRef.DefaultLvalueConversion(Res.get());
18479 if (!Res.isUsable())
18480 return ExprError();
18481 }
18482 return Res;
18483}
18484
18486 SourceLocation StartLoc,
18487 SourceLocation LParenLoc,
18488 SourceLocation EndLoc) {
18490 SmallVector<Expr *, 8> PrivateCopies;
18491 bool IsImplicitClause =
18492 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18493 for (Expr *RefExpr : VarList) {
18494 assert(RefExpr && "NULL expr in OpenMP private clause.");
18495 SourceLocation ELoc;
18496 SourceRange ERange;
18497 Expr *SimpleRefExpr = RefExpr;
18498 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
18499 if (Res.second) {
18500 // It will be analyzed later.
18501 Vars.push_back(RefExpr);
18502 PrivateCopies.push_back(nullptr);
18503 }
18504 ValueDecl *D = Res.first;
18505 if (!D)
18506 continue;
18507
18508 QualType Type = D->getType();
18509 auto *VD = dyn_cast<VarDecl>(D);
18510
18511 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18512 // A variable that appears in a private clause must not have an incomplete
18513 // type or a reference type.
18515 diag::err_omp_private_incomplete_type))
18516 continue;
18517 Type = Type.getNonReferenceType();
18518
18519 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18520 // A variable that is privatized must not have a const-qualified type
18521 // unless it is of class type with a mutable member. This restriction does
18522 // not apply to the firstprivate clause.
18523 //
18524 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
18525 // A variable that appears in a private clause must not have a
18526 // const-qualified type unless it is of class type with a mutable member.
18527 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc))
18528 continue;
18529
18530 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18531 // in a Construct]
18532 // Variables with the predetermined data-sharing attributes may not be
18533 // listed in data-sharing attributes clauses, except for the cases
18534 // listed below. For these exceptions only, listing a predetermined
18535 // variable in a data-sharing attribute clause is allowed and overrides
18536 // the variable's predetermined data-sharing attributes.
18537 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18538 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
18539 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
18540 << getOpenMPClauseName(OMPC_private);
18542 continue;
18543 }
18544
18545 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18546 // Variably modified types are not supported for tasks.
18548 isOpenMPTaskingDirective(CurrDir)) {
18549 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18550 << getOpenMPClauseName(OMPC_private) << Type
18551 << getOpenMPDirectiveName(CurrDir);
18552 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
18554 Diag(D->getLocation(),
18555 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18556 << D;
18557 continue;
18558 }
18559
18560 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18561 // A list item cannot appear in both a map clause and a data-sharing
18562 // attribute clause on the same construct
18563 //
18564 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18565 // A list item cannot appear in both a map clause and a data-sharing
18566 // attribute clause on the same construct unless the construct is a
18567 // combined construct.
18568 if ((getLangOpts().OpenMP <= 45 &&
18570 CurrDir == OMPD_target) {
18571 OpenMPClauseKind ConflictKind;
18572 if (DSAStack->checkMappableExprComponentListsForDecl(
18573 VD, /*CurrentRegionOnly=*/true,
18575 OpenMPClauseKind WhereFoundClauseKind) -> bool {
18576 ConflictKind = WhereFoundClauseKind;
18577 return true;
18578 })) {
18579 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18580 << getOpenMPClauseName(OMPC_private)
18581 << getOpenMPClauseName(ConflictKind)
18582 << getOpenMPDirectiveName(CurrDir);
18584 continue;
18585 }
18586 }
18587
18588 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
18589 // A variable of class type (or array thereof) that appears in a private
18590 // clause requires an accessible, unambiguous default constructor for the
18591 // class type.
18592 // Generate helper private variable and initialize it with the default
18593 // value. The address of the original variable is replaced by the address of
18594 // the new private variable in CodeGen. This new variable is not added to
18595 // IdResolver, so the code in the OpenMP region uses original variable for
18596 // proper diagnostics.
18597 Type = Type.getUnqualifiedType();
18598 VarDecl *VDPrivate =
18599 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
18600 D->hasAttrs() ? &D->getAttrs() : nullptr,
18601 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18603 if (VDPrivate->isInvalidDecl())
18604 continue;
18605 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18606 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
18607
18608 DeclRefExpr *Ref = nullptr;
18609 if (!VD && !SemaRef.CurContext->isDependentContext()) {
18610 auto *FD = dyn_cast<FieldDecl>(D);
18611 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18612 if (VD)
18614 RefExpr->getExprLoc());
18615 else
18616 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
18617 }
18618 if (!IsImplicitClause)
18619 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
18620 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
18621 ? RefExpr->IgnoreParens()
18622 : Ref);
18623 PrivateCopies.push_back(VDPrivateRefExpr);
18624 }
18625
18626 if (Vars.empty())
18627 return nullptr;
18628
18629 return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
18630 Vars, PrivateCopies);
18631}
18632
18634 SourceLocation StartLoc,
18635 SourceLocation LParenLoc,
18636 SourceLocation EndLoc) {
18638 SmallVector<Expr *, 8> PrivateCopies;
18640 SmallVector<Decl *, 4> ExprCaptures;
18641 bool IsImplicitClause =
18642 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18643 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
18644
18645 for (Expr *RefExpr : VarList) {
18646 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
18647 SourceLocation ELoc;
18648 SourceRange ERange;
18649 Expr *SimpleRefExpr = RefExpr;
18650 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
18651 if (Res.second) {
18652 // It will be analyzed later.
18653 Vars.push_back(RefExpr);
18654 PrivateCopies.push_back(nullptr);
18655 Inits.push_back(nullptr);
18656 }
18657 ValueDecl *D = Res.first;
18658 if (!D)
18659 continue;
18660
18661 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
18662 QualType Type = D->getType();
18663 auto *VD = dyn_cast<VarDecl>(D);
18664
18665 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18666 // A variable that appears in a private clause must not have an incomplete
18667 // type or a reference type.
18669 diag::err_omp_firstprivate_incomplete_type))
18670 continue;
18671 Type = Type.getNonReferenceType();
18672
18673 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
18674 // A variable of class type (or array thereof) that appears in a private
18675 // clause requires an accessible, unambiguous copy constructor for the
18676 // class type.
18677 QualType ElemType =
18679
18680 // If an implicit firstprivate variable found it was checked already.
18681 DSAStackTy::DSAVarData TopDVar;
18682 if (!IsImplicitClause) {
18683 DSAStackTy::DSAVarData DVar =
18684 DSAStack->getTopDSA(D, /*FromParent=*/false);
18685 TopDVar = DVar;
18686 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18687 bool IsConstant = ElemType.isConstant(getASTContext());
18688 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
18689 // A list item that specifies a given variable may not appear in more
18690 // than one clause on the same directive, except that a variable may be
18691 // specified in both firstprivate and lastprivate clauses.
18692 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18693 // A list item may appear in a firstprivate or lastprivate clause but not
18694 // both.
18695 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
18696 (isOpenMPDistributeDirective(CurrDir) ||
18697 DVar.CKind != OMPC_lastprivate) &&
18698 DVar.RefExpr) {
18699 Diag(ELoc, diag::err_omp_wrong_dsa)
18700 << getOpenMPClauseName(DVar.CKind)
18701 << getOpenMPClauseName(OMPC_firstprivate);
18703 continue;
18704 }
18705
18706 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18707 // in a Construct]
18708 // Variables with the predetermined data-sharing attributes may not be
18709 // listed in data-sharing attributes clauses, except for the cases
18710 // listed below. For these exceptions only, listing a predetermined
18711 // variable in a data-sharing attribute clause is allowed and overrides
18712 // the variable's predetermined data-sharing attributes.
18713 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18714 // in a Construct, C/C++, p.2]
18715 // Variables with const-qualified type having no mutable member may be
18716 // listed in a firstprivate clause, even if they are static data members.
18717 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
18718 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
18719 Diag(ELoc, diag::err_omp_wrong_dsa)
18720 << getOpenMPClauseName(DVar.CKind)
18721 << getOpenMPClauseName(OMPC_firstprivate);
18723 continue;
18724 }
18725
18726 // OpenMP [2.9.3.4, Restrictions, p.2]
18727 // A list item that is private within a parallel region must not appear
18728 // in a firstprivate clause on a worksharing construct if any of the
18729 // worksharing regions arising from the worksharing construct ever bind
18730 // to any of the parallel regions arising from the parallel construct.
18731 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18732 // A list item that is private within a teams region must not appear in a
18733 // firstprivate clause on a distribute construct if any of the distribute
18734 // regions arising from the distribute construct ever bind to any of the
18735 // teams regions arising from the teams construct.
18736 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18737 // A list item that appears in a reduction clause of a teams construct
18738 // must not appear in a firstprivate clause on a distribute construct if
18739 // any of the distribute regions arising from the distribute construct
18740 // ever bind to any of the teams regions arising from the teams construct.
18741 if ((isOpenMPWorksharingDirective(CurrDir) ||
18742 isOpenMPDistributeDirective(CurrDir)) &&
18743 !isOpenMPParallelDirective(CurrDir) &&
18744 !isOpenMPTeamsDirective(CurrDir)) {
18745 DVar = DSAStack->getImplicitDSA(D, true);
18746 if (DVar.CKind != OMPC_shared &&
18747 (isOpenMPParallelDirective(DVar.DKind) ||
18748 isOpenMPTeamsDirective(DVar.DKind) ||
18749 DVar.DKind == OMPD_unknown)) {
18750 Diag(ELoc, diag::err_omp_required_access)
18751 << getOpenMPClauseName(OMPC_firstprivate)
18752 << getOpenMPClauseName(OMPC_shared);
18754 continue;
18755 }
18756 }
18757 // OpenMP [2.9.3.4, Restrictions, p.3]
18758 // A list item that appears in a reduction clause of a parallel construct
18759 // must not appear in a firstprivate clause on a worksharing or task
18760 // construct if any of the worksharing or task regions arising from the
18761 // worksharing or task construct ever bind to any of the parallel regions
18762 // arising from the parallel construct.
18763 // OpenMP [2.9.3.4, Restrictions, p.4]
18764 // A list item that appears in a reduction clause in worksharing
18765 // construct must not appear in a firstprivate clause in a task construct
18766 // encountered during execution of any of the worksharing regions arising
18767 // from the worksharing construct.
18768 if (isOpenMPTaskingDirective(CurrDir)) {
18769 DVar = DSAStack->hasInnermostDSA(
18770 D,
18771 [](OpenMPClauseKind C, bool AppliedToPointee) {
18772 return C == OMPC_reduction && !AppliedToPointee;
18773 },
18774 [](OpenMPDirectiveKind K) {
18775 return isOpenMPParallelDirective(K) ||
18778 },
18779 /*FromParent=*/true);
18780 if (DVar.CKind == OMPC_reduction &&
18781 (isOpenMPParallelDirective(DVar.DKind) ||
18782 isOpenMPWorksharingDirective(DVar.DKind) ||
18783 isOpenMPTeamsDirective(DVar.DKind))) {
18784 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
18785 << getOpenMPDirectiveName(DVar.DKind);
18787 continue;
18788 }
18789 }
18790
18791 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18792 // A list item cannot appear in both a map clause and a data-sharing
18793 // attribute clause on the same construct
18794 //
18795 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18796 // A list item cannot appear in both a map clause and a data-sharing
18797 // attribute clause on the same construct unless the construct is a
18798 // combined construct.
18799 if ((getLangOpts().OpenMP <= 45 &&
18801 CurrDir == OMPD_target) {
18802 OpenMPClauseKind ConflictKind;
18803 if (DSAStack->checkMappableExprComponentListsForDecl(
18804 VD, /*CurrentRegionOnly=*/true,
18805 [&ConflictKind](
18807 OpenMPClauseKind WhereFoundClauseKind) {
18808 ConflictKind = WhereFoundClauseKind;
18809 return true;
18810 })) {
18811 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18812 << getOpenMPClauseName(OMPC_firstprivate)
18813 << getOpenMPClauseName(ConflictKind)
18814 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
18816 continue;
18817 }
18818 }
18819 }
18820
18821 // Variably modified types are not supported for tasks.
18823 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
18824 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18825 << getOpenMPClauseName(OMPC_firstprivate) << Type
18826 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
18827 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
18829 Diag(D->getLocation(),
18830 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18831 << D;
18832 continue;
18833 }
18834
18835 Type = Type.getUnqualifiedType();
18836 VarDecl *VDPrivate =
18837 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
18838 D->hasAttrs() ? &D->getAttrs() : nullptr,
18839 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18840 // Generate helper private variable and initialize it with the value of the
18841 // original variable. The address of the original variable is replaced by
18842 // the address of the new private variable in the CodeGen. This new variable
18843 // is not added to IdResolver, so the code in the OpenMP region uses
18844 // original variable for proper diagnostics and variable capturing.
18845 Expr *VDInitRefExpr = nullptr;
18846 // For arrays generate initializer for single element and replace it by the
18847 // original array element in CodeGen.
18848 if (Type->isArrayType()) {
18849 VarDecl *VDInit =
18850 buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName());
18851 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc);
18852 Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get();
18853 ElemType = ElemType.getUnqualifiedType();
18854 VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(),
18855 ElemType, ".firstprivate.temp");
18856 InitializedEntity Entity =
18859
18860 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
18861 ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init);
18862 if (Result.isInvalid())
18863 VDPrivate->setInvalidDecl();
18864 else
18865 VDPrivate->setInit(Result.getAs<Expr>());
18866 // Remove temp variable declaration.
18867 getASTContext().Deallocate(VDInitTemp);
18868 } else {
18869 VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type,
18870 ".firstprivate.temp");
18871 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(),
18872 RefExpr->getExprLoc());
18874 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
18875 /*DirectInit=*/false);
18876 }
18877 if (VDPrivate->isInvalidDecl()) {
18878 if (IsImplicitClause) {
18879 Diag(RefExpr->getExprLoc(),
18880 diag::note_omp_task_predetermined_firstprivate_here);
18881 }
18882 continue;
18883 }
18884 SemaRef.CurContext->addDecl(VDPrivate);
18885 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18886 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(),
18887 RefExpr->getExprLoc());
18888 DeclRefExpr *Ref = nullptr;
18889 if (!VD && !SemaRef.CurContext->isDependentContext()) {
18890 if (TopDVar.CKind == OMPC_lastprivate) {
18891 Ref = TopDVar.PrivateCopy;
18892 } else {
18893 auto *FD = dyn_cast<FieldDecl>(D);
18894 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18895 if (VD)
18896 Ref =
18898 RefExpr->getExprLoc());
18899 else
18900 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
18901 if (VD || !isOpenMPCapturedDecl(D))
18902 ExprCaptures.push_back(Ref->getDecl());
18903 }
18904 }
18905 if (!IsImplicitClause)
18906 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
18907 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
18908 ? RefExpr->IgnoreParens()
18909 : Ref);
18910 PrivateCopies.push_back(VDPrivateRefExpr);
18911 Inits.push_back(VDInitRefExpr);
18912 }
18913
18914 if (Vars.empty())
18915 return nullptr;
18916
18918 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
18919 buildPreInits(getASTContext(), ExprCaptures));
18920}
18921
18924 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
18925 SourceLocation LParenLoc, SourceLocation EndLoc) {
18926 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
18927 assert(ColonLoc.isValid() && "Colon location must be valid.");
18928 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
18929 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
18930 /*Last=*/OMPC_LASTPRIVATE_unknown)
18931 << getOpenMPClauseName(OMPC_lastprivate);
18932 return nullptr;
18933 }
18934
18936 SmallVector<Expr *, 8> SrcExprs;
18937 SmallVector<Expr *, 8> DstExprs;
18938 SmallVector<Expr *, 8> AssignmentOps;
18939 SmallVector<Decl *, 4> ExprCaptures;
18940 SmallVector<Expr *, 4> ExprPostUpdates;
18941 for (Expr *RefExpr : VarList) {
18942 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18943 SourceLocation ELoc;
18944 SourceRange ERange;
18945 Expr *SimpleRefExpr = RefExpr;
18946 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
18947 if (Res.second) {
18948 // It will be analyzed later.
18949 Vars.push_back(RefExpr);
18950 SrcExprs.push_back(nullptr);
18951 DstExprs.push_back(nullptr);
18952 AssignmentOps.push_back(nullptr);
18953 }
18954 ValueDecl *D = Res.first;
18955 if (!D)
18956 continue;
18957
18958 QualType Type = D->getType();
18959 auto *VD = dyn_cast<VarDecl>(D);
18960
18961 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
18962 // A variable that appears in a lastprivate clause must not have an
18963 // incomplete type or a reference type.
18965 diag::err_omp_lastprivate_incomplete_type))
18966 continue;
18967 Type = Type.getNonReferenceType();
18968
18969 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18970 // A variable that is privatized must not have a const-qualified type
18971 // unless it is of class type with a mutable member. This restriction does
18972 // not apply to the firstprivate clause.
18973 //
18974 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
18975 // A variable that appears in a lastprivate clause must not have a
18976 // const-qualified type unless it is of class type with a mutable member.
18977 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc))
18978 continue;
18979
18980 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
18981 // A list item that appears in a lastprivate clause with the conditional
18982 // modifier must be a scalar variable.
18983 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
18984 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
18985 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
18987 Diag(D->getLocation(),
18988 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18989 << D;
18990 continue;
18991 }
18992
18993 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18994 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18995 // in a Construct]
18996 // Variables with the predetermined data-sharing attributes may not be
18997 // listed in data-sharing attributes clauses, except for the cases
18998 // listed below.
18999 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
19000 // A list item may appear in a firstprivate or lastprivate clause but not
19001 // both.
19002 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19003 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
19004 (isOpenMPDistributeDirective(CurrDir) ||
19005 DVar.CKind != OMPC_firstprivate) &&
19006 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
19007 Diag(ELoc, diag::err_omp_wrong_dsa)
19008 << getOpenMPClauseName(DVar.CKind)
19009 << getOpenMPClauseName(OMPC_lastprivate);
19011 continue;
19012 }
19013
19014 // OpenMP [2.14.3.5, Restrictions, p.2]
19015 // A list item that is private within a parallel region, or that appears in
19016 // the reduction clause of a parallel construct, must not appear in a
19017 // lastprivate clause on a worksharing construct if any of the corresponding
19018 // worksharing regions ever binds to any of the corresponding parallel
19019 // regions.
19020 DSAStackTy::DSAVarData TopDVar = DVar;
19021 if (isOpenMPWorksharingDirective(CurrDir) &&
19022 !isOpenMPParallelDirective(CurrDir) &&
19023 !isOpenMPTeamsDirective(CurrDir)) {
19024 DVar = DSAStack->getImplicitDSA(D, true);
19025 if (DVar.CKind != OMPC_shared) {
19026 Diag(ELoc, diag::err_omp_required_access)
19027 << getOpenMPClauseName(OMPC_lastprivate)
19028 << getOpenMPClauseName(OMPC_shared);
19030 continue;
19031 }
19032 }
19033
19034 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
19035 // A variable of class type (or array thereof) that appears in a
19036 // lastprivate clause requires an accessible, unambiguous default
19037 // constructor for the class type, unless the list item is also specified
19038 // in a firstprivate clause.
19039 // A variable of class type (or array thereof) that appears in a
19040 // lastprivate clause requires an accessible, unambiguous copy assignment
19041 // operator for the class type.
19043 VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(),
19044 Type.getUnqualifiedType(), ".lastprivate.src",
19045 D->hasAttrs() ? &D->getAttrs() : nullptr);
19046 DeclRefExpr *PseudoSrcExpr =
19047 buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc);
19048 VarDecl *DstVD =
19049 buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst",
19050 D->hasAttrs() ? &D->getAttrs() : nullptr);
19051 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
19052 // For arrays generate assignment operation for single element and replace
19053 // it by the original array element in CodeGen.
19054 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
19055 PseudoDstExpr, PseudoSrcExpr);
19056 if (AssignmentOp.isInvalid())
19057 continue;
19058 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
19059 /*DiscardedValue*/ false);
19060 if (AssignmentOp.isInvalid())
19061 continue;
19062
19063 DeclRefExpr *Ref = nullptr;
19064 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19065 if (TopDVar.CKind == OMPC_firstprivate) {
19066 Ref = TopDVar.PrivateCopy;
19067 } else {
19068 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19069 if (!isOpenMPCapturedDecl(D))
19070 ExprCaptures.push_back(Ref->getDecl());
19071 }
19072 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
19073 (!isOpenMPCapturedDecl(D) &&
19074 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
19076 if (!RefRes.isUsable())
19077 continue;
19078 ExprResult PostUpdateRes =
19079 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
19080 SimpleRefExpr, RefRes.get());
19081 if (!PostUpdateRes.isUsable())
19082 continue;
19083 ExprPostUpdates.push_back(
19084 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
19085 }
19086 }
19087 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
19088 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19089 ? RefExpr->IgnoreParens()
19090 : Ref);
19091 SrcExprs.push_back(PseudoSrcExpr);
19092 DstExprs.push_back(PseudoDstExpr);
19093 AssignmentOps.push_back(AssignmentOp.get());
19094 }
19095
19096 if (Vars.empty())
19097 return nullptr;
19098
19100 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
19101 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
19102 buildPreInits(getASTContext(), ExprCaptures),
19103 buildPostUpdate(SemaRef, ExprPostUpdates));
19104}
19105
19107 SourceLocation StartLoc,
19108 SourceLocation LParenLoc,
19109 SourceLocation EndLoc) {
19111 for (Expr *RefExpr : VarList) {
19112 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
19113 SourceLocation ELoc;
19114 SourceRange ERange;
19115 Expr *SimpleRefExpr = RefExpr;
19116 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19117 if (Res.second) {
19118 // It will be analyzed later.
19119 Vars.push_back(RefExpr);
19120 }
19121 ValueDecl *D = Res.first;
19122 if (!D)
19123 continue;
19124
19125 auto *VD = dyn_cast<VarDecl>(D);
19126 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19127 // in a Construct]
19128 // Variables with the predetermined data-sharing attributes may not be
19129 // listed in data-sharing attributes clauses, except for the cases
19130 // listed below. For these exceptions only, listing a predetermined
19131 // variable in a data-sharing attribute clause is allowed and overrides
19132 // the variable's predetermined data-sharing attributes.
19133 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19134 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
19135 DVar.RefExpr) {
19136 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
19137 << getOpenMPClauseName(OMPC_shared);
19139 continue;
19140 }
19141
19142 DeclRefExpr *Ref = nullptr;
19143 if (!VD && isOpenMPCapturedDecl(D) &&
19145 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19146 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
19147 Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext())
19148 ? RefExpr->IgnoreParens()
19149 : Ref);
19150 }
19151
19152 if (Vars.empty())
19153 return nullptr;
19154
19155 return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19156 Vars);
19157}
19158
19159namespace {
19160class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
19161 DSAStackTy *Stack;
19162
19163public:
19164 bool VisitDeclRefExpr(DeclRefExpr *E) {
19165 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
19166 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
19167 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
19168 return false;
19169 if (DVar.CKind != OMPC_unknown)
19170 return true;
19171 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
19172 VD,
19173 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
19174 return isOpenMPPrivate(C) && !AppliedToPointee;
19175 },
19176 [](OpenMPDirectiveKind) { return true; },
19177 /*FromParent=*/true);
19178 return DVarPrivate.CKind != OMPC_unknown;
19179 }
19180 return false;
19181 }
19182 bool VisitStmt(Stmt *S) {
19183 for (Stmt *Child : S->children()) {
19184 if (Child && Visit(Child))
19185 return true;
19186 }
19187 return false;
19188 }
19189 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
19190};
19191} // namespace
19192
19193namespace {
19194// Transform MemberExpression for specified FieldDecl of current class to
19195// DeclRefExpr to specified OMPCapturedExprDecl.
19196class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
19197 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
19198 ValueDecl *Field = nullptr;
19199 DeclRefExpr *CapturedExpr = nullptr;
19200
19201public:
19202 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
19203 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
19204
19205 ExprResult TransformMemberExpr(MemberExpr *E) {
19206 if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
19207 E->getMemberDecl() == Field) {
19208 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
19209 return CapturedExpr;
19210 }
19211 return BaseTransform::TransformMemberExpr(E);
19212 }
19213 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
19214};
19215} // namespace
19216
19217template <typename T, typename U>
19219 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
19220 for (U &Set : Lookups) {
19221 for (auto *D : Set) {
19222 if (T Res = Gen(cast<ValueDecl>(D)))
19223 return Res;
19224 }
19225 }
19226 return T();
19227}
19228
19230 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
19231
19232 for (auto *RD : D->redecls()) {
19233 // Don't bother with extra checks if we already know this one isn't visible.
19234 if (RD == D)
19235 continue;
19236
19237 auto ND = cast<NamedDecl>(RD);
19238 if (LookupResult::isVisible(SemaRef, ND))
19239 return ND;
19240 }
19241
19242 return nullptr;
19243}
19244
19245static void
19247 SourceLocation Loc, QualType Ty,
19249 // Find all of the associated namespaces and classes based on the
19250 // arguments we have.
19251 Sema::AssociatedNamespaceSet AssociatedNamespaces;
19252 Sema::AssociatedClassSet AssociatedClasses;
19253 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
19254 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
19255 AssociatedClasses);
19256
19257 // C++ [basic.lookup.argdep]p3:
19258 // Let X be the lookup set produced by unqualified lookup (3.4.1)
19259 // and let Y be the lookup set produced by argument dependent
19260 // lookup (defined as follows). If X contains [...] then Y is
19261 // empty. Otherwise Y is the set of declarations found in the
19262 // namespaces associated with the argument types as described
19263 // below. The set of declarations found by the lookup of the name
19264 // is the union of X and Y.
19265 //
19266 // Here, we compute Y and add its members to the overloaded
19267 // candidate set.
19268 for (auto *NS : AssociatedNamespaces) {
19269 // When considering an associated namespace, the lookup is the
19270 // same as the lookup performed when the associated namespace is
19271 // used as a qualifier (3.4.3.2) except that:
19272 //
19273 // -- Any using-directives in the associated namespace are
19274 // ignored.
19275 //
19276 // -- Any namespace-scope friend functions declared in
19277 // associated classes are visible within their respective
19278 // namespaces even if they are not visible during an ordinary
19279 // lookup (11.4).
19280 DeclContext::lookup_result R = NS->lookup(Id.getName());
19281 for (auto *D : R) {
19282 auto *Underlying = D;
19283 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19284 Underlying = USD->getTargetDecl();
19285
19286 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
19287 !isa<OMPDeclareMapperDecl>(Underlying))
19288 continue;
19289
19290 if (!SemaRef.isVisible(D)) {
19291 D = findAcceptableDecl(SemaRef, D);
19292 if (!D)
19293 continue;
19294 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19295 Underlying = USD->getTargetDecl();
19296 }
19297 Lookups.emplace_back();
19298 Lookups.back().addDecl(Underlying);
19299 }
19300 }
19301}
19302
19303static ExprResult
19305 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
19306 const DeclarationNameInfo &ReductionId, QualType Ty,
19307 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
19308 if (ReductionIdScopeSpec.isInvalid())
19309 return ExprError();
19310 SmallVector<UnresolvedSet<8>, 4> Lookups;
19311 if (S) {
19312 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19313 Lookup.suppressDiagnostics();
19314 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec)) {
19315 NamedDecl *D = Lookup.getRepresentativeDecl();
19316 do {
19317 S = S->getParent();
19318 } while (S && !S->isDeclScope(D));
19319 if (S)
19320 S = S->getParent();
19321 Lookups.emplace_back();
19322 Lookups.back().append(Lookup.begin(), Lookup.end());
19323 Lookup.clear();
19324 }
19325 } else if (auto *ULE =
19326 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
19327 Lookups.push_back(UnresolvedSet<8>());
19328 Decl *PrevD = nullptr;
19329 for (NamedDecl *D : ULE->decls()) {
19330 if (D == PrevD)
19331 Lookups.push_back(UnresolvedSet<8>());
19332 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
19333 Lookups.back().addDecl(DRD);
19334 PrevD = D;
19335 }
19336 }
19337 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
19340 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
19341 return !D->isInvalidDecl() &&
19342 (D->getType()->isDependentType() ||
19343 D->getType()->isInstantiationDependentType() ||
19344 D->getType()->containsUnexpandedParameterPack());
19345 })) {
19346 UnresolvedSet<8> ResSet;
19347 for (const UnresolvedSet<8> &Set : Lookups) {
19348 if (Set.empty())
19349 continue;
19350 ResSet.append(Set.begin(), Set.end());
19351 // The last item marks the end of all declarations at the specified scope.
19352 ResSet.addDecl(Set[Set.size() - 1]);
19353 }
19355 SemaRef.Context, /*NamingClass=*/nullptr,
19356 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
19357 /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false);
19358 }
19359 // Lookup inside the classes.
19360 // C++ [over.match.oper]p3:
19361 // For a unary operator @ with an operand of a type whose
19362 // cv-unqualified version is T1, and for a binary operator @ with
19363 // a left operand of a type whose cv-unqualified version is T1 and
19364 // a right operand of a type whose cv-unqualified version is T2,
19365 // three sets of candidate functions, designated member
19366 // candidates, non-member candidates and built-in candidates, are
19367 // constructed as follows:
19368 // -- If T1 is a complete class type or a class currently being
19369 // defined, the set of member candidates is the result of the
19370 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
19371 // the set of member candidates is empty.
19372 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19373 Lookup.suppressDiagnostics();
19374 if (const auto *TyRec = Ty->getAs<RecordType>()) {
19375 // Complete the type if it can be completed.
19376 // If the type is neither complete nor being defined, bail out now.
19377 if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() ||
19378 TyRec->getDecl()->getDefinition()) {
19379 Lookup.clear();
19380 SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
19381 if (Lookup.empty()) {
19382 Lookups.emplace_back();
19383 Lookups.back().append(Lookup.begin(), Lookup.end());
19384 }
19385 }
19386 }
19387 // Perform ADL.
19388 if (SemaRef.getLangOpts().CPlusPlus)
19389 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
19390 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
19391 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
19392 if (!D->isInvalidDecl() &&
19393 SemaRef.Context.hasSameType(D->getType(), Ty))
19394 return D;
19395 return nullptr;
19396 }))
19397 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
19398 VK_LValue, Loc);
19399 if (SemaRef.getLangOpts().CPlusPlus) {
19400 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
19401 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
19402 if (!D->isInvalidDecl() &&
19403 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
19404 !Ty.isMoreQualifiedThan(D->getType()))
19405 return D;
19406 return nullptr;
19407 })) {
19408 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
19409 /*DetectVirtual=*/false);
19410 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
19411 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
19412 VD->getType().getUnqualifiedType()))) {
19413 if (SemaRef.CheckBaseClassAccess(
19414 Loc, VD->getType(), Ty, Paths.front(),
19415 /*DiagID=*/0) != Sema::AR_inaccessible) {
19416 SemaRef.BuildBasePathArray(Paths, BasePath);
19417 return SemaRef.BuildDeclRefExpr(
19418 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc);
19419 }
19420 }
19421 }
19422 }
19423 }
19424 if (ReductionIdScopeSpec.isSet()) {
19425 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
19426 << Ty << Range;
19427 return ExprError();
19428 }
19429 return ExprEmpty();
19430}
19431
19432namespace {
19433/// Data for the reduction-based clauses.
19434struct ReductionData {
19435 /// List of original reduction items.
19437 /// List of private copies of the reduction items.
19438 SmallVector<Expr *, 8> Privates;
19439 /// LHS expressions for the reduction_op expressions.
19441 /// RHS expressions for the reduction_op expressions.
19443 /// Reduction operation expression.
19444 SmallVector<Expr *, 8> ReductionOps;
19445 /// inscan copy operation expressions.
19446 SmallVector<Expr *, 8> InscanCopyOps;
19447 /// inscan copy temp array expressions for prefix sums.
19448 SmallVector<Expr *, 8> InscanCopyArrayTemps;
19449 /// inscan copy temp array element expressions for prefix sums.
19450 SmallVector<Expr *, 8> InscanCopyArrayElems;
19451 /// Taskgroup descriptors for the corresponding reduction items in
19452 /// in_reduction clauses.
19453 SmallVector<Expr *, 8> TaskgroupDescriptors;
19454 /// List of captures for clause.
19455 SmallVector<Decl *, 4> ExprCaptures;
19456 /// List of postupdate expressions.
19457 SmallVector<Expr *, 4> ExprPostUpdates;
19458 /// Reduction modifier.
19459 unsigned RedModifier = 0;
19460 ReductionData() = delete;
19461 /// Reserves required memory for the reduction data.
19462 ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
19463 Vars.reserve(Size);
19464 Privates.reserve(Size);
19465 LHSs.reserve(Size);
19466 RHSs.reserve(Size);
19467 ReductionOps.reserve(Size);
19468 if (RedModifier == OMPC_REDUCTION_inscan) {
19469 InscanCopyOps.reserve(Size);
19470 InscanCopyArrayTemps.reserve(Size);
19471 InscanCopyArrayElems.reserve(Size);
19472 }
19473 TaskgroupDescriptors.reserve(Size);
19474 ExprCaptures.reserve(Size);
19475 ExprPostUpdates.reserve(Size);
19476 }
19477 /// Stores reduction item and reduction operation only (required for dependent
19478 /// reduction item).
19479 void push(Expr *Item, Expr *ReductionOp) {
19480 Vars.emplace_back(Item);
19481 Privates.emplace_back(nullptr);
19482 LHSs.emplace_back(nullptr);
19483 RHSs.emplace_back(nullptr);
19484 ReductionOps.emplace_back(ReductionOp);
19485 TaskgroupDescriptors.emplace_back(nullptr);
19486 if (RedModifier == OMPC_REDUCTION_inscan) {
19487 InscanCopyOps.push_back(nullptr);
19488 InscanCopyArrayTemps.push_back(nullptr);
19489 InscanCopyArrayElems.push_back(nullptr);
19490 }
19491 }
19492 /// Stores reduction data.
19493 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
19494 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
19495 Expr *CopyArrayElem) {
19496 Vars.emplace_back(Item);
19497 Privates.emplace_back(Private);
19498 LHSs.emplace_back(LHS);
19499 RHSs.emplace_back(RHS);
19500 ReductionOps.emplace_back(ReductionOp);
19501 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
19502 if (RedModifier == OMPC_REDUCTION_inscan) {
19503 InscanCopyOps.push_back(CopyOp);
19504 InscanCopyArrayTemps.push_back(CopyArrayTemp);
19505 InscanCopyArrayElems.push_back(CopyArrayElem);
19506 } else {
19507 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
19508 CopyArrayElem == nullptr &&
19509 "Copy operation must be used for inscan reductions only.");
19510 }
19511 }
19512};
19513} // namespace
19514
19516 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
19517 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
19518 const Expr *Length = OASE->getLength();
19519 if (Length == nullptr) {
19520 // For array sections of the form [1:] or [:], we would need to analyze
19521 // the lower bound...
19522 if (OASE->getColonLocFirst().isValid())
19523 return false;
19524
19525 // This is an array subscript which has implicit length 1!
19526 SingleElement = true;
19527 ArraySizes.push_back(llvm::APSInt::get(1));
19528 } else {
19530 if (!Length->EvaluateAsInt(Result, Context))
19531 return false;
19532
19533 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19534 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
19535 ArraySizes.push_back(ConstantLengthValue);
19536 }
19537
19538 // Get the base of this array section and walk up from there.
19539 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
19540
19541 // We require length = 1 for all array sections except the right-most to
19542 // guarantee that the memory region is contiguous and has no holes in it.
19543 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) {
19544 Length = TempOASE->getLength();
19545 if (Length == nullptr) {
19546 // For array sections of the form [1:] or [:], we would need to analyze
19547 // the lower bound...
19548 if (OASE->getColonLocFirst().isValid())
19549 return false;
19550
19551 // This is an array subscript which has implicit length 1!
19552 ArraySizes.push_back(llvm::APSInt::get(1));
19553 } else {
19555 if (!Length->EvaluateAsInt(Result, Context))
19556 return false;
19557
19558 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19559 if (ConstantLengthValue.getSExtValue() != 1)
19560 return false;
19561
19562 ArraySizes.push_back(ConstantLengthValue);
19563 }
19564 Base = TempOASE->getBase()->IgnoreParenImpCasts();
19565 }
19566
19567 // If we have a single element, we don't need to add the implicit lengths.
19568 if (!SingleElement) {
19569 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
19570 // Has implicit length 1!
19571 ArraySizes.push_back(llvm::APSInt::get(1));
19572 Base = TempASE->getBase()->IgnoreParenImpCasts();
19573 }
19574 }
19575
19576 // This array section can be privatized as a single value or as a constant
19577 // sized array.
19578 return true;
19579}
19580
19581static BinaryOperatorKind
19583 if (BOK == BO_Add)
19584 return BO_AddAssign;
19585 if (BOK == BO_Mul)
19586 return BO_MulAssign;
19587 if (BOK == BO_And)
19588 return BO_AndAssign;
19589 if (BOK == BO_Or)
19590 return BO_OrAssign;
19591 if (BOK == BO_Xor)
19592 return BO_XorAssign;
19593 return BOK;
19594}
19595
19597 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
19598 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19599 SourceLocation ColonLoc, SourceLocation EndLoc,
19600 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19601 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
19602 DeclarationName DN = ReductionId.getName();
19604 BinaryOperatorKind BOK = BO_Comma;
19605
19606 ASTContext &Context = S.Context;
19607 // OpenMP [2.14.3.6, reduction clause]
19608 // C
19609 // reduction-identifier is either an identifier or one of the following
19610 // operators: +, -, *, &, |, ^, && and ||
19611 // C++
19612 // reduction-identifier is either an id-expression or one of the following
19613 // operators: +, -, *, &, |, ^, && and ||
19614 switch (OOK) {
19615 case OO_Plus:
19616 BOK = BO_Add;
19617 break;
19618 case OO_Minus:
19619 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
19620 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
19621 // reduction identifier.
19622 if (S.LangOpts.OpenMP > 52)
19623 BOK = BO_Comma;
19624 else
19625 BOK = BO_Add;
19626 break;
19627 case OO_Star:
19628 BOK = BO_Mul;
19629 break;
19630 case OO_Amp:
19631 BOK = BO_And;
19632 break;
19633 case OO_Pipe:
19634 BOK = BO_Or;
19635 break;
19636 case OO_Caret:
19637 BOK = BO_Xor;
19638 break;
19639 case OO_AmpAmp:
19640 BOK = BO_LAnd;
19641 break;
19642 case OO_PipePipe:
19643 BOK = BO_LOr;
19644 break;
19645 case OO_New:
19646 case OO_Delete:
19647 case OO_Array_New:
19648 case OO_Array_Delete:
19649 case OO_Slash:
19650 case OO_Percent:
19651 case OO_Tilde:
19652 case OO_Exclaim:
19653 case OO_Equal:
19654 case OO_Less:
19655 case OO_Greater:
19656 case OO_LessEqual:
19657 case OO_GreaterEqual:
19658 case OO_PlusEqual:
19659 case OO_MinusEqual:
19660 case OO_StarEqual:
19661 case OO_SlashEqual:
19662 case OO_PercentEqual:
19663 case OO_CaretEqual:
19664 case OO_AmpEqual:
19665 case OO_PipeEqual:
19666 case OO_LessLess:
19667 case OO_GreaterGreater:
19668 case OO_LessLessEqual:
19669 case OO_GreaterGreaterEqual:
19670 case OO_EqualEqual:
19671 case OO_ExclaimEqual:
19672 case OO_Spaceship:
19673 case OO_PlusPlus:
19674 case OO_MinusMinus:
19675 case OO_Comma:
19676 case OO_ArrowStar:
19677 case OO_Arrow:
19678 case OO_Call:
19679 case OO_Subscript:
19680 case OO_Conditional:
19681 case OO_Coawait:
19683 llvm_unreachable("Unexpected reduction identifier");
19684 case OO_None:
19685 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
19686 if (II->isStr("max"))
19687 BOK = BO_GT;
19688 else if (II->isStr("min"))
19689 BOK = BO_LT;
19690 }
19691 break;
19692 }
19693
19694 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
19695 // A reduction clause with the minus (-) operator was deprecated
19696 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
19697 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
19698
19699 SourceRange ReductionIdRange;
19700 if (ReductionIdScopeSpec.isValid())
19701 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
19702 else
19703 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
19704 ReductionIdRange.setEnd(ReductionId.getEndLoc());
19705
19706 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
19707 bool FirstIter = true;
19708 for (Expr *RefExpr : VarList) {
19709 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
19710 // OpenMP [2.1, C/C++]
19711 // A list item is a variable or array section, subject to the restrictions
19712 // specified in Section 2.4 on page 42 and in each of the sections
19713 // describing clauses and directives for which a list appears.
19714 // OpenMP [2.14.3.3, Restrictions, p.1]
19715 // A variable that is part of another variable (as an array or
19716 // structure element) cannot appear in a private clause.
19717 if (!FirstIter && IR != ER)
19718 ++IR;
19719 FirstIter = false;
19720 SourceLocation ELoc;
19721 SourceRange ERange;
19722 Expr *SimpleRefExpr = RefExpr;
19723 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
19724 /*AllowArraySection=*/true);
19725 if (Res.second) {
19726 // Try to find 'declare reduction' corresponding construct before using
19727 // builtin/overloaded operators.
19728 QualType Type = Context.DependentTy;
19729 CXXCastPath BasePath;
19730 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19731 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19732 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19733 Expr *ReductionOp = nullptr;
19734 if (S.CurContext->isDependentContext() &&
19735 (DeclareReductionRef.isUnset() ||
19736 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
19737 ReductionOp = DeclareReductionRef.get();
19738 // It will be analyzed later.
19739 RD.push(RefExpr, ReductionOp);
19740 }
19741 ValueDecl *D = Res.first;
19742 if (!D)
19743 continue;
19744
19745 Expr *TaskgroupDescriptor = nullptr;
19746 QualType Type;
19747 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
19748 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
19749 if (ASE) {
19750 Type = ASE->getType().getNonReferenceType();
19751 } else if (OASE) {
19752 QualType BaseType =
19754 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
19755 Type = ATy->getElementType();
19756 else
19757 Type = BaseType->getPointeeType();
19758 Type = Type.getNonReferenceType();
19759 } else {
19761 }
19762 auto *VD = dyn_cast<VarDecl>(D);
19763
19764 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19765 // A variable that appears in a private clause must not have an incomplete
19766 // type or a reference type.
19767 if (S.RequireCompleteType(ELoc, D->getType(),
19768 diag::err_omp_reduction_incomplete_type))
19769 continue;
19770 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19771 // A list item that appears in a reduction clause must not be
19772 // const-qualified.
19773 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
19774 /*AcceptIfMutable*/ false, ASE || OASE))
19775 continue;
19776
19777 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
19778 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
19779 // If a list-item is a reference type then it must bind to the same object
19780 // for all threads of the team.
19781 if (!ASE && !OASE) {
19782 if (VD) {
19783 VarDecl *VDDef = VD->getDefinition();
19784 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
19785 DSARefChecker Check(Stack);
19786 if (Check.Visit(VDDef->getInit())) {
19787 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
19788 << getOpenMPClauseName(ClauseKind) << ERange;
19789 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
19790 continue;
19791 }
19792 }
19793 }
19794
19795 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19796 // in a Construct]
19797 // Variables with the predetermined data-sharing attributes may not be
19798 // listed in data-sharing attributes clauses, except for the cases
19799 // listed below. For these exceptions only, listing a predetermined
19800 // variable in a data-sharing attribute clause is allowed and overrides
19801 // the variable's predetermined data-sharing attributes.
19802 // OpenMP [2.14.3.6, Restrictions, p.3]
19803 // Any number of reduction clauses can be specified on the directive,
19804 // but a list item can appear only once in the reduction clauses for that
19805 // directive.
19806 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19807 if (DVar.CKind == OMPC_reduction) {
19808 S.Diag(ELoc, diag::err_omp_once_referenced)
19809 << getOpenMPClauseName(ClauseKind);
19810 if (DVar.RefExpr)
19811 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
19812 continue;
19813 }
19814 if (DVar.CKind != OMPC_unknown) {
19815 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19816 << getOpenMPClauseName(DVar.CKind)
19817 << getOpenMPClauseName(OMPC_reduction);
19818 reportOriginalDsa(S, Stack, D, DVar);
19819 continue;
19820 }
19821
19822 // OpenMP [2.14.3.6, Restrictions, p.1]
19823 // A list item that appears in a reduction clause of a worksharing
19824 // construct must be shared in the parallel regions to which any of the
19825 // worksharing regions arising from the worksharing construct bind.
19826 if (isOpenMPWorksharingDirective(CurrDir) &&
19827 !isOpenMPParallelDirective(CurrDir) &&
19828 !isOpenMPTeamsDirective(CurrDir)) {
19829 DVar = Stack->getImplicitDSA(D, true);
19830 if (DVar.CKind != OMPC_shared) {
19831 S.Diag(ELoc, diag::err_omp_required_access)
19832 << getOpenMPClauseName(OMPC_reduction)
19833 << getOpenMPClauseName(OMPC_shared);
19834 reportOriginalDsa(S, Stack, D, DVar);
19835 continue;
19836 }
19837 }
19838 } else {
19839 // Threadprivates cannot be shared between threads, so dignose if the base
19840 // is a threadprivate variable.
19841 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19842 if (DVar.CKind == OMPC_threadprivate) {
19843 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19844 << getOpenMPClauseName(DVar.CKind)
19845 << getOpenMPClauseName(OMPC_reduction);
19846 reportOriginalDsa(S, Stack, D, DVar);
19847 continue;
19848 }
19849 }
19850
19851 // Try to find 'declare reduction' corresponding construct before using
19852 // builtin/overloaded operators.
19853 CXXCastPath BasePath;
19854 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19855 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19856 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19857 if (DeclareReductionRef.isInvalid())
19858 continue;
19859 if (S.CurContext->isDependentContext() &&
19860 (DeclareReductionRef.isUnset() ||
19861 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
19862 RD.push(RefExpr, DeclareReductionRef.get());
19863 continue;
19864 }
19865 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
19866 // Not allowed reduction identifier is found.
19867 if (S.LangOpts.OpenMP > 52)
19868 S.Diag(ReductionId.getBeginLoc(),
19869 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
19870 << Type << ReductionIdRange;
19871 else
19872 S.Diag(ReductionId.getBeginLoc(),
19873 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
19874 << Type << ReductionIdRange;
19875 continue;
19876 }
19877
19878 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19879 // The type of a list item that appears in a reduction clause must be valid
19880 // for the reduction-identifier. For a max or min reduction in C, the type
19881 // of the list item must be an allowed arithmetic data type: char, int,
19882 // float, double, or _Bool, possibly modified with long, short, signed, or
19883 // unsigned. For a max or min reduction in C++, the type of the list item
19884 // must be an allowed arithmetic data type: char, wchar_t, int, float,
19885 // double, or bool, possibly modified with long, short, signed, or unsigned.
19886 if (DeclareReductionRef.isUnset()) {
19887 if ((BOK == BO_GT || BOK == BO_LT) &&
19888 !(Type->isScalarType() ||
19889 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
19890 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
19891 << getOpenMPClauseName(ClauseKind) << S.getLangOpts().CPlusPlus;
19892 if (!ASE && !OASE) {
19893 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19895 S.Diag(D->getLocation(),
19896 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19897 << D;
19898 }
19899 continue;
19900 }
19901 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
19902 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
19903 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
19904 << getOpenMPClauseName(ClauseKind);
19905 if (!ASE && !OASE) {
19906 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19908 S.Diag(D->getLocation(),
19909 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19910 << D;
19911 }
19912 continue;
19913 }
19914 }
19915
19916 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
19917 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
19918 D->hasAttrs() ? &D->getAttrs() : nullptr);
19919 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
19920 D->hasAttrs() ? &D->getAttrs() : nullptr);
19921 QualType PrivateTy = Type;
19922
19923 // Try if we can determine constant lengths for all array sections and avoid
19924 // the VLA.
19925 bool ConstantLengthOASE = false;
19926 if (OASE) {
19927 bool SingleElement;
19929 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
19930 Context, OASE, SingleElement, ArraySizes);
19931
19932 // If we don't have a single element, we must emit a constant array type.
19933 if (ConstantLengthOASE && !SingleElement) {
19934 for (llvm::APSInt &Size : ArraySizes)
19935 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
19937 /*IndexTypeQuals=*/0);
19938 }
19939 }
19940
19941 if ((OASE && !ConstantLengthOASE) ||
19942 (!OASE && !ASE &&
19944 if (!Context.getTargetInfo().isVLASupported()) {
19945 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
19946 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19947 S.Diag(ELoc, diag::note_vla_unsupported);
19948 continue;
19949 } else {
19950 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19951 S.targetDiag(ELoc, diag::note_vla_unsupported);
19952 }
19953 }
19954 // For arrays/array sections only:
19955 // Create pseudo array type for private copy. The size for this array will
19956 // be generated during codegen.
19957 // For array subscripts or single variables Private Ty is the same as Type
19958 // (type of the variable or single array element).
19959 PrivateTy = Context.getVariableArrayType(
19960 Type,
19961 new (Context)
19962 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
19963 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0, SourceRange());
19964 } else if (!ASE && !OASE &&
19965 Context.getAsArrayType(D->getType().getNonReferenceType())) {
19966 PrivateTy = D->getType().getNonReferenceType();
19967 }
19968 // Private copy.
19969 VarDecl *PrivateVD =
19970 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19971 D->hasAttrs() ? &D->getAttrs() : nullptr,
19972 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19973 // Add initializer for private variable.
19974 Expr *Init = nullptr;
19975 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
19976 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
19977 if (DeclareReductionRef.isUsable()) {
19978 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
19979 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
19980 if (DRD->getInitializer()) {
19981 Init = DRDRef;
19982 RHSVD->setInit(DRDRef);
19984 }
19985 } else {
19986 switch (BOK) {
19987 case BO_Add:
19988 case BO_Xor:
19989 case BO_Or:
19990 case BO_LOr:
19991 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
19993 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
19994 break;
19995 case BO_Mul:
19996 case BO_LAnd:
19997 if (Type->isScalarType() || Type->isAnyComplexType()) {
19998 // '*' and '&&' reduction ops - initializer is '1'.
19999 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
20000 }
20001 break;
20002 case BO_And: {
20003 // '&' reduction op - initializer is '~0'.
20004 QualType OrigType = Type;
20005 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
20006 Type = ComplexTy->getElementType();
20007 if (Type->isRealFloatingType()) {
20008 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
20009 Context.getFloatTypeSemantics(Type));
20010 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
20011 Type, ELoc);
20012 } else if (Type->isScalarType()) {
20013 uint64_t Size = Context.getTypeSize(Type);
20014 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
20015 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
20016 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
20017 }
20018 if (Init && OrigType->isAnyComplexType()) {
20019 // Init = 0xFFFF + 0xFFFFi;
20020 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
20021 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
20022 }
20023 Type = OrigType;
20024 break;
20025 }
20026 case BO_LT:
20027 case BO_GT: {
20028 // 'min' reduction op - initializer is 'Largest representable number in
20029 // the reduction list item type'.
20030 // 'max' reduction op - initializer is 'Least representable number in
20031 // the reduction list item type'.
20032 if (Type->isIntegerType() || Type->isPointerType()) {
20033 bool IsSigned = Type->hasSignedIntegerRepresentation();
20034 uint64_t Size = Context.getTypeSize(Type);
20035 QualType IntTy =
20036 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
20037 llvm::APInt InitValue =
20038 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
20039 : llvm::APInt::getMinValue(Size)
20040 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
20041 : llvm::APInt::getMaxValue(Size);
20042 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
20043 if (Type->isPointerType()) {
20044 // Cast to pointer type.
20046 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
20047 if (CastExpr.isInvalid())
20048 continue;
20049 Init = CastExpr.get();
20050 }
20051 } else if (Type->isRealFloatingType()) {
20052 llvm::APFloat InitValue = llvm::APFloat::getLargest(
20053 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
20054 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
20055 Type, ELoc);
20056 }
20057 break;
20058 }
20059 case BO_PtrMemD:
20060 case BO_PtrMemI:
20061 case BO_MulAssign:
20062 case BO_Div:
20063 case BO_Rem:
20064 case BO_Sub:
20065 case BO_Shl:
20066 case BO_Shr:
20067 case BO_LE:
20068 case BO_GE:
20069 case BO_EQ:
20070 case BO_NE:
20071 case BO_Cmp:
20072 case BO_AndAssign:
20073 case BO_XorAssign:
20074 case BO_OrAssign:
20075 case BO_Assign:
20076 case BO_AddAssign:
20077 case BO_SubAssign:
20078 case BO_DivAssign:
20079 case BO_RemAssign:
20080 case BO_ShlAssign:
20081 case BO_ShrAssign:
20082 case BO_Comma:
20083 llvm_unreachable("Unexpected reduction operation");
20084 }
20085 }
20086 if (Init && DeclareReductionRef.isUnset()) {
20087 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
20088 // Store initializer for single element in private copy. Will be used
20089 // during codegen.
20090 PrivateVD->setInit(RHSVD->getInit());
20091 PrivateVD->setInitStyle(RHSVD->getInitStyle());
20092 } else if (!Init) {
20093 S.ActOnUninitializedDecl(RHSVD);
20094 // Store initializer for single element in private copy. Will be used
20095 // during codegen.
20096 PrivateVD->setInit(RHSVD->getInit());
20097 PrivateVD->setInitStyle(RHSVD->getInitStyle());
20098 }
20099 if (RHSVD->isInvalidDecl())
20100 continue;
20101 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
20102 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
20103 << Type << ReductionIdRange;
20104 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20106 S.Diag(D->getLocation(),
20107 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20108 << D;
20109 continue;
20110 }
20111 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
20112 ExprResult ReductionOp;
20113 if (DeclareReductionRef.isUsable()) {
20114 QualType RedTy = DeclareReductionRef.get()->getType();
20115 QualType PtrRedTy = Context.getPointerType(RedTy);
20116 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
20117 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
20118 if (!BasePath.empty()) {
20119 LHS = S.DefaultLvalueConversion(LHS.get());
20120 RHS = S.DefaultLvalueConversion(RHS.get());
20122 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
20123 LHS.get()->getValueKind(), FPOptionsOverride());
20125 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
20126 RHS.get()->getValueKind(), FPOptionsOverride());
20127 }
20129 QualType Params[] = {PtrRedTy, PtrRedTy};
20130 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
20131 auto *OVE = new (Context) OpaqueValueExpr(
20132 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
20133 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
20134 Expr *Args[] = {LHS.get(), RHS.get()};
20135 ReductionOp =
20136 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
20138 } else {
20140 if (Type->isRecordType() && CombBOK != BOK) {
20142 ReductionOp =
20143 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20144 CombBOK, LHSDRE, RHSDRE);
20145 }
20146 if (!ReductionOp.isUsable()) {
20147 ReductionOp =
20148 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
20149 LHSDRE, RHSDRE);
20150 if (ReductionOp.isUsable()) {
20151 if (BOK != BO_LT && BOK != BO_GT) {
20152 ReductionOp =
20153 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20154 BO_Assign, LHSDRE, ReductionOp.get());
20155 } else {
20156 auto *ConditionalOp = new (Context)
20157 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
20158 RHSDRE, Type, VK_LValue, OK_Ordinary);
20159 ReductionOp =
20160 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20161 BO_Assign, LHSDRE, ConditionalOp);
20162 }
20163 }
20164 }
20165 if (ReductionOp.isUsable())
20166 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
20167 /*DiscardedValue*/ false);
20168 if (!ReductionOp.isUsable())
20169 continue;
20170 }
20171
20172 // Add copy operations for inscan reductions.
20173 // LHS = RHS;
20174 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
20175 if (ClauseKind == OMPC_reduction &&
20176 RD.RedModifier == OMPC_REDUCTION_inscan) {
20177 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
20178 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
20179 RHS.get());
20180 if (!CopyOpRes.isUsable())
20181 continue;
20182 CopyOpRes =
20183 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
20184 if (!CopyOpRes.isUsable())
20185 continue;
20186 // For simd directive and simd-based directives in simd mode no need to
20187 // construct temp array, need just a single temp element.
20188 if (Stack->getCurrentDirective() == OMPD_simd ||
20189 (S.getLangOpts().OpenMPSimd &&
20190 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
20191 VarDecl *TempArrayVD =
20192 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
20193 D->hasAttrs() ? &D->getAttrs() : nullptr);
20194 // Add a constructor to the temp decl.
20195 S.ActOnUninitializedDecl(TempArrayVD);
20196 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
20197 } else {
20198 // Build temp array for prefix sum.
20199 auto *Dim = new (S.Context)
20202 PrivateTy, Dim, ArraySizeModifier::Normal,
20203 /*IndexTypeQuals=*/0, {ELoc, ELoc});
20204 VarDecl *TempArrayVD =
20205 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
20206 D->hasAttrs() ? &D->getAttrs() : nullptr);
20207 // Add a constructor to the temp decl.
20208 S.ActOnUninitializedDecl(TempArrayVD);
20209 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
20210 TempArrayElem =
20211 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
20212 auto *Idx = new (S.Context)
20214 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
20215 ELoc, Idx, ELoc);
20216 }
20217 }
20218
20219 // OpenMP [2.15.4.6, Restrictions, p.2]
20220 // A list item that appears in an in_reduction clause of a task construct
20221 // must appear in a task_reduction clause of a construct associated with a
20222 // taskgroup region that includes the participating task in its taskgroup
20223 // set. The construct associated with the innermost region that meets this
20224 // condition must specify the same reduction-identifier as the in_reduction
20225 // clause.
20226 if (ClauseKind == OMPC_in_reduction) {
20227 SourceRange ParentSR;
20228 BinaryOperatorKind ParentBOK;
20229 const Expr *ParentReductionOp = nullptr;
20230 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
20231 DSAStackTy::DSAVarData ParentBOKDSA =
20232 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
20233 ParentBOKTD);
20234 DSAStackTy::DSAVarData ParentReductionOpDSA =
20235 Stack->getTopMostTaskgroupReductionData(
20236 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
20237 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
20238 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
20239 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
20240 (DeclareReductionRef.isUsable() && IsParentBOK) ||
20241 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
20242 bool EmitError = true;
20243 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
20244 llvm::FoldingSetNodeID RedId, ParentRedId;
20245 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
20246 DeclareReductionRef.get()->Profile(RedId, Context,
20247 /*Canonical=*/true);
20248 EmitError = RedId != ParentRedId;
20249 }
20250 if (EmitError) {
20251 S.Diag(ReductionId.getBeginLoc(),
20252 diag::err_omp_reduction_identifier_mismatch)
20253 << ReductionIdRange << RefExpr->getSourceRange();
20254 S.Diag(ParentSR.getBegin(),
20255 diag::note_omp_previous_reduction_identifier)
20256 << ParentSR
20257 << (IsParentBOK ? ParentBOKDSA.RefExpr
20258 : ParentReductionOpDSA.RefExpr)
20259 ->getSourceRange();
20260 continue;
20261 }
20262 }
20263 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
20264 }
20265
20266 DeclRefExpr *Ref = nullptr;
20267 Expr *VarsExpr = RefExpr->IgnoreParens();
20268 if (!VD && !S.CurContext->isDependentContext()) {
20269 if (ASE || OASE) {
20270 TransformExprToCaptures RebuildToCapture(S, D);
20271 VarsExpr =
20272 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
20273 Ref = RebuildToCapture.getCapturedExpr();
20274 } else {
20275 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
20276 }
20277 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
20278 RD.ExprCaptures.emplace_back(Ref->getDecl());
20279 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20280 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
20281 if (!RefRes.isUsable())
20282 continue;
20283 ExprResult PostUpdateRes =
20284 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
20285 RefRes.get());
20286 if (!PostUpdateRes.isUsable())
20287 continue;
20288 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
20289 Stack->getCurrentDirective() == OMPD_taskgroup) {
20290 S.Diag(RefExpr->getExprLoc(),
20291 diag::err_omp_reduction_non_addressable_expression)
20292 << RefExpr->getSourceRange();
20293 continue;
20294 }
20295 RD.ExprPostUpdates.emplace_back(
20296 S.IgnoredValueConversions(PostUpdateRes.get()).get());
20297 }
20298 }
20299 }
20300 // All reduction items are still marked as reduction (to do not increase
20301 // code base size).
20302 unsigned Modifier = RD.RedModifier;
20303 // Consider task_reductions as reductions with task modifier. Required for
20304 // correct analysis of in_reduction clauses.
20305 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
20306 Modifier = OMPC_REDUCTION_task;
20307 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
20308 ASE || OASE);
20309 if (Modifier == OMPC_REDUCTION_task &&
20310 (CurrDir == OMPD_taskgroup ||
20311 ((isOpenMPParallelDirective(CurrDir) ||
20312 isOpenMPWorksharingDirective(CurrDir)) &&
20313 !isOpenMPSimdDirective(CurrDir)))) {
20314 if (DeclareReductionRef.isUsable())
20315 Stack->addTaskgroupReductionData(D, ReductionIdRange,
20316 DeclareReductionRef.get());
20317 else
20318 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
20319 }
20320 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
20321 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
20322 TempArrayElem.get());
20323 }
20324 return RD.Vars.empty();
20325}
20326
20329 SourceLocation StartLoc, SourceLocation LParenLoc,
20330 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
20331 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20332 ArrayRef<Expr *> UnresolvedReductions) {
20333 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
20334 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
20335 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
20336 /*Last=*/OMPC_REDUCTION_unknown)
20337 << getOpenMPClauseName(OMPC_reduction);
20338 return nullptr;
20339 }
20340 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
20341 // A reduction clause with the inscan reduction-modifier may only appear on a
20342 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
20343 // construct, a parallel worksharing-loop construct or a parallel
20344 // worksharing-loop SIMD construct.
20345 if (Modifier == OMPC_REDUCTION_inscan &&
20346 (DSAStack->getCurrentDirective() != OMPD_for &&
20347 DSAStack->getCurrentDirective() != OMPD_for_simd &&
20348 DSAStack->getCurrentDirective() != OMPD_simd &&
20349 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
20350 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
20351 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
20352 return nullptr;
20353 }
20354
20355 ReductionData RD(VarList.size(), Modifier);
20356 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
20357 StartLoc, LParenLoc, ColonLoc, EndLoc,
20358 ReductionIdScopeSpec, ReductionId,
20359 UnresolvedReductions, RD))
20360 return nullptr;
20361
20363 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
20364 Modifier, RD.Vars,
20365 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20366 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
20367 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
20368 buildPreInits(getASTContext(), RD.ExprCaptures),
20369 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
20370}
20371
20373 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20374 SourceLocation ColonLoc, SourceLocation EndLoc,
20375 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20376 ArrayRef<Expr *> UnresolvedReductions) {
20377 ReductionData RD(VarList.size());
20378 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction,
20379 VarList, StartLoc, LParenLoc, ColonLoc,
20380 EndLoc, ReductionIdScopeSpec, ReductionId,
20381 UnresolvedReductions, RD))
20382 return nullptr;
20383
20385 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20386 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20387 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
20388 buildPreInits(getASTContext(), RD.ExprCaptures),
20389 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
20390}
20391
20393 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20394 SourceLocation ColonLoc, SourceLocation EndLoc,
20395 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20396 ArrayRef<Expr *> UnresolvedReductions) {
20397 ReductionData RD(VarList.size());
20398 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList,
20399 StartLoc, LParenLoc, ColonLoc, EndLoc,
20400 ReductionIdScopeSpec, ReductionId,
20401 UnresolvedReductions, RD))
20402 return nullptr;
20403
20405 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20406 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20407 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
20408 buildPreInits(getASTContext(), RD.ExprCaptures),
20409 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
20410}
20411
20413 SourceLocation LinLoc) {
20414 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
20415 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
20416 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
20417 << getLangOpts().CPlusPlus;
20418 return true;
20419 }
20420 return false;
20421}
20422
20424 OpenMPLinearClauseKind LinKind,
20425 QualType Type, bool IsDeclareSimd) {
20426 const auto *VD = dyn_cast_or_null<VarDecl>(D);
20427 // A variable must not have an incomplete type or a reference type.
20429 diag::err_omp_linear_incomplete_type))
20430 return true;
20431 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
20432 !Type->isReferenceType()) {
20433 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
20434 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
20435 return true;
20436 }
20437 Type = Type.getNonReferenceType();
20438
20439 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
20440 // A variable that is privatized must not have a const-qualified type
20441 // unless it is of class type with a mutable member. This restriction does
20442 // not apply to the firstprivate clause, nor to the linear clause on
20443 // declarative directives (like declare simd).
20444 if (!IsDeclareSimd &&
20445 rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc))
20446 return true;
20447
20448 // A list item must be of integral or pointer type.
20449 Type = Type.getUnqualifiedType().getCanonicalType();
20450 const auto *Ty = Type.getTypePtrOrNull();
20451 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
20452 !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) {
20453 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
20454 if (D) {
20455 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20457 Diag(D->getLocation(),
20458 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20459 << D;
20460 }
20461 return true;
20462 }
20463 return false;
20464}
20465
20467 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
20468 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
20469 SourceLocation LinLoc, SourceLocation ColonLoc,
20470 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
20472 SmallVector<Expr *, 8> Privates;
20474 SmallVector<Decl *, 4> ExprCaptures;
20475 SmallVector<Expr *, 4> ExprPostUpdates;
20476 // OpenMP 5.2 [Section 5.4.6, linear clause]
20477 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
20478 // 'ref'
20479 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
20480 getLangOpts().OpenMP >= 52)
20481 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
20482 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
20483 LinKind = OMPC_LINEAR_val;
20484 for (Expr *RefExpr : VarList) {
20485 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20486 SourceLocation ELoc;
20487 SourceRange ERange;
20488 Expr *SimpleRefExpr = RefExpr;
20489 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20490 if (Res.second) {
20491 // It will be analyzed later.
20492 Vars.push_back(RefExpr);
20493 Privates.push_back(nullptr);
20494 Inits.push_back(nullptr);
20495 }
20496 ValueDecl *D = Res.first;
20497 if (!D)
20498 continue;
20499
20500 QualType Type = D->getType();
20501 auto *VD = dyn_cast<VarDecl>(D);
20502
20503 // OpenMP [2.14.3.7, linear clause]
20504 // A list-item cannot appear in more than one linear clause.
20505 // A list-item that appears in a linear clause cannot appear in any
20506 // other data-sharing attribute clause.
20507 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
20508 if (DVar.RefExpr) {
20509 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
20510 << getOpenMPClauseName(OMPC_linear);
20512 continue;
20513 }
20514
20515 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
20516 continue;
20517 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20518
20519 // Build private copy of original var.
20520 VarDecl *Private =
20521 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
20522 D->hasAttrs() ? &D->getAttrs() : nullptr,
20523 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
20524 DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc);
20525 // Build var to save initial value.
20526 VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start");
20527 Expr *InitExpr;
20528 DeclRefExpr *Ref = nullptr;
20529 if (!VD && !SemaRef.CurContext->isDependentContext()) {
20530 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
20531 if (!isOpenMPCapturedDecl(D)) {
20532 ExprCaptures.push_back(Ref->getDecl());
20533 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20535 if (!RefRes.isUsable())
20536 continue;
20537 ExprResult PostUpdateRes =
20538 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
20539 SimpleRefExpr, RefRes.get());
20540 if (!PostUpdateRes.isUsable())
20541 continue;
20542 ExprPostUpdates.push_back(
20543 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
20544 }
20545 }
20546 }
20547 if (LinKind == OMPC_LINEAR_uval)
20548 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
20549 else
20550 InitExpr = VD ? SimpleRefExpr : Ref;
20553 /*DirectInit=*/false);
20554 DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc);
20555
20556 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
20557 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
20558 ? RefExpr->IgnoreParens()
20559 : Ref);
20560 Privates.push_back(PrivateRef);
20561 Inits.push_back(InitRef);
20562 }
20563
20564 if (Vars.empty())
20565 return nullptr;
20566
20567 Expr *StepExpr = Step;
20568 Expr *CalcStepExpr = nullptr;
20569 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
20570 !Step->isInstantiationDependent() &&
20572 SourceLocation StepLoc = Step->getBeginLoc();
20574 if (Val.isInvalid())
20575 return nullptr;
20576 StepExpr = Val.get();
20577
20578 // Build var to save the step value.
20579 VarDecl *SaveVar =
20580 buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step");
20581 ExprResult SaveRef =
20582 buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc);
20583 ExprResult CalcStep = SemaRef.BuildBinOp(
20584 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr);
20585 CalcStep =
20586 SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false);
20587
20588 // Warn about zero linear step (it would be probably better specified as
20589 // making corresponding variables 'const').
20590 if (std::optional<llvm::APSInt> Result =
20592 if (!Result->isNegative() && !Result->isStrictlyPositive())
20593 Diag(StepLoc, diag::warn_omp_linear_step_zero)
20594 << Vars[0] << (Vars.size() > 1);
20595 } else if (CalcStep.isUsable()) {
20596 // Calculate the step beforehand instead of doing this on each iteration.
20597 // (This is not used if the number of iterations may be kfold-ed).
20598 CalcStepExpr = CalcStep.get();
20599 }
20600 }
20601
20602 return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind,
20603 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
20604 Vars, Privates, Inits, StepExpr, CalcStepExpr,
20605 buildPreInits(getASTContext(), ExprCaptures),
20606 buildPostUpdate(SemaRef, ExprPostUpdates));
20607}
20608
20610 Expr *NumIterations, Sema &SemaRef,
20611 Scope *S, DSAStackTy *Stack) {
20612 // Walk the vars and build update/final expressions for the CodeGen.
20613 SmallVector<Expr *, 8> Updates;
20615 SmallVector<Expr *, 8> UsedExprs;
20616 Expr *Step = Clause.getStep();
20617 Expr *CalcStep = Clause.getCalcStep();
20618 // OpenMP [2.14.3.7, linear clause]
20619 // If linear-step is not specified it is assumed to be 1.
20620 if (!Step)
20621 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
20622 else if (CalcStep)
20623 Step = cast<BinaryOperator>(CalcStep)->getLHS();
20624 bool HasErrors = false;
20625 auto CurInit = Clause.inits().begin();
20626 auto CurPrivate = Clause.privates().begin();
20627 OpenMPLinearClauseKind LinKind = Clause.getModifier();
20628 for (Expr *RefExpr : Clause.varlists()) {
20629 SourceLocation ELoc;
20630 SourceRange ERange;
20631 Expr *SimpleRefExpr = RefExpr;
20632 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20633 ValueDecl *D = Res.first;
20634 if (Res.second || !D) {
20635 Updates.push_back(nullptr);
20636 Finals.push_back(nullptr);
20637 HasErrors = true;
20638 continue;
20639 }
20640 auto &&Info = Stack->isLoopControlVariable(D);
20641 // OpenMP [2.15.11, distribute simd Construct]
20642 // A list item may not appear in a linear clause, unless it is the loop
20643 // iteration variable.
20644 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
20645 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
20646 SemaRef.Diag(ELoc,
20647 diag::err_omp_linear_distribute_var_non_loop_iteration);
20648 Updates.push_back(nullptr);
20649 Finals.push_back(nullptr);
20650 HasErrors = true;
20651 continue;
20652 }
20653 Expr *InitExpr = *CurInit;
20654
20655 // Build privatized reference to the current linear var.
20656 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
20657 Expr *CapturedRef;
20658 if (LinKind == OMPC_LINEAR_uval)
20659 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
20660 else
20661 CapturedRef =
20662 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
20663 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
20664 /*RefersToCapture=*/true);
20665
20666 // Build update: Var = InitExpr + IV * Step
20668 if (!Info.first)
20670 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
20671 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
20672 else
20673 Update = *CurPrivate;
20674 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
20675 /*DiscardedValue*/ false);
20676
20677 // Build final: Var = PrivCopy;
20678 ExprResult Final;
20679 if (!Info.first)
20680 Final = SemaRef.BuildBinOp(
20681 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
20682 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
20683 else
20684 Final = *CurPrivate;
20685 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
20686 /*DiscardedValue*/ false);
20687
20688 if (!Update.isUsable() || !Final.isUsable()) {
20689 Updates.push_back(nullptr);
20690 Finals.push_back(nullptr);
20691 UsedExprs.push_back(nullptr);
20692 HasErrors = true;
20693 } else {
20694 Updates.push_back(Update.get());
20695 Finals.push_back(Final.get());
20696 if (!Info.first)
20697 UsedExprs.push_back(SimpleRefExpr);
20698 }
20699 ++CurInit;
20700 ++CurPrivate;
20701 }
20702 if (Expr *S = Clause.getStep())
20703 UsedExprs.push_back(S);
20704 // Fill the remaining part with the nullptr.
20705 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
20706 Clause.setUpdates(Updates);
20707 Clause.setFinals(Finals);
20708 Clause.setUsedExprs(UsedExprs);
20709 return HasErrors;
20710}
20711
20713 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
20714 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
20716 for (Expr *RefExpr : VarList) {
20717 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20718 SourceLocation ELoc;
20719 SourceRange ERange;
20720 Expr *SimpleRefExpr = RefExpr;
20721 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20722 if (Res.second) {
20723 // It will be analyzed later.
20724 Vars.push_back(RefExpr);
20725 }
20726 ValueDecl *D = Res.first;
20727 if (!D)
20728 continue;
20729
20730 QualType QType = D->getType();
20731 auto *VD = dyn_cast<VarDecl>(D);
20732
20733 // OpenMP [2.8.1, simd construct, Restrictions]
20734 // The type of list items appearing in the aligned clause must be
20735 // array, pointer, reference to array, or reference to pointer.
20737 const Type *Ty = QType.getTypePtrOrNull();
20738 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
20739 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
20740 << QType << getLangOpts().CPlusPlus << ERange;
20741 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20743 Diag(D->getLocation(),
20744 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20745 << D;
20746 continue;
20747 }
20748
20749 // OpenMP [2.8.1, simd construct, Restrictions]
20750 // A list-item cannot appear in more than one aligned clause.
20751 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
20752 Diag(ELoc, diag::err_omp_used_in_clause_twice)
20753 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
20754 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
20755 << getOpenMPClauseName(OMPC_aligned);
20756 continue;
20757 }
20758
20759 DeclRefExpr *Ref = nullptr;
20760 if (!VD && isOpenMPCapturedDecl(D))
20761 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
20762 Vars.push_back(SemaRef
20763 .DefaultFunctionArrayConversion(
20764 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
20765 .get());
20766 }
20767
20768 // OpenMP [2.8.1, simd construct, Description]
20769 // The parameter of the aligned clause, alignment, must be a constant
20770 // positive integer expression.
20771 // If no optional parameter is specified, implementation-defined default
20772 // alignments for SIMD instructions on the target platforms are assumed.
20773 if (Alignment != nullptr) {
20774 ExprResult AlignResult =
20775 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
20776 if (AlignResult.isInvalid())
20777 return nullptr;
20778 Alignment = AlignResult.get();
20779 }
20780 if (Vars.empty())
20781 return nullptr;
20782
20783 return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc,
20784 ColonLoc, EndLoc, Vars, Alignment);
20785}
20786
20788 SourceLocation StartLoc,
20789 SourceLocation LParenLoc,
20790 SourceLocation EndLoc) {
20792 SmallVector<Expr *, 8> SrcExprs;
20793 SmallVector<Expr *, 8> DstExprs;
20794 SmallVector<Expr *, 8> AssignmentOps;
20795 for (Expr *RefExpr : VarList) {
20796 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
20797 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20798 // It will be analyzed later.
20799 Vars.push_back(RefExpr);
20800 SrcExprs.push_back(nullptr);
20801 DstExprs.push_back(nullptr);
20802 AssignmentOps.push_back(nullptr);
20803 continue;
20804 }
20805
20806 SourceLocation ELoc = RefExpr->getExprLoc();
20807 // OpenMP [2.1, C/C++]
20808 // A list item is a variable name.
20809 // OpenMP [2.14.4.1, Restrictions, p.1]
20810 // A list item that appears in a copyin clause must be threadprivate.
20811 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
20812 if (!DE || !isa<VarDecl>(DE->getDecl())) {
20813 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
20814 << 0 << RefExpr->getSourceRange();
20815 continue;
20816 }
20817
20818 Decl *D = DE->getDecl();
20819 auto *VD = cast<VarDecl>(D);
20820
20821 QualType Type = VD->getType();
20823 // It will be analyzed later.
20824 Vars.push_back(DE);
20825 SrcExprs.push_back(nullptr);
20826 DstExprs.push_back(nullptr);
20827 AssignmentOps.push_back(nullptr);
20828 continue;
20829 }
20830
20831 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
20832 // A list item that appears in a copyin clause must be threadprivate.
20833 if (!DSAStack->isThreadPrivate(VD)) {
20834 Diag(ELoc, diag::err_omp_required_access)
20835 << getOpenMPClauseName(OMPC_copyin)
20836 << getOpenMPDirectiveName(OMPD_threadprivate);
20837 continue;
20838 }
20839
20840 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20841 // A variable of class type (or array thereof) that appears in a
20842 // copyin clause requires an accessible, unambiguous copy assignment
20843 // operator for the class type.
20844 QualType ElemType =
20846 VarDecl *SrcVD =
20847 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
20848 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20849 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
20850 SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
20851 VarDecl *DstVD =
20852 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst",
20853 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20854 DeclRefExpr *PseudoDstExpr =
20855 buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc());
20856 // For arrays generate assignment operation for single element and replace
20857 // it by the original array element in CodeGen.
20858 ExprResult AssignmentOp =
20859 SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
20860 PseudoDstExpr, PseudoSrcExpr);
20861 if (AssignmentOp.isInvalid())
20862 continue;
20863 AssignmentOp =
20864 SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
20865 /*DiscardedValue*/ false);
20866 if (AssignmentOp.isInvalid())
20867 continue;
20868
20869 DSAStack->addDSA(VD, DE, OMPC_copyin);
20870 Vars.push_back(DE);
20871 SrcExprs.push_back(PseudoSrcExpr);
20872 DstExprs.push_back(PseudoDstExpr);
20873 AssignmentOps.push_back(AssignmentOp.get());
20874 }
20875
20876 if (Vars.empty())
20877 return nullptr;
20878
20879 return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
20880 Vars, SrcExprs, DstExprs, AssignmentOps);
20881}
20882
20884 SourceLocation StartLoc,
20885 SourceLocation LParenLoc,
20886 SourceLocation EndLoc) {
20888 SmallVector<Expr *, 8> SrcExprs;
20889 SmallVector<Expr *, 8> DstExprs;
20890 SmallVector<Expr *, 8> AssignmentOps;
20891 for (Expr *RefExpr : VarList) {
20892 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20893 SourceLocation ELoc;
20894 SourceRange ERange;
20895 Expr *SimpleRefExpr = RefExpr;
20896 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20897 if (Res.second) {
20898 // It will be analyzed later.
20899 Vars.push_back(RefExpr);
20900 SrcExprs.push_back(nullptr);
20901 DstExprs.push_back(nullptr);
20902 AssignmentOps.push_back(nullptr);
20903 }
20904 ValueDecl *D = Res.first;
20905 if (!D)
20906 continue;
20907
20908 QualType Type = D->getType();
20909 auto *VD = dyn_cast<VarDecl>(D);
20910
20911 // OpenMP [2.14.4.2, Restrictions, p.2]
20912 // A list item that appears in a copyprivate clause may not appear in a
20913 // private or firstprivate clause on the single construct.
20914 if (!VD || !DSAStack->isThreadPrivate(VD)) {
20915 DSAStackTy::DSAVarData DVar =
20916 DSAStack->getTopDSA(D, /*FromParent=*/false);
20917 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
20918 DVar.RefExpr) {
20919 Diag(ELoc, diag::err_omp_wrong_dsa)
20920 << getOpenMPClauseName(DVar.CKind)
20921 << getOpenMPClauseName(OMPC_copyprivate);
20923 continue;
20924 }
20925
20926 // OpenMP [2.11.4.2, Restrictions, p.1]
20927 // All list items that appear in a copyprivate clause must be either
20928 // threadprivate or private in the enclosing context.
20929 if (DVar.CKind == OMPC_unknown) {
20930 DVar = DSAStack->getImplicitDSA(D, false);
20931 if (DVar.CKind == OMPC_shared) {
20932 Diag(ELoc, diag::err_omp_required_access)
20933 << getOpenMPClauseName(OMPC_copyprivate)
20934 << "threadprivate or private in the enclosing context";
20936 continue;
20937 }
20938 }
20939 }
20940
20941 // Variably modified types are not supported.
20943 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
20944 << getOpenMPClauseName(OMPC_copyprivate) << Type
20945 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
20946 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20948 Diag(D->getLocation(),
20949 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20950 << D;
20951 continue;
20952 }
20953
20954 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20955 // A variable of class type (or array thereof) that appears in a
20956 // copyin clause requires an accessible, unambiguous copy assignment
20957 // operator for the class type.
20959 .getBaseElementType(Type.getNonReferenceType())
20961 VarDecl *SrcVD =
20962 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
20963 D->hasAttrs() ? &D->getAttrs() : nullptr);
20964 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc);
20965 VarDecl *DstVD =
20966 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
20967 D->hasAttrs() ? &D->getAttrs() : nullptr);
20968 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
20969 ExprResult AssignmentOp = SemaRef.BuildBinOp(
20970 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
20971 if (AssignmentOp.isInvalid())
20972 continue;
20973 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
20974 /*DiscardedValue*/ false);
20975 if (AssignmentOp.isInvalid())
20976 continue;
20977
20978 // No need to mark vars as copyprivate, they are already threadprivate or
20979 // implicitly private.
20980 assert(VD || isOpenMPCapturedDecl(D));
20981 Vars.push_back(
20982 VD ? RefExpr->IgnoreParens()
20983 : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false));
20984 SrcExprs.push_back(PseudoSrcExpr);
20985 DstExprs.push_back(PseudoDstExpr);
20986 AssignmentOps.push_back(AssignmentOp.get());
20987 }
20988
20989 if (Vars.empty())
20990 return nullptr;
20991
20992 return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc,
20993 EndLoc, Vars, SrcExprs, DstExprs,
20994 AssignmentOps);
20995}
20996
20998 SourceLocation StartLoc,
20999 SourceLocation LParenLoc,
21000 SourceLocation EndLoc) {
21001 if (VarList.empty())
21002 return nullptr;
21003
21004 return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21005 VarList);
21006}
21007
21008/// Tries to find omp_depend_t. type.
21009static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
21010 bool Diagnose = true) {
21011 QualType OMPDependT = Stack->getOMPDependT();
21012 if (!OMPDependT.isNull())
21013 return true;
21014 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
21015 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
21016 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
21017 if (Diagnose)
21018 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
21019 return false;
21020 }
21021 Stack->setOMPDependT(PT.get());
21022 return true;
21023}
21024
21026 SourceLocation StartLoc,
21027 SourceLocation LParenLoc,
21028 SourceLocation EndLoc) {
21029 if (!Depobj)
21030 return nullptr;
21031
21032 bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack);
21033
21034 // OpenMP 5.0, 2.17.10.1 depobj Construct
21035 // depobj is an lvalue expression of type omp_depend_t.
21036 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
21037 !Depobj->isInstantiationDependent() &&
21039 (OMPDependTFound && !getASTContext().typesAreCompatible(
21040 DSAStack->getOMPDependT(), Depobj->getType(),
21041 /*CompareUnqualified=*/true))) {
21042 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21043 << 0 << Depobj->getType() << Depobj->getSourceRange();
21044 }
21045
21046 if (!Depobj->isLValue()) {
21047 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21048 << 1 << Depobj->getSourceRange();
21049 }
21050
21051 return OMPDepobjClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21052 Depobj);
21053}
21054
21055namespace {
21056// Utility struct that gathers the related info for doacross clause.
21057struct DoacrossDataInfoTy {
21058 // The list of expressions.
21060 // The OperatorOffset for doacross loop.
21062 // The depended loop count.
21063 llvm::APSInt TotalDepCount;
21064};
21065} // namespace
21066static DoacrossDataInfoTy
21068 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
21069 SourceLocation EndLoc) {
21070
21073 llvm::APSInt DepCounter(/*BitWidth=*/32);
21074 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
21075
21076 if (const Expr *OrderedCountExpr =
21077 Stack->getParentOrderedRegionParam().first) {
21078 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
21079 TotalDepCount.setIsUnsigned(/*Val=*/true);
21080 }
21081
21082 for (Expr *RefExpr : VarList) {
21083 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
21084 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21085 // It will be analyzed later.
21086 Vars.push_back(RefExpr);
21087 continue;
21088 }
21089
21090 SourceLocation ELoc = RefExpr->getExprLoc();
21091 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
21092 if (!IsSource) {
21093 if (Stack->getParentOrderedRegionParam().first &&
21094 DepCounter >= TotalDepCount) {
21095 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
21096 continue;
21097 }
21098 ++DepCounter;
21099 // OpenMP [2.13.9, Summary]
21100 // depend(dependence-type : vec), where dependence-type is:
21101 // 'sink' and where vec is the iteration vector, which has the form:
21102 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
21103 // where n is the value specified by the ordered clause in the loop
21104 // directive, xi denotes the loop iteration variable of the i-th nested
21105 // loop associated with the loop directive, and di is a constant
21106 // non-negative integer.
21107 if (SemaRef.CurContext->isDependentContext()) {
21108 // It will be analyzed later.
21109 Vars.push_back(RefExpr);
21110 continue;
21111 }
21112 SimpleExpr = SimpleExpr->IgnoreImplicit();
21114 SourceLocation OOLoc;
21115 Expr *LHS = SimpleExpr;
21116 Expr *RHS = nullptr;
21117 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
21118 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
21119 OOLoc = BO->getOperatorLoc();
21120 LHS = BO->getLHS()->IgnoreParenImpCasts();
21121 RHS = BO->getRHS()->IgnoreParenImpCasts();
21122 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
21123 OOK = OCE->getOperator();
21124 OOLoc = OCE->getOperatorLoc();
21125 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
21126 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
21127 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
21128 OOK = MCE->getMethodDecl()
21129 ->getNameInfo()
21130 .getName()
21131 .getCXXOverloadedOperator();
21132 OOLoc = MCE->getCallee()->getExprLoc();
21133 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
21134 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
21135 }
21136 SourceLocation ELoc;
21137 SourceRange ERange;
21138 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
21139 if (Res.second) {
21140 // It will be analyzed later.
21141 Vars.push_back(RefExpr);
21142 }
21143 ValueDecl *D = Res.first;
21144 if (!D)
21145 continue;
21146
21147 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
21148 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
21149 continue;
21150 }
21151 if (RHS) {
21152 ExprResult RHSRes =
21154 RHS, OMPC_depend, /*StrictlyPositive=*/false);
21155 if (RHSRes.isInvalid())
21156 continue;
21157 }
21158 if (!SemaRef.CurContext->isDependentContext() &&
21159 Stack->getParentOrderedRegionParam().first &&
21160 DepCounter != Stack->isParentLoopControlVariable(D).first) {
21161 const ValueDecl *VD =
21162 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
21163 if (VD)
21164 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21165 << 1 << VD;
21166 else
21167 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21168 << 0;
21169 continue;
21170 }
21171 OpsOffs.emplace_back(RHS, OOK);
21172 }
21173 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21174 }
21175 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
21176 TotalDepCount > VarList.size() &&
21177 Stack->getParentOrderedRegionParam().first &&
21178 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
21179 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
21180 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
21181 }
21182 return {Vars, OpsOffs, TotalDepCount};
21183}
21184
21186 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
21187 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
21188 SourceLocation EndLoc) {
21189 OpenMPDependClauseKind DepKind = Data.DepKind;
21190 SourceLocation DepLoc = Data.DepLoc;
21191 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
21192 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
21193 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21194 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
21195 return nullptr;
21196 }
21197 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
21198 DepKind == OMPC_DEPEND_mutexinoutset) {
21199 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
21200 return nullptr;
21201 }
21202 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
21203 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21204 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
21205 DepKind == OMPC_DEPEND_sink ||
21206 ((getLangOpts().OpenMP < 50 ||
21207 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21208 DepKind == OMPC_DEPEND_depobj))) {
21209 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
21210 OMPC_DEPEND_outallmemory,
21211 OMPC_DEPEND_inoutallmemory};
21212 if (getLangOpts().OpenMP < 50 ||
21213 DSAStack->getCurrentDirective() == OMPD_depobj)
21214 Except.push_back(OMPC_DEPEND_depobj);
21215 if (getLangOpts().OpenMP < 51)
21216 Except.push_back(OMPC_DEPEND_inoutset);
21217 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
21218 ? "depend modifier(iterator) or "
21219 : "";
21220 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21221 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
21222 /*Last=*/OMPC_DEPEND_unknown,
21223 Except)
21224 << getOpenMPClauseName(OMPC_depend);
21225 return nullptr;
21226 }
21227 if (DepModifier &&
21228 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
21229 Diag(DepModifier->getExprLoc(),
21230 diag::err_omp_depend_sink_source_with_modifier);
21231 return nullptr;
21232 }
21233 if (DepModifier &&
21234 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
21235 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
21236
21239 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
21240
21241 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
21242 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
21243 SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
21244 Vars = VarOffset.Vars;
21245 OpsOffs = VarOffset.OpsOffs;
21246 TotalDepCount = VarOffset.TotalDepCount;
21247 } else {
21248 for (Expr *RefExpr : VarList) {
21249 assert(RefExpr && "NULL expr in OpenMP shared clause.");
21250 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21251 // It will be analyzed later.
21252 Vars.push_back(RefExpr);
21253 continue;
21254 }
21255
21256 SourceLocation ELoc = RefExpr->getExprLoc();
21257 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
21258 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
21259 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
21260 if (OMPDependTFound)
21261 OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack,
21262 DepKind == OMPC_DEPEND_depobj);
21263 if (DepKind == OMPC_DEPEND_depobj) {
21264 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21265 // List items used in depend clauses with the depobj dependence type
21266 // must be expressions of the omp_depend_t type.
21267 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21268 !RefExpr->isInstantiationDependent() &&
21269 !RefExpr->containsUnexpandedParameterPack() &&
21270 (OMPDependTFound &&
21271 !getASTContext().hasSameUnqualifiedType(
21272 DSAStack->getOMPDependT(), RefExpr->getType()))) {
21273 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21274 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
21275 continue;
21276 }
21277 if (!RefExpr->isLValue()) {
21278 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21279 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
21280 continue;
21281 }
21282 } else {
21283 // OpenMP 5.0 [2.17.11, Restrictions]
21284 // List items used in depend clauses cannot be zero-length array
21285 // sections.
21286 QualType ExprTy = RefExpr->getType().getNonReferenceType();
21287 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
21288 if (OASE) {
21289 QualType BaseType =
21291 if (BaseType.isNull())
21292 return nullptr;
21293 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21294 ExprTy = ATy->getElementType();
21295 else
21296 ExprTy = BaseType->getPointeeType();
21297 if (BaseType.isNull() || ExprTy.isNull())
21298 return nullptr;
21299 ExprTy = ExprTy.getNonReferenceType();
21300 const Expr *Length = OASE->getLength();
21302 if (Length && !Length->isValueDependent() &&
21303 Length->EvaluateAsInt(Result, getASTContext()) &&
21304 Result.Val.getInt().isZero()) {
21305 Diag(ELoc,
21306 diag::err_omp_depend_zero_length_array_section_not_allowed)
21307 << SimpleExpr->getSourceRange();
21308 continue;
21309 }
21310 }
21311
21312 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21313 // List items used in depend clauses with the in, out, inout,
21314 // inoutset, or mutexinoutset dependence types cannot be
21315 // expressions of the omp_depend_t type.
21316 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21317 !RefExpr->isInstantiationDependent() &&
21318 !RefExpr->containsUnexpandedParameterPack() &&
21319 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
21320 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
21321 ExprTy.getTypePtr()))) {
21322 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21323 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21324 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21325 << RefExpr->getSourceRange();
21326 continue;
21327 }
21328
21329 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
21330 if (ASE && !ASE->getBase()->isTypeDependent() &&
21331 !ASE->getBase()
21332 ->getType()
21333 .getNonReferenceType()
21334 ->isPointerType() &&
21335 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
21336 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21337 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21338 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21339 << RefExpr->getSourceRange();
21340 continue;
21341 }
21342
21343 ExprResult Res;
21344 {
21346 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
21347 RefExpr->IgnoreParenImpCasts());
21348 }
21349 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
21350 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
21351 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21352 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21353 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21354 << RefExpr->getSourceRange();
21355 continue;
21356 }
21357 }
21358 }
21359 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21360 }
21361 }
21362
21363 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
21364 DepKind != OMPC_DEPEND_outallmemory &&
21365 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
21366 return nullptr;
21367
21368 auto *C = OMPDependClause::Create(
21369 getASTContext(), StartLoc, LParenLoc, EndLoc,
21370 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
21371 TotalDepCount.getZExtValue());
21372 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
21373 DSAStack->isParentOrderedRegion())
21374 DSAStack->addDoacrossDependClause(C, OpsOffs);
21375 return C;
21376}
21377
21380 SourceLocation LParenLoc, SourceLocation ModifierLoc,
21381 SourceLocation EndLoc) {
21382 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
21383 "Unexpected device modifier in OpenMP < 50.");
21384
21385 bool ErrorFound = false;
21386 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
21387 std::string Values =
21388 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
21389 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21390 << Values << getOpenMPClauseName(OMPC_device);
21391 ErrorFound = true;
21392 }
21393
21394 Expr *ValExpr = Device;
21395 Stmt *HelperValStmt = nullptr;
21396
21397 // OpenMP [2.9.1, Restrictions]
21398 // The device expression must evaluate to a non-negative integer value.
21399 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device,
21400 /*StrictlyPositive=*/false) ||
21401 ErrorFound;
21402 if (ErrorFound)
21403 return nullptr;
21404
21405 // OpenMP 5.0 [2.12.5, Restrictions]
21406 // In case of ancestor device-modifier, a requires directive with
21407 // the reverse_offload clause must be specified.
21408 if (Modifier == OMPC_DEVICE_ancestor) {
21409 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
21411 StartLoc,
21412 diag::err_omp_device_ancestor_without_requires_reverse_offload);
21413 ErrorFound = true;
21414 }
21415 }
21416
21417 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
21418 OpenMPDirectiveKind CaptureRegion =
21419 getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP);
21420 if (CaptureRegion != OMPD_unknown &&
21422 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
21423 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21424 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
21425 HelperValStmt = buildPreInits(getASTContext(), Captures);
21426 }
21427
21428 return new (getASTContext())
21429 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
21430 LParenLoc, ModifierLoc, EndLoc);
21431}
21432
21434 DSAStackTy *Stack, QualType QTy,
21435 bool FullCheck = true) {
21436 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
21437 return false;
21438 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
21439 !QTy.isTriviallyCopyableType(SemaRef.Context))
21440 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
21441 return true;
21442}
21443
21444/// Return true if it can be proven that the provided array expression
21445/// (array section or array subscript) does NOT specify the whole size of the
21446/// array whose base type is \a BaseQTy.
21448 const Expr *E,
21449 QualType BaseQTy) {
21450 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21451
21452 // If this is an array subscript, it refers to the whole size if the size of
21453 // the dimension is constant and equals 1. Also, an array section assumes the
21454 // format of an array subscript if no colon is used.
21455 if (isa<ArraySubscriptExpr>(E) ||
21456 (OASE && OASE->getColonLocFirst().isInvalid())) {
21457 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21458 return ATy->getSExtSize() != 1;
21459 // Size can't be evaluated statically.
21460 return false;
21461 }
21462
21463 assert(OASE && "Expecting array section if not an array subscript.");
21464 const Expr *LowerBound = OASE->getLowerBound();
21465 const Expr *Length = OASE->getLength();
21466
21467 // If there is a lower bound that does not evaluates to zero, we are not
21468 // covering the whole dimension.
21469 if (LowerBound) {
21471 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
21472 return false; // Can't get the integer value as a constant.
21473
21474 llvm::APSInt ConstLowerBound = Result.Val.getInt();
21475 if (ConstLowerBound.getSExtValue())
21476 return true;
21477 }
21478
21479 // If we don't have a length we covering the whole dimension.
21480 if (!Length)
21481 return false;
21482
21483 // If the base is a pointer, we don't have a way to get the size of the
21484 // pointee.
21485 if (BaseQTy->isPointerType())
21486 return false;
21487
21488 // We can only check if the length is the same as the size of the dimension
21489 // if we have a constant array.
21490 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
21491 if (!CATy)
21492 return false;
21493
21495 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21496 return false; // Can't get the integer value as a constant.
21497
21498 llvm::APSInt ConstLength = Result.Val.getInt();
21499 return CATy->getSExtSize() != ConstLength.getSExtValue();
21500}
21501
21502// Return true if it can be proven that the provided array expression (array
21503// section or array subscript) does NOT specify a single element of the array
21504// whose base type is \a BaseQTy.
21506 const Expr *E,
21507 QualType BaseQTy) {
21508 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21509
21510 // An array subscript always refer to a single element. Also, an array section
21511 // assumes the format of an array subscript if no colon is used.
21512 if (isa<ArraySubscriptExpr>(E) ||
21513 (OASE && OASE->getColonLocFirst().isInvalid()))
21514 return false;
21515
21516 assert(OASE && "Expecting array section if not an array subscript.");
21517 const Expr *Length = OASE->getLength();
21518
21519 // If we don't have a length we have to check if the array has unitary size
21520 // for this dimension. Also, we should always expect a length if the base type
21521 // is pointer.
21522 if (!Length) {
21523 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21524 return ATy->getSExtSize() != 1;
21525 // We cannot assume anything.
21526 return false;
21527 }
21528
21529 // Check if the length evaluates to 1.
21531 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21532 return false; // Can't get the integer value as a constant.
21533
21534 llvm::APSInt ConstLength = Result.Val.getInt();
21535 return ConstLength.getSExtValue() != 1;
21536}
21537
21538// The base of elements of list in a map clause have to be either:
21539// - a reference to variable or field.
21540// - a member expression.
21541// - an array expression.
21542//
21543// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
21544// reference to 'r'.
21545//
21546// If we have:
21547//
21548// struct SS {
21549// Bla S;
21550// foo() {
21551// #pragma omp target map (S.Arr[:12]);
21552// }
21553// }
21554//
21555// We want to retrieve the member expression 'this->S';
21556
21557// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
21558// If a list item is an array section, it must specify contiguous storage.
21559//
21560// For this restriction it is sufficient that we make sure only references
21561// to variables or fields and array expressions, and that no array sections
21562// exist except in the rightmost expression (unless they cover the whole
21563// dimension of the array). E.g. these would be invalid:
21564//
21565// r.ArrS[3:5].Arr[6:7]
21566//
21567// r.ArrS[3:5].x
21568//
21569// but these would be valid:
21570// r.ArrS[3].Arr[6:7]
21571//
21572// r.ArrS[3].x
21573namespace {
21574class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
21575 Sema &SemaRef;
21576 OpenMPClauseKind CKind = OMPC_unknown;
21577 OpenMPDirectiveKind DKind = OMPD_unknown;
21579 bool IsNonContiguous = false;
21580 bool NoDiagnose = false;
21581 const Expr *RelevantExpr = nullptr;
21582 bool AllowUnitySizeArraySection = true;
21583 bool AllowWholeSizeArraySection = true;
21584 bool AllowAnotherPtr = true;
21585 SourceLocation ELoc;
21586 SourceRange ERange;
21587
21588 void emitErrorMsg() {
21589 // If nothing else worked, this is not a valid map clause expression.
21590 if (SemaRef.getLangOpts().OpenMP < 50) {
21591 SemaRef.Diag(ELoc,
21592 diag::err_omp_expected_named_var_member_or_array_expression)
21593 << ERange;
21594 } else {
21595 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21596 << getOpenMPClauseName(CKind) << ERange;
21597 }
21598 }
21599
21600public:
21601 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
21602 if (!isa<VarDecl>(DRE->getDecl())) {
21603 emitErrorMsg();
21604 return false;
21605 }
21606 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21607 RelevantExpr = DRE;
21608 // Record the component.
21609 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
21610 return true;
21611 }
21612
21613 bool VisitMemberExpr(MemberExpr *ME) {
21614 Expr *E = ME;
21615 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
21616
21617 if (isa<CXXThisExpr>(BaseE)) {
21618 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21619 // We found a base expression: this->Val.
21620 RelevantExpr = ME;
21621 } else {
21622 E = BaseE;
21623 }
21624
21625 if (!isa<FieldDecl>(ME->getMemberDecl())) {
21626 if (!NoDiagnose) {
21627 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
21628 << ME->getSourceRange();
21629 return false;
21630 }
21631 if (RelevantExpr)
21632 return false;
21633 return Visit(E);
21634 }
21635
21636 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
21637
21638 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
21639 // A bit-field cannot appear in a map clause.
21640 //
21641 if (FD->isBitField()) {
21642 if (!NoDiagnose) {
21643 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
21644 << ME->getSourceRange() << getOpenMPClauseName(CKind);
21645 return false;
21646 }
21647 if (RelevantExpr)
21648 return false;
21649 return Visit(E);
21650 }
21651
21652 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21653 // If the type of a list item is a reference to a type T then the type
21654 // will be considered to be T for all purposes of this clause.
21655 QualType CurType = BaseE->getType().getNonReferenceType();
21656
21657 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
21658 // A list item cannot be a variable that is a member of a structure with
21659 // a union type.
21660 //
21661 if (CurType->isUnionType()) {
21662 if (!NoDiagnose) {
21663 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
21664 << ME->getSourceRange();
21665 return false;
21666 }
21667 return RelevantExpr || Visit(E);
21668 }
21669
21670 // If we got a member expression, we should not expect any array section
21671 // before that:
21672 //
21673 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
21674 // If a list item is an element of a structure, only the rightmost symbol
21675 // of the variable reference can be an array section.
21676 //
21677 AllowUnitySizeArraySection = false;
21678 AllowWholeSizeArraySection = false;
21679
21680 // Record the component.
21681 Components.emplace_back(ME, FD, IsNonContiguous);
21682 return RelevantExpr || Visit(E);
21683 }
21684
21685 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
21686 Expr *E = AE->getBase()->IgnoreParenImpCasts();
21687
21688 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
21689 if (!NoDiagnose) {
21690 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21691 << 0 << AE->getSourceRange();
21692 return false;
21693 }
21694 return RelevantExpr || Visit(E);
21695 }
21696
21697 // If we got an array subscript that express the whole dimension we
21698 // can have any array expressions before. If it only expressing part of
21699 // the dimension, we can only have unitary-size array expressions.
21701 AllowWholeSizeArraySection = false;
21702
21703 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
21704 Expr::EvalResult Result;
21705 if (!AE->getIdx()->isValueDependent() &&
21706 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
21707 !Result.Val.getInt().isZero()) {
21708 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21709 diag::err_omp_invalid_map_this_expr);
21710 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21711 diag::note_omp_invalid_subscript_on_this_ptr_map);
21712 }
21713 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21714 RelevantExpr = TE;
21715 }
21716
21717 // Record the component - we don't have any declaration associated.
21718 Components.emplace_back(AE, nullptr, IsNonContiguous);
21719
21720 return RelevantExpr || Visit(E);
21721 }
21722
21723 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
21724 // After OMP 5.0 Array section in reduction clause will be implicitly
21725 // mapped
21726 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
21727 "Array sections cannot be implicitly mapped.");
21728 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21729 QualType CurType =
21731
21732 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21733 // If the type of a list item is a reference to a type T then the type
21734 // will be considered to be T for all purposes of this clause.
21735 if (CurType->isReferenceType())
21736 CurType = CurType->getPointeeType();
21737
21738 bool IsPointer = CurType->isAnyPointerType();
21739
21740 if (!IsPointer && !CurType->isArrayType()) {
21741 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21742 << 0 << OASE->getSourceRange();
21743 return false;
21744 }
21745
21746 bool NotWhole =
21747 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
21748 bool NotUnity =
21749 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
21750
21751 if (AllowWholeSizeArraySection) {
21752 // Any array section is currently allowed. Allowing a whole size array
21753 // section implies allowing a unity array section as well.
21754 //
21755 // If this array section refers to the whole dimension we can still
21756 // accept other array sections before this one, except if the base is a
21757 // pointer. Otherwise, only unitary sections are accepted.
21758 if (NotWhole || IsPointer)
21759 AllowWholeSizeArraySection = false;
21760 } else if (DKind == OMPD_target_update &&
21761 SemaRef.getLangOpts().OpenMP >= 50) {
21762 if (IsPointer && !AllowAnotherPtr)
21763 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
21764 << /*array of unknown bound */ 1;
21765 else
21766 IsNonContiguous = true;
21767 } else if (AllowUnitySizeArraySection && NotUnity) {
21768 // A unity or whole array section is not allowed and that is not
21769 // compatible with the properties of the current array section.
21770 if (NoDiagnose)
21771 return false;
21772 SemaRef.Diag(ELoc,
21773 diag::err_array_section_does_not_specify_contiguous_storage)
21774 << OASE->getSourceRange();
21775 return false;
21776 }
21777
21778 if (IsPointer)
21779 AllowAnotherPtr = false;
21780
21781 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
21782 Expr::EvalResult ResultR;
21783 Expr::EvalResult ResultL;
21784 if (!OASE->getLength()->isValueDependent() &&
21785 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
21786 !ResultR.Val.getInt().isOne()) {
21787 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21788 diag::err_omp_invalid_map_this_expr);
21789 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21790 diag::note_omp_invalid_length_on_this_ptr_mapping);
21791 }
21792 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
21793 OASE->getLowerBound()->EvaluateAsInt(ResultL,
21794 SemaRef.getASTContext()) &&
21795 !ResultL.Val.getInt().isZero()) {
21796 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21797 diag::err_omp_invalid_map_this_expr);
21798 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21799 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
21800 }
21801 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21802 RelevantExpr = TE;
21803 }
21804
21805 // Record the component - we don't have any declaration associated.
21806 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
21807 return RelevantExpr || Visit(E);
21808 }
21809 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
21810 Expr *Base = E->getBase();
21811
21812 // Record the component - we don't have any declaration associated.
21813 Components.emplace_back(E, nullptr, IsNonContiguous);
21814
21815 return Visit(Base->IgnoreParenImpCasts());
21816 }
21817
21818 bool VisitUnaryOperator(UnaryOperator *UO) {
21819 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
21820 UO->getOpcode() != UO_Deref) {
21821 emitErrorMsg();
21822 return false;
21823 }
21824 if (!RelevantExpr) {
21825 // Record the component if haven't found base decl.
21826 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
21827 }
21828 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
21829 }
21830 bool VisitBinaryOperator(BinaryOperator *BO) {
21831 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
21832 emitErrorMsg();
21833 return false;
21834 }
21835
21836 // Pointer arithmetic is the only thing we expect to happen here so after we
21837 // make sure the binary operator is a pointer type, the only thing we need
21838 // to do is to visit the subtree that has the same type as root (so that we
21839 // know the other subtree is just an offset)
21840 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
21841 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
21842 Components.emplace_back(BO, nullptr, false);
21843 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
21844 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
21845 "Either LHS or RHS have base decl inside");
21846 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
21847 return RelevantExpr || Visit(LE);
21848 return RelevantExpr || Visit(RE);
21849 }
21850 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
21851 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21852 RelevantExpr = CTE;
21853 Components.emplace_back(CTE, nullptr, IsNonContiguous);
21854 return true;
21855 }
21856 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
21857 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21858 Components.emplace_back(COCE, nullptr, IsNonContiguous);
21859 return true;
21860 }
21861 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
21862 Expr *Source = E->getSourceExpr();
21863 if (!Source) {
21864 emitErrorMsg();
21865 return false;
21866 }
21867 return Visit(Source);
21868 }
21869 bool VisitStmt(Stmt *) {
21870 emitErrorMsg();
21871 return false;
21872 }
21873 const Expr *getFoundBase() const { return RelevantExpr; }
21874 explicit MapBaseChecker(
21875 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
21877 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
21878 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
21879 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
21880};
21881} // namespace
21882
21883/// Return the expression of the base of the mappable expression or null if it
21884/// cannot be determined and do all the necessary checks to see if the
21885/// expression is valid as a standalone mappable expression. In the process,
21886/// record all the components of the expression.
21888 Sema &SemaRef, Expr *E,
21890 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
21891 SourceLocation ELoc = E->getExprLoc();
21892 SourceRange ERange = E->getSourceRange();
21893 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
21894 ERange);
21895 if (Checker.Visit(E->IgnoreParens())) {
21896 // Check if the highest dimension array section has length specified
21897 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
21898 (CKind == OMPC_to || CKind == OMPC_from)) {
21899 auto CI = CurComponents.rbegin();
21900 auto CE = CurComponents.rend();
21901 for (; CI != CE; ++CI) {
21902 const auto *OASE =
21903 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
21904 if (!OASE)
21905 continue;
21906 if (OASE && OASE->getLength())
21907 break;
21908 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
21909 << ERange;
21910 }
21911 }
21912 return Checker.getFoundBase();
21913 }
21914 return nullptr;
21915}
21916
21917// Return true if expression E associated with value VD has conflicts with other
21918// map information.
21920 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
21921 bool CurrentRegionOnly,
21923 OpenMPClauseKind CKind) {
21924 assert(VD && E);
21925 SourceLocation ELoc = E->getExprLoc();
21926 SourceRange ERange = E->getSourceRange();
21927
21928 // In order to easily check the conflicts we need to match each component of
21929 // the expression under test with the components of the expressions that are
21930 // already in the stack.
21931
21932 assert(!CurComponents.empty() && "Map clause expression with no components!");
21933 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
21934 "Map clause expression with unexpected base!");
21935
21936 // Variables to help detecting enclosing problems in data environment nests.
21937 bool IsEnclosedByDataEnvironmentExpr = false;
21938 const Expr *EnclosingExpr = nullptr;
21939
21940 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
21941 VD, CurrentRegionOnly,
21942 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
21943 ERange, CKind, &EnclosingExpr,
21945 StackComponents,
21946 OpenMPClauseKind Kind) {
21947 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
21948 return false;
21949 assert(!StackComponents.empty() &&
21950 "Map clause expression with no components!");
21951 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
21952 "Map clause expression with unexpected base!");
21953 (void)VD;
21954
21955 // The whole expression in the stack.
21956 const Expr *RE = StackComponents.front().getAssociatedExpression();
21957
21958 // Expressions must start from the same base. Here we detect at which
21959 // point both expressions diverge from each other and see if we can
21960 // detect if the memory referred to both expressions is contiguous and
21961 // do not overlap.
21962 auto CI = CurComponents.rbegin();
21963 auto CE = CurComponents.rend();
21964 auto SI = StackComponents.rbegin();
21965 auto SE = StackComponents.rend();
21966 for (; CI != CE && SI != SE; ++CI, ++SI) {
21967
21968 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
21969 // At most one list item can be an array item derived from a given
21970 // variable in map clauses of the same construct.
21971 if (CurrentRegionOnly &&
21972 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
21973 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
21974 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
21975 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
21976 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
21977 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
21978 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
21979 diag::err_omp_multiple_array_items_in_map_clause)
21980 << CI->getAssociatedExpression()->getSourceRange();
21981 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
21982 diag::note_used_here)
21983 << SI->getAssociatedExpression()->getSourceRange();
21984 return true;
21985 }
21986
21987 // Do both expressions have the same kind?
21988 if (CI->getAssociatedExpression()->getStmtClass() !=
21989 SI->getAssociatedExpression()->getStmtClass())
21990 break;
21991
21992 // Are we dealing with different variables/fields?
21993 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
21994 break;
21995 }
21996 // Check if the extra components of the expressions in the enclosing
21997 // data environment are redundant for the current base declaration.
21998 // If they are, the maps completely overlap, which is legal.
21999 for (; SI != SE; ++SI) {
22000 QualType Type;
22001 if (const auto *ASE =
22002 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
22003 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
22004 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
22005 SI->getAssociatedExpression())) {
22006 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
22007 Type = ArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
22008 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
22009 SI->getAssociatedExpression())) {
22010 Type = OASE->getBase()->getType()->getPointeeType();
22011 }
22012 if (Type.isNull() || Type->isAnyPointerType() ||
22014 SemaRef, SI->getAssociatedExpression(), Type))
22015 break;
22016 }
22017
22018 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
22019 // List items of map clauses in the same construct must not share
22020 // original storage.
22021 //
22022 // If the expressions are exactly the same or one is a subset of the
22023 // other, it means they are sharing storage.
22024 if (CI == CE && SI == SE) {
22025 if (CurrentRegionOnly) {
22026 if (CKind == OMPC_map) {
22027 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22028 } else {
22029 assert(CKind == OMPC_to || CKind == OMPC_from);
22030 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22031 << ERange;
22032 }
22033 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22034 << RE->getSourceRange();
22035 return true;
22036 }
22037 // If we find the same expression in the enclosing data environment,
22038 // that is legal.
22039 IsEnclosedByDataEnvironmentExpr = true;
22040 return false;
22041 }
22042
22043 QualType DerivedType =
22044 std::prev(CI)->getAssociatedDeclaration()->getType();
22045 SourceLocation DerivedLoc =
22046 std::prev(CI)->getAssociatedExpression()->getExprLoc();
22047
22048 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22049 // If the type of a list item is a reference to a type T then the type
22050 // will be considered to be T for all purposes of this clause.
22051 DerivedType = DerivedType.getNonReferenceType();
22052
22053 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
22054 // A variable for which the type is pointer and an array section
22055 // derived from that variable must not appear as list items of map
22056 // clauses of the same construct.
22057 //
22058 // Also, cover one of the cases in:
22059 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
22060 // If any part of the original storage of a list item has corresponding
22061 // storage in the device data environment, all of the original storage
22062 // must have corresponding storage in the device data environment.
22063 //
22064 if (DerivedType->isAnyPointerType()) {
22065 if (CI == CE || SI == SE) {
22066 SemaRef.Diag(
22067 DerivedLoc,
22068 diag::err_omp_pointer_mapped_along_with_derived_section)
22069 << DerivedLoc;
22070 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22071 << RE->getSourceRange();
22072 return true;
22073 }
22074 if (CI->getAssociatedExpression()->getStmtClass() !=
22075 SI->getAssociatedExpression()->getStmtClass() ||
22076 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
22077 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
22078 assert(CI != CE && SI != SE);
22079 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
22080 << DerivedLoc;
22081 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22082 << RE->getSourceRange();
22083 return true;
22084 }
22085 }
22086
22087 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
22088 // List items of map clauses in the same construct must not share
22089 // original storage.
22090 //
22091 // An expression is a subset of the other.
22092 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
22093 if (CKind == OMPC_map) {
22094 if (CI != CE || SI != SE) {
22095 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
22096 // a pointer.
22097 auto Begin =
22098 CI != CE ? CurComponents.begin() : StackComponents.begin();
22099 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
22100 auto It = Begin;
22101 while (It != End && !It->getAssociatedDeclaration())
22102 std::advance(It, 1);
22103 assert(It != End &&
22104 "Expected at least one component with the declaration.");
22105 if (It != Begin && It->getAssociatedDeclaration()
22106 ->getType()
22107 .getCanonicalType()
22108 ->isAnyPointerType()) {
22109 IsEnclosedByDataEnvironmentExpr = false;
22110 EnclosingExpr = nullptr;
22111 return false;
22112 }
22113 }
22114 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22115 } else {
22116 assert(CKind == OMPC_to || CKind == OMPC_from);
22117 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22118 << ERange;
22119 }
22120 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22121 << RE->getSourceRange();
22122 return true;
22123 }
22124
22125 // The current expression uses the same base as other expression in the
22126 // data environment but does not contain it completely.
22127 if (!CurrentRegionOnly && SI != SE)
22128 EnclosingExpr = RE;
22129
22130 // The current expression is a subset of the expression in the data
22131 // environment.
22132 IsEnclosedByDataEnvironmentExpr |=
22133 (!CurrentRegionOnly && CI != CE && SI == SE);
22134
22135 return false;
22136 });
22137
22138 if (CurrentRegionOnly)
22139 return FoundError;
22140
22141 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
22142 // If any part of the original storage of a list item has corresponding
22143 // storage in the device data environment, all of the original storage must
22144 // have corresponding storage in the device data environment.
22145 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
22146 // If a list item is an element of a structure, and a different element of
22147 // the structure has a corresponding list item in the device data environment
22148 // prior to a task encountering the construct associated with the map clause,
22149 // then the list item must also have a corresponding list item in the device
22150 // data environment prior to the task encountering the construct.
22151 //
22152 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
22153 SemaRef.Diag(ELoc,
22154 diag::err_omp_original_storage_is_shared_and_does_not_contain)
22155 << ERange;
22156 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
22157 << EnclosingExpr->getSourceRange();
22158 return true;
22159 }
22160
22161 return FoundError;
22162}
22163
22164// Look up the user-defined mapper given the mapper name and mapped type, and
22165// build a reference to it.
22167 CXXScopeSpec &MapperIdScopeSpec,
22168 const DeclarationNameInfo &MapperId,
22169 QualType Type,
22170 Expr *UnresolvedMapper) {
22171 if (MapperIdScopeSpec.isInvalid())
22172 return ExprError();
22173 // Get the actual type for the array type.
22174 if (Type->isArrayType()) {
22175 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
22177 }
22178 // Find all user-defined mappers with the given MapperId.
22179 SmallVector<UnresolvedSet<8>, 4> Lookups;
22180 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
22181 Lookup.suppressDiagnostics();
22182 if (S) {
22183 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec)) {
22184 NamedDecl *D = Lookup.getRepresentativeDecl();
22185 while (S && !S->isDeclScope(D))
22186 S = S->getParent();
22187 if (S)
22188 S = S->getParent();
22189 Lookups.emplace_back();
22190 Lookups.back().append(Lookup.begin(), Lookup.end());
22191 Lookup.clear();
22192 }
22193 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
22194 // Extract the user-defined mappers with the given MapperId.
22195 Lookups.push_back(UnresolvedSet<8>());
22196 for (NamedDecl *D : ULE->decls()) {
22197 auto *DMD = cast<OMPDeclareMapperDecl>(D);
22198 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
22199 Lookups.back().addDecl(DMD);
22200 }
22201 }
22202 // Defer the lookup for dependent types. The results will be passed through
22203 // UnresolvedMapper on instantiation.
22204 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
22207 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
22208 return !D->isInvalidDecl() &&
22209 (D->getType()->isDependentType() ||
22210 D->getType()->isInstantiationDependentType() ||
22211 D->getType()->containsUnexpandedParameterPack());
22212 })) {
22213 UnresolvedSet<8> URS;
22214 for (const UnresolvedSet<8> &Set : Lookups) {
22215 if (Set.empty())
22216 continue;
22217 URS.append(Set.begin(), Set.end());
22218 }
22220 SemaRef.Context, /*NamingClass=*/nullptr,
22221 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
22222 /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false);
22223 }
22224 SourceLocation Loc = MapperId.getLoc();
22225 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22226 // The type must be of struct, union or class type in C and C++
22228 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
22229 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
22230 return ExprError();
22231 }
22232 // Perform argument dependent lookup.
22233 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
22234 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
22235 // Return the first user-defined mapper with the desired type.
22236 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
22237 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
22238 if (!D->isInvalidDecl() &&
22239 SemaRef.Context.hasSameType(D->getType(), Type))
22240 return D;
22241 return nullptr;
22242 }))
22243 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
22244 // Find the first user-defined mapper with a type derived from the desired
22245 // type.
22246 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
22247 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
22248 if (!D->isInvalidDecl() &&
22249 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
22250 !Type.isMoreQualifiedThan(D->getType()))
22251 return D;
22252 return nullptr;
22253 })) {
22254 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
22255 /*DetectVirtual=*/false);
22256 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
22257 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
22258 VD->getType().getUnqualifiedType()))) {
22259 if (SemaRef.CheckBaseClassAccess(
22260 Loc, VD->getType(), Type, Paths.front(),
22261 /*DiagID=*/0) != Sema::AR_inaccessible) {
22262 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
22263 }
22264 }
22265 }
22266 }
22267 // Report error if a mapper is specified, but cannot be found.
22268 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
22269 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
22270 << Type << MapperId.getName();
22271 return ExprError();
22272 }
22273 return ExprEmpty();
22274}
22275
22276namespace {
22277// Utility struct that gathers all the related lists associated with a mappable
22278// expression.
22279struct MappableVarListInfo {
22280 // The list of expressions.
22281 ArrayRef<Expr *> VarList;
22282 // The list of processed expressions.
22283 SmallVector<Expr *, 16> ProcessedVarList;
22284 // The mappble components for each expression.
22286 // The base declaration of the variable.
22287 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
22288 // The reference to the user-defined mapper associated with every expression.
22289 SmallVector<Expr *, 16> UDMapperList;
22290
22291 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
22292 // We have a list of components and base declarations for each entry in the
22293 // variable list.
22294 VarComponents.reserve(VarList.size());
22295 VarBaseDeclarations.reserve(VarList.size());
22296 }
22297};
22298} // namespace
22299
22300// Check the validity of the provided variable list for the provided clause kind
22301// \a CKind. In the check process the valid expressions, mappable expression
22302// components, variables, and user-defined mappers are extracted and used to
22303// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
22304// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
22305// and \a MapperId are expected to be valid if the clause kind is 'map'.
22307 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
22308 MappableVarListInfo &MVLI, SourceLocation StartLoc,
22309 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
22310 ArrayRef<Expr *> UnresolvedMappers,
22312 ArrayRef<OpenMPMapModifierKind> Modifiers = std::nullopt,
22313 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
22314 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
22315 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
22316 "Unexpected clause kind with mappable expressions!");
22317
22318 // If the identifier of user-defined mapper is not specified, it is "default".
22319 // We do not change the actual name in this clause to distinguish whether a
22320 // mapper is specified explicitly, i.e., it is not explicitly specified when
22321 // MapperId.getName() is empty.
22322 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
22323 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
22324 MapperId.setName(DeclNames.getIdentifier(
22325 &SemaRef.getASTContext().Idents.get("default")));
22326 MapperId.setLoc(StartLoc);
22327 }
22328
22329 // Iterators to find the current unresolved mapper expression.
22330 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
22331 bool UpdateUMIt = false;
22332 Expr *UnresolvedMapper = nullptr;
22333
22334 bool HasHoldModifier =
22335 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
22336
22337 // Keep track of the mappable components and base declarations in this clause.
22338 // Each entry in the list is going to have a list of components associated. We
22339 // record each set of the components so that we can build the clause later on.
22340 // In the end we should have the same amount of declarations and component
22341 // lists.
22342
22343 for (Expr *RE : MVLI.VarList) {
22344 assert(RE && "Null expr in omp to/from/map clause");
22345 SourceLocation ELoc = RE->getExprLoc();
22346
22347 // Find the current unresolved mapper expression.
22348 if (UpdateUMIt && UMIt != UMEnd) {
22349 UMIt++;
22350 assert(
22351 UMIt != UMEnd &&
22352 "Expect the size of UnresolvedMappers to match with that of VarList");
22353 }
22354 UpdateUMIt = true;
22355 if (UMIt != UMEnd)
22356 UnresolvedMapper = *UMIt;
22357
22358 const Expr *VE = RE->IgnoreParenLValueCasts();
22359
22360 if (VE->isValueDependent() || VE->isTypeDependent() ||
22363 // Try to find the associated user-defined mapper.
22365 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22366 VE->getType().getCanonicalType(), UnresolvedMapper);
22367 if (ER.isInvalid())
22368 continue;
22369 MVLI.UDMapperList.push_back(ER.get());
22370 // We can only analyze this information once the missing information is
22371 // resolved.
22372 MVLI.ProcessedVarList.push_back(RE);
22373 continue;
22374 }
22375
22376 Expr *SimpleExpr = RE->IgnoreParenCasts();
22377
22378 if (!RE->isLValue()) {
22379 if (SemaRef.getLangOpts().OpenMP < 50) {
22380 SemaRef.Diag(
22381 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
22382 << RE->getSourceRange();
22383 } else {
22384 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22385 << getOpenMPClauseName(CKind) << RE->getSourceRange();
22386 }
22387 continue;
22388 }
22389
22391 ValueDecl *CurDeclaration = nullptr;
22392
22393 // Obtain the array or member expression bases if required. Also, fill the
22394 // components array with all the components identified in the process.
22395 const Expr *BE =
22396 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
22397 DSAS->getCurrentDirective(), NoDiagnose);
22398 if (!BE)
22399 continue;
22400
22401 assert(!CurComponents.empty() &&
22402 "Invalid mappable expression information.");
22403
22404 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
22405 // Add store "this" pointer to class in DSAStackTy for future checking
22406 DSAS->addMappedClassesQualTypes(TE->getType());
22407 // Try to find the associated user-defined mapper.
22409 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22410 VE->getType().getCanonicalType(), UnresolvedMapper);
22411 if (ER.isInvalid())
22412 continue;
22413 MVLI.UDMapperList.push_back(ER.get());
22414 // Skip restriction checking for variable or field declarations
22415 MVLI.ProcessedVarList.push_back(RE);
22416 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22417 MVLI.VarComponents.back().append(CurComponents.begin(),
22418 CurComponents.end());
22419 MVLI.VarBaseDeclarations.push_back(nullptr);
22420 continue;
22421 }
22422
22423 // For the following checks, we rely on the base declaration which is
22424 // expected to be associated with the last component. The declaration is
22425 // expected to be a variable or a field (if 'this' is being mapped).
22426 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
22427 assert(CurDeclaration && "Null decl on map clause.");
22428 assert(
22429 CurDeclaration->isCanonicalDecl() &&
22430 "Expecting components to have associated only canonical declarations.");
22431
22432 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
22433 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
22434
22435 assert((VD || FD) && "Only variables or fields are expected here!");
22436 (void)FD;
22437
22438 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
22439 // threadprivate variables cannot appear in a map clause.
22440 // OpenMP 4.5 [2.10.5, target update Construct]
22441 // threadprivate variables cannot appear in a from clause.
22442 if (VD && DSAS->isThreadPrivate(VD)) {
22443 if (NoDiagnose)
22444 continue;
22445 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
22446 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
22447 << getOpenMPClauseName(CKind);
22448 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
22449 continue;
22450 }
22451
22452 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22453 // A list item cannot appear in both a map clause and a data-sharing
22454 // attribute clause on the same construct.
22455
22456 // Check conflicts with other map clause expressions. We check the conflicts
22457 // with the current construct separately from the enclosing data
22458 // environment, because the restrictions are different. We only have to
22459 // check conflicts across regions for the map clauses.
22460 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
22461 /*CurrentRegionOnly=*/true, CurComponents, CKind))
22462 break;
22463 if (CKind == OMPC_map &&
22464 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
22465 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
22466 /*CurrentRegionOnly=*/false, CurComponents, CKind))
22467 break;
22468
22469 // OpenMP 4.5 [2.10.5, target update Construct]
22470 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22471 // If the type of a list item is a reference to a type T then the type will
22472 // be considered to be T for all purposes of this clause.
22473 auto I = llvm::find_if(
22474 CurComponents,
22476 return MC.getAssociatedDeclaration();
22477 });
22478 assert(I != CurComponents.end() && "Null decl on map clause.");
22479 (void)I;
22480 QualType Type;
22481 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
22482 auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens());
22483 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
22484 if (ASE) {
22485 Type = ASE->getType().getNonReferenceType();
22486 } else if (OASE) {
22487 QualType BaseType =
22489 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
22490 Type = ATy->getElementType();
22491 else
22492 Type = BaseType->getPointeeType();
22493 Type = Type.getNonReferenceType();
22494 } else if (OAShE) {
22495 Type = OAShE->getBase()->getType()->getPointeeType();
22496 } else {
22497 Type = VE->getType();
22498 }
22499
22500 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
22501 // A list item in a to or from clause must have a mappable type.
22502 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22503 // A list item must have a mappable type.
22504 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
22505 DSAS, Type, /*FullCheck=*/true))
22506 continue;
22507
22508 if (CKind == OMPC_map) {
22509 // target enter data
22510 // OpenMP [2.10.2, Restrictions, p. 99]
22511 // A map-type must be specified in all map clauses and must be either
22512 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
22513 // no map type is present.
22514 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
22515 if (DKind == OMPD_target_enter_data &&
22516 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
22517 SemaRef.getLangOpts().OpenMP >= 52)) {
22518 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22519 << (IsMapTypeImplicit ? 1 : 0)
22520 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22521 << getOpenMPDirectiveName(DKind);
22522 continue;
22523 }
22524
22525 // target exit_data
22526 // OpenMP [2.10.3, Restrictions, p. 102]
22527 // A map-type must be specified in all map clauses and must be either
22528 // from, release, or delete. Starting with OpenMP 5.2 the default map
22529 // type is `from` if no map type is present.
22530 if (DKind == OMPD_target_exit_data &&
22531 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
22532 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
22533 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22534 << (IsMapTypeImplicit ? 1 : 0)
22535 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22536 << getOpenMPDirectiveName(DKind);
22537 continue;
22538 }
22539
22540 // The 'ompx_hold' modifier is specifically intended to be used on a
22541 // 'target' or 'target data' directive to prevent data from being unmapped
22542 // during the associated statement. It is not permitted on a 'target
22543 // enter data' or 'target exit data' directive, which have no associated
22544 // statement.
22545 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
22546 HasHoldModifier) {
22547 SemaRef.Diag(StartLoc,
22548 diag::err_omp_invalid_map_type_modifier_for_directive)
22550 OMPC_MAP_MODIFIER_ompx_hold)
22551 << getOpenMPDirectiveName(DKind);
22552 continue;
22553 }
22554
22555 // target, target data
22556 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
22557 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
22558 // A map-type in a map clause must be to, from, tofrom or alloc
22559 if ((DKind == OMPD_target_data ||
22561 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
22562 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
22563 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22564 << (IsMapTypeImplicit ? 1 : 0)
22565 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22566 << getOpenMPDirectiveName(DKind);
22567 continue;
22568 }
22569
22570 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
22571 // A list item cannot appear in both a map clause and a data-sharing
22572 // attribute clause on the same construct
22573 //
22574 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
22575 // A list item cannot appear in both a map clause and a data-sharing
22576 // attribute clause on the same construct unless the construct is a
22577 // combined construct.
22578 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
22580 DKind == OMPD_target)) {
22581 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
22582 if (isOpenMPPrivate(DVar.CKind)) {
22583 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22584 << getOpenMPClauseName(DVar.CKind)
22585 << getOpenMPClauseName(OMPC_map)
22586 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
22587 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
22588 continue;
22589 }
22590 }
22591 }
22592
22593 // Try to find the associated user-defined mapper.
22595 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22596 Type.getCanonicalType(), UnresolvedMapper);
22597 if (ER.isInvalid())
22598 continue;
22599 MVLI.UDMapperList.push_back(ER.get());
22600
22601 // Save the current expression.
22602 MVLI.ProcessedVarList.push_back(RE);
22603
22604 // Store the components in the stack so that they can be used to check
22605 // against other clauses later on.
22606 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
22607 /*WhereFoundClauseKind=*/OMPC_map);
22608
22609 // Save the components and declaration to create the clause. For purposes of
22610 // the clause creation, any component list that has base 'this' uses
22611 // null as base declaration.
22612 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22613 MVLI.VarComponents.back().append(CurComponents.begin(),
22614 CurComponents.end());
22615 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
22616 : CurDeclaration);
22617 }
22618}
22619
22621 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
22622 ArrayRef<SourceLocation> MapTypeModifiersLoc,
22623 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22624 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
22625 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22626 const OMPVarListLocTy &Locs, bool NoDiagnose,
22627 ArrayRef<Expr *> UnresolvedMappers) {
22628 OpenMPMapModifierKind Modifiers[] = {
22633
22634 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
22635 BuiltinType::OMPIterator))
22636 Diag(IteratorModifier->getExprLoc(),
22637 diag::err_omp_map_modifier_not_iterator);
22638
22639 // Process map-type-modifiers, flag errors for duplicate modifiers.
22640 unsigned Count = 0;
22641 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
22642 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
22643 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
22644 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
22645 continue;
22646 }
22647 assert(Count < NumberOfOMPMapClauseModifiers &&
22648 "Modifiers exceed the allowed number of map type modifiers");
22649 Modifiers[Count] = MapTypeModifiers[I];
22650 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
22651 ++Count;
22652 }
22653
22654 MappableVarListInfo MVLI(VarList);
22656 MapperIdScopeSpec, MapperId, UnresolvedMappers,
22657 MapType, Modifiers, IsMapTypeImplicit,
22658 NoDiagnose);
22659
22660 // We need to produce a map clause even if we don't have variables so that
22661 // other diagnostics related with non-existing map clauses are accurate.
22662 return OMPMapClause::Create(
22663 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22664 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
22665 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
22666 MapperId, MapType, IsMapTypeImplicit, MapLoc);
22667}
22668
22671 assert(ParsedType.isUsable());
22672
22673 QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get());
22674 if (ReductionType.isNull())
22675 return QualType();
22676
22677 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
22678 // A type name in a declare reduction directive cannot be a function type, an
22679 // array type, a reference type, or a type qualified with const, volatile or
22680 // restrict.
22681 if (ReductionType.hasQualifiers()) {
22682 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
22683 return QualType();
22684 }
22685
22686 if (ReductionType->isFunctionType()) {
22687 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
22688 return QualType();
22689 }
22690 if (ReductionType->isReferenceType()) {
22691 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
22692 return QualType();
22693 }
22694 if (ReductionType->isArrayType()) {
22695 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
22696 return QualType();
22697 }
22698 return ReductionType;
22699}
22700
22703 Scope *S, DeclContext *DC, DeclarationName Name,
22704 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
22705 AccessSpecifier AS, Decl *PrevDeclInScope) {
22707 Decls.reserve(ReductionTypes.size());
22708
22709 LookupResult Lookup(SemaRef, Name, SourceLocation(),
22712 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
22713 // A reduction-identifier may not be re-declared in the current scope for the
22714 // same type or for a type that is compatible according to the base language
22715 // rules.
22716 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22717 OMPDeclareReductionDecl *PrevDRD = nullptr;
22718 bool InCompoundScope = true;
22719 if (S != nullptr) {
22720 // Find previous declaration with the same name not referenced in other
22721 // declarations.
22723 InCompoundScope =
22724 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22725 SemaRef.LookupName(Lookup, S);
22726 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22727 /*AllowInlineNamespace=*/false);
22728 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
22729 LookupResult::Filter Filter = Lookup.makeFilter();
22730 while (Filter.hasNext()) {
22731 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
22732 if (InCompoundScope) {
22733 auto I = UsedAsPrevious.find(PrevDecl);
22734 if (I == UsedAsPrevious.end())
22735 UsedAsPrevious[PrevDecl] = false;
22736 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
22737 UsedAsPrevious[D] = true;
22738 }
22739 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22740 PrevDecl->getLocation();
22741 }
22742 Filter.done();
22743 if (InCompoundScope) {
22744 for (const auto &PrevData : UsedAsPrevious) {
22745 if (!PrevData.second) {
22746 PrevDRD = PrevData.first;
22747 break;
22748 }
22749 }
22750 }
22751 } else if (PrevDeclInScope != nullptr) {
22752 auto *PrevDRDInScope = PrevDRD =
22753 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
22754 do {
22755 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
22756 PrevDRDInScope->getLocation();
22757 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
22758 } while (PrevDRDInScope != nullptr);
22759 }
22760 for (const auto &TyData : ReductionTypes) {
22761 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
22762 bool Invalid = false;
22763 if (I != PreviousRedeclTypes.end()) {
22764 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
22765 << TyData.first;
22766 Diag(I->second, diag::note_previous_definition);
22767 Invalid = true;
22768 }
22769 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
22771 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
22772 DC->addDecl(DRD);
22773 DRD->setAccess(AS);
22774 Decls.push_back(DRD);
22775 if (Invalid)
22776 DRD->setInvalidDecl();
22777 else
22778 PrevDRD = DRD;
22779 }
22780
22781 return DeclGroupPtrTy::make(
22782 DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size()));
22783}
22784
22786 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22787
22788 // Enter new function scope.
22792
22793 if (S != nullptr)
22794 SemaRef.PushDeclContext(S, DRD);
22795 else
22796 SemaRef.CurContext = DRD;
22797
22800
22801 QualType ReductionType = DRD->getType();
22802 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
22803 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
22804 // uses semantics of argument handles by value, but it should be passed by
22805 // reference. C lang does not support references, so pass all parameters as
22806 // pointers.
22807 // Create 'T omp_in;' variable.
22808 VarDecl *OmpInParm =
22809 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in");
22810 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
22811 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
22812 // uses semantics of argument handles by value, but it should be passed by
22813 // reference. C lang does not support references, so pass all parameters as
22814 // pointers.
22815 // Create 'T omp_out;' variable.
22816 VarDecl *OmpOutParm =
22817 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out");
22818 if (S != nullptr) {
22819 SemaRef.PushOnScopeChains(OmpInParm, S);
22820 SemaRef.PushOnScopeChains(OmpOutParm, S);
22821 } else {
22822 DRD->addDecl(OmpInParm);
22823 DRD->addDecl(OmpOutParm);
22824 }
22825 Expr *InE =
22826 ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation());
22827 Expr *OutE =
22828 ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation());
22829 DRD->setCombinerData(InE, OutE);
22830}
22831
22833 Expr *Combiner) {
22834 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22837
22840
22841 if (Combiner != nullptr)
22842 DRD->setCombiner(Combiner);
22843 else
22844 DRD->setInvalidDecl();
22845}
22846
22848 Decl *D) {
22849 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22850
22851 // Enter new function scope.
22854
22855 if (S != nullptr)
22856 SemaRef.PushDeclContext(S, DRD);
22857 else
22858 SemaRef.CurContext = DRD;
22859
22862
22863 QualType ReductionType = DRD->getType();
22864 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
22865 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
22866 // uses semantics of argument handles by value, but it should be passed by
22867 // reference. C lang does not support references, so pass all parameters as
22868 // pointers.
22869 // Create 'T omp_priv;' variable.
22870 VarDecl *OmpPrivParm =
22871 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv");
22872 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
22873 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
22874 // uses semantics of argument handles by value, but it should be passed by
22875 // reference. C lang does not support references, so pass all parameters as
22876 // pointers.
22877 // Create 'T omp_orig;' variable.
22878 VarDecl *OmpOrigParm =
22879 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig");
22880 if (S != nullptr) {
22881 SemaRef.PushOnScopeChains(OmpPrivParm, S);
22882 SemaRef.PushOnScopeChains(OmpOrigParm, S);
22883 } else {
22884 DRD->addDecl(OmpPrivParm);
22885 DRD->addDecl(OmpOrigParm);
22886 }
22887 Expr *OrigE =
22888 ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation());
22889 Expr *PrivE =
22890 ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation());
22891 DRD->setInitializerData(OrigE, PrivE);
22892 return OmpPrivParm;
22893}
22894
22896 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
22897 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22900
22903
22904 if (Initializer != nullptr) {
22905 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
22906 } else if (OmpPrivParm->hasInit()) {
22907 DRD->setInitializer(OmpPrivParm->getInit(),
22908 OmpPrivParm->isDirectInit()
22911 } else {
22912 DRD->setInvalidDecl();
22913 }
22914}
22915
22917 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
22918 for (Decl *D : DeclReductions.get()) {
22919 if (IsValid) {
22920 if (S)
22921 SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
22922 /*AddToContext=*/false);
22923 } else {
22924 D->setInvalidDecl();
22925 }
22926 }
22927 return DeclReductions;
22928}
22929
22931 Declarator &D) {
22933 QualType T = TInfo->getType();
22934 if (D.isInvalidType())
22935 return true;
22936
22937 if (getLangOpts().CPlusPlus) {
22938 // Check that there are no default arguments (C++ only).
22940 }
22941
22942 return SemaRef.CreateParsedType(T, TInfo);
22943}
22944
22947 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
22948
22950 assert(!MapperType.isNull() && "Expect valid mapper type");
22951
22952 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22953 // The type must be of struct, union or class type in C and C++
22954 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
22955 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
22956 return QualType();
22957 }
22958 return MapperType;
22959}
22960
22962 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
22964 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
22965 LookupResult Lookup(SemaRef, Name, SourceLocation(),
22968 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22969 // A mapper-identifier may not be redeclared in the current scope for the
22970 // same type or for a type that is compatible according to the base language
22971 // rules.
22972 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22973 OMPDeclareMapperDecl *PrevDMD = nullptr;
22974 bool InCompoundScope = true;
22975 if (S != nullptr) {
22976 // Find previous declaration with the same name not referenced in other
22977 // declarations.
22979 InCompoundScope =
22980 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22981 SemaRef.LookupName(Lookup, S);
22982 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22983 /*AllowInlineNamespace=*/false);
22984 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
22985 LookupResult::Filter Filter = Lookup.makeFilter();
22986 while (Filter.hasNext()) {
22987 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
22988 if (InCompoundScope) {
22989 auto I = UsedAsPrevious.find(PrevDecl);
22990 if (I == UsedAsPrevious.end())
22991 UsedAsPrevious[PrevDecl] = false;
22992 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
22993 UsedAsPrevious[D] = true;
22994 }
22995 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22996 PrevDecl->getLocation();
22997 }
22998 Filter.done();
22999 if (InCompoundScope) {
23000 for (const auto &PrevData : UsedAsPrevious) {
23001 if (!PrevData.second) {
23002 PrevDMD = PrevData.first;
23003 break;
23004 }
23005 }
23006 }
23007 } else if (PrevDeclInScope) {
23008 auto *PrevDMDInScope = PrevDMD =
23009 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
23010 do {
23011 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
23012 PrevDMDInScope->getLocation();
23013 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
23014 } while (PrevDMDInScope != nullptr);
23015 }
23016 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
23017 bool Invalid = false;
23018 if (I != PreviousRedeclTypes.end()) {
23019 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
23020 << MapperType << Name;
23021 Diag(I->second, diag::note_previous_definition);
23022 Invalid = true;
23023 }
23024 // Build expressions for implicit maps of data members with 'default'
23025 // mappers.
23026 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses.begin(),
23027 Clauses.end());
23028 if (getLangOpts().OpenMP >= 50)
23030 ClausesWithImplicit);
23031 auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name,
23032 MapperType, VN, ClausesWithImplicit,
23033 PrevDMD);
23034 if (S)
23035 SemaRef.PushOnScopeChains(DMD, S);
23036 else
23037 DC->addDecl(DMD);
23038 DMD->setAccess(AS);
23039 if (Invalid)
23040 DMD->setInvalidDecl();
23041
23042 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
23043 VD->setDeclContext(DMD);
23044 VD->setLexicalDeclContext(DMD);
23045 DMD->addDecl(VD);
23046 DMD->setMapperVarRef(MapperVarRef);
23047
23049}
23050
23052 Scope *S, QualType MapperType, SourceLocation StartLoc,
23053 DeclarationName VN) {
23054 TypeSourceInfo *TInfo =
23055 getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc);
23056 auto *VD = VarDecl::Create(
23057 getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc,
23058 StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None);
23059 if (S)
23060 SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false);
23061 Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc);
23062 DSAStack->addDeclareMapperVarRef(E);
23063 return E;
23064}
23065
23067 if (DSAStack->getDeclareMapperVarRef())
23068 DSAStack->addIteratorVarDecl(VD);
23069}
23070
23072 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
23073 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
23074 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
23075 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
23076 return true;
23078 return true;
23079 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
23080 return true;
23081 return false;
23082 }
23083 return true;
23084}
23085
23087 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
23088 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
23089}
23090
23092 SourceLocation StartLoc,
23093 SourceLocation LParenLoc,
23094 SourceLocation EndLoc) {
23095 Expr *ValExpr = NumTeams;
23096 Stmt *HelperValStmt = nullptr;
23097
23098 // OpenMP [teams Constrcut, Restrictions]
23099 // The num_teams expression must evaluate to a positive integer value.
23100 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams,
23101 /*StrictlyPositive=*/true))
23102 return nullptr;
23103
23104 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23106 DKind, OMPC_num_teams, getLangOpts().OpenMP);
23107 if (CaptureRegion != OMPD_unknown &&
23109 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23110 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23111 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23112 HelperValStmt = buildPreInits(getASTContext(), Captures);
23113 }
23114
23115 return new (getASTContext()) OMPNumTeamsClause(
23116 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23117}
23118
23120 SourceLocation StartLoc,
23121 SourceLocation LParenLoc,
23122 SourceLocation EndLoc) {
23123 Expr *ValExpr = ThreadLimit;
23124 Stmt *HelperValStmt = nullptr;
23125
23126 // OpenMP [teams Constrcut, Restrictions]
23127 // The thread_limit expression must evaluate to a positive integer value.
23128 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit,
23129 /*StrictlyPositive=*/true))
23130 return nullptr;
23131
23132 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23134 DKind, OMPC_thread_limit, getLangOpts().OpenMP);
23135 if (CaptureRegion != OMPD_unknown &&
23137 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23138 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23139 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23140 HelperValStmt = buildPreInits(getASTContext(), Captures);
23141 }
23142
23143 return new (getASTContext()) OMPThreadLimitClause(
23144 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23145}
23146
23148 SourceLocation StartLoc,
23149 SourceLocation LParenLoc,
23150 SourceLocation EndLoc) {
23151 Expr *ValExpr = Priority;
23152 Stmt *HelperValStmt = nullptr;
23153 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23154
23155 // OpenMP [2.9.1, task Constrcut]
23156 // The priority-value is a non-negative numerical scalar expression.
23158 ValExpr, SemaRef, OMPC_priority,
23159 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
23160 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23161 return nullptr;
23162
23163 return new (getASTContext()) OMPPriorityClause(
23164 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23165}
23166
23168 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
23169 SourceLocation StartLoc, SourceLocation LParenLoc,
23170 SourceLocation ModifierLoc, SourceLocation EndLoc) {
23171 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
23172 "Unexpected grainsize modifier in OpenMP < 51.");
23173
23174 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
23175 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
23177 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23178 << Values << getOpenMPClauseName(OMPC_grainsize);
23179 return nullptr;
23180 }
23181
23182 Expr *ValExpr = Grainsize;
23183 Stmt *HelperValStmt = nullptr;
23184 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23185
23186 // OpenMP [2.9.2, taskloop Constrcut]
23187 // The parameter of the grainsize clause must be a positive integer
23188 // expression.
23189 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize,
23190 /*StrictlyPositive=*/true,
23191 /*BuildCapture=*/true,
23192 DSAStack->getCurrentDirective(),
23193 &CaptureRegion, &HelperValStmt))
23194 return nullptr;
23195
23196 return new (getASTContext())
23197 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
23198 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23199}
23200
23202 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
23203 SourceLocation StartLoc, SourceLocation LParenLoc,
23204 SourceLocation ModifierLoc, SourceLocation EndLoc) {
23205 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
23206 "Unexpected num_tasks modifier in OpenMP < 51.");
23207
23208 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
23209 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
23211 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23212 << Values << getOpenMPClauseName(OMPC_num_tasks);
23213 return nullptr;
23214 }
23215
23216 Expr *ValExpr = NumTasks;
23217 Stmt *HelperValStmt = nullptr;
23218 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23219
23220 // OpenMP [2.9.2, taskloop Constrcut]
23221 // The parameter of the num_tasks clause must be a positive integer
23222 // expression.
23224 ValExpr, SemaRef, OMPC_num_tasks,
23225 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
23226 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23227 return nullptr;
23228
23229 return new (getASTContext())
23230 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
23231 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23232}
23233
23235 SourceLocation StartLoc,
23236 SourceLocation LParenLoc,
23237 SourceLocation EndLoc) {
23238 // OpenMP [2.13.2, critical construct, Description]
23239 // ... where hint-expression is an integer constant expression that evaluates
23240 // to a valid lock hint.
23241 ExprResult HintExpr =
23242 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
23243 if (HintExpr.isInvalid())
23244 return nullptr;
23245 return new (getASTContext())
23246 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
23247}
23248
23249/// Tries to find omp_event_handle_t type.
23251 DSAStackTy *Stack) {
23252 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
23253 if (!OMPEventHandleT.isNull())
23254 return true;
23255 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
23256 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
23257 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23258 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
23259 return false;
23260 }
23261 Stack->setOMPEventHandleT(PT.get());
23262 return true;
23263}
23264
23266 SourceLocation StartLoc,
23267 SourceLocation LParenLoc,
23268 SourceLocation EndLoc) {
23269 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
23270 !Evt->isInstantiationDependent() &&
23273 return nullptr;
23274 // OpenMP 5.0, 2.10.1 task Construct.
23275 // event-handle is a variable of the omp_event_handle_t type.
23276 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
23277 if (!Ref) {
23278 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23279 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
23280 return nullptr;
23281 }
23282 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
23283 if (!VD) {
23284 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23285 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
23286 return nullptr;
23287 }
23288 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
23289 VD->getType()) ||
23290 VD->getType().isConstant(getASTContext())) {
23291 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23292 << "omp_event_handle_t" << 1 << VD->getType()
23293 << Evt->getSourceRange();
23294 return nullptr;
23295 }
23296 // OpenMP 5.0, 2.10.1 task Construct
23297 // [detach clause]... The event-handle will be considered as if it was
23298 // specified on a firstprivate clause.
23299 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
23300 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
23301 DVar.RefExpr) {
23302 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
23303 << getOpenMPClauseName(DVar.CKind)
23304 << getOpenMPClauseName(OMPC_firstprivate);
23306 return nullptr;
23307 }
23308 }
23309
23310 return new (getASTContext())
23311 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
23312}
23313
23315 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
23316 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
23317 SourceLocation EndLoc) {
23318 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
23319 std::string Values;
23320 Values += "'";
23321 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
23322 Values += "'";
23323 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23324 << Values << getOpenMPClauseName(OMPC_dist_schedule);
23325 return nullptr;
23326 }
23327 Expr *ValExpr = ChunkSize;
23328 Stmt *HelperValStmt = nullptr;
23329 if (ChunkSize) {
23330 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
23331 !ChunkSize->isInstantiationDependent() &&
23332 !ChunkSize->containsUnexpandedParameterPack()) {
23333 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
23334 ExprResult Val =
23335 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
23336 if (Val.isInvalid())
23337 return nullptr;
23338
23339 ValExpr = Val.get();
23340
23341 // OpenMP [2.7.1, Restrictions]
23342 // chunk_size must be a loop invariant integer expression with a positive
23343 // value.
23344 if (std::optional<llvm::APSInt> Result =
23346 if (Result->isSigned() && !Result->isStrictlyPositive()) {
23347 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
23348 << "dist_schedule" << ChunkSize->getSourceRange();
23349 return nullptr;
23350 }
23352 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
23353 getLangOpts().OpenMP) != OMPD_unknown &&
23355 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23356 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23357 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23358 HelperValStmt = buildPreInits(getASTContext(), Captures);
23359 }
23360 }
23361 }
23362
23363 return new (getASTContext())
23364 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
23365 Kind, ValExpr, HelperValStmt);
23366}
23367
23370 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
23371 SourceLocation KindLoc, SourceLocation EndLoc) {
23372 if (getLangOpts().OpenMP < 50) {
23373 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
23374 Kind != OMPC_DEFAULTMAP_scalar) {
23375 std::string Value;
23376 SourceLocation Loc;
23377 Value += "'";
23378 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
23379 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
23380 OMPC_DEFAULTMAP_MODIFIER_tofrom);
23381 Loc = MLoc;
23382 } else {
23383 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
23384 OMPC_DEFAULTMAP_scalar);
23385 Loc = KindLoc;
23386 }
23387 Value += "'";
23388 Diag(Loc, diag::err_omp_unexpected_clause_value)
23389 << Value << getOpenMPClauseName(OMPC_defaultmap);
23390 return nullptr;
23391 }
23392 } else {
23393 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
23394 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
23395 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
23396 if (!isDefaultmapKind || !isDefaultmapModifier) {
23397 StringRef KindValue = "'scalar', 'aggregate', 'pointer'";
23398 if (getLangOpts().OpenMP == 50) {
23399 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
23400 "'firstprivate', 'none', 'default'";
23401 if (!isDefaultmapKind && isDefaultmapModifier) {
23402 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23403 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23404 } else if (isDefaultmapKind && !isDefaultmapModifier) {
23405 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23406 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23407 } else {
23408 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23409 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23410 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23411 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23412 }
23413 } else {
23414 StringRef ModifierValue =
23415 "'alloc', 'from', 'to', 'tofrom', "
23416 "'firstprivate', 'none', 'default', 'present'";
23417 if (!isDefaultmapKind && isDefaultmapModifier) {
23418 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23419 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23420 } else if (isDefaultmapKind && !isDefaultmapModifier) {
23421 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23422 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23423 } else {
23424 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23425 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23426 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23427 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23428 }
23429 }
23430 return nullptr;
23431 }
23432
23433 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
23434 // At most one defaultmap clause for each category can appear on the
23435 // directive.
23436 if (DSAStack->checkDefaultmapCategory(Kind)) {
23437 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
23438 return nullptr;
23439 }
23440 }
23441 if (Kind == OMPC_DEFAULTMAP_unknown) {
23442 // Variable category is not specified - mark all categories.
23443 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
23444 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
23445 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
23446 } else {
23447 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
23448 }
23449
23450 return new (getASTContext())
23451 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
23452}
23453
23456 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
23457 if (!CurLexicalContext->isFileContext() &&
23458 !CurLexicalContext->isExternCContext() &&
23459 !CurLexicalContext->isExternCXXContext() &&
23460 !isa<CXXRecordDecl>(CurLexicalContext) &&
23461 !isa<ClassTemplateDecl>(CurLexicalContext) &&
23462 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
23463 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
23464 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
23465 return false;
23466 }
23467
23468 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23469 if (getLangOpts().HIP)
23470 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
23471
23472 DeclareTargetNesting.push_back(DTCI);
23473 return true;
23474}
23475
23478 assert(!DeclareTargetNesting.empty() &&
23479 "check isInOpenMPDeclareTargetContext() first!");
23480 return DeclareTargetNesting.pop_back_val();
23481}
23482
23485 for (auto &It : DTCI.ExplicitlyMapped)
23486 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
23487}
23488
23490 if (DeclareTargetNesting.empty())
23491 return;
23492 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23493 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
23494 << getOpenMPDirectiveName(DTCI.Kind);
23495}
23496
23498 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
23500 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
23501
23502 if (Lookup.isAmbiguous())
23503 return nullptr;
23504 Lookup.suppressDiagnostics();
23505
23506 if (!Lookup.isSingleResult()) {
23507 VarOrFuncDeclFilterCCC CCC(SemaRef);
23508 if (TypoCorrection Corrected =
23509 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
23511 SemaRef.diagnoseTypo(Corrected,
23512 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
23513 << Id.getName());
23514 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
23515 return nullptr;
23516 }
23517
23518 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
23519 return nullptr;
23520 }
23521
23522 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
23523 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
23524 !isa<FunctionTemplateDecl>(ND)) {
23525 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
23526 return nullptr;
23527 }
23528 return ND;
23529}
23530
23532 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
23534 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
23535 isa<FunctionTemplateDecl>(ND)) &&
23536 "Expected variable, function or function template.");
23537
23538 if (auto *VD = dyn_cast<VarDecl>(ND)) {
23539 // Only global variables can be marked as declare target.
23540 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23541 !VD->isStaticDataMember()) {
23542 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
23543 << VD->getNameAsString();
23544 return;
23545 }
23546 }
23547 // Diagnose marking after use as it may lead to incorrect diagnosis and
23548 // codegen.
23549 if (getLangOpts().OpenMP >= 50 &&
23550 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
23551 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
23552
23553 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23554 if (getLangOpts().HIP)
23555 Diag(Loc, diag::warn_hip_omp_target_directives);
23556
23557 // Explicit declare target lists have precedence.
23558 const unsigned Level = -1;
23559
23560 auto *VD = cast<ValueDecl>(ND);
23561 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23562 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23563 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
23564 (*ActiveAttr)->getLevel() == Level) {
23565 Diag(Loc, diag::err_omp_device_type_mismatch)
23566 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
23567 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
23568 (*ActiveAttr)->getDevType());
23569 return;
23570 }
23571 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
23572 (*ActiveAttr)->getLevel() == Level) {
23573 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
23574 return;
23575 }
23576
23577 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
23578 return;
23579
23580 Expr *IndirectE = nullptr;
23581 bool IsIndirect = false;
23582 if (DTCI.Indirect) {
23583 IndirectE = *DTCI.Indirect;
23584 if (!IndirectE)
23585 IsIndirect = true;
23586 }
23587 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23588 getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level,
23589 SourceRange(Loc, Loc));
23590 ND->addAttr(A);
23591 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
23592 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
23593 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
23594 if (auto *VD = dyn_cast<VarDecl>(ND);
23595 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
23596 VD->hasGlobalStorage())
23598}
23599
23601 Sema &SemaRef, Decl *D) {
23602 if (!D || !isa<VarDecl>(D))
23603 return;
23604 auto *VD = cast<VarDecl>(D);
23605 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
23606 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
23607 if (SemaRef.LangOpts.OpenMP >= 50 &&
23608 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
23609 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
23610 VD->hasGlobalStorage()) {
23611 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
23612 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
23613 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
23614 // If a lambda declaration and definition appears between a
23615 // declare target directive and the matching end declare target
23616 // directive, all variables that are captured by the lambda
23617 // expression must also appear in a to clause.
23618 SemaRef.Diag(VD->getLocation(),
23619 diag::err_omp_lambda_capture_in_declare_target_not_to);
23620 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
23621 << VD << 0 << SR;
23622 return;
23623 }
23624 }
23625 if (MapTy)
23626 return;
23627 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
23628 SemaRef.Diag(SL, diag::note_used_here) << SR;
23629}
23630
23632 Sema &SemaRef, DSAStackTy *Stack,
23633 ValueDecl *VD) {
23634 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
23635 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
23636 /*FullCheck=*/false);
23637}
23638
23640 SourceLocation IdLoc) {
23641 if (!D || D->isInvalidDecl())
23642 return;
23643 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
23644 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
23645 if (auto *VD = dyn_cast<VarDecl>(D)) {
23646 // Only global variables can be marked as declare target.
23647 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23648 !VD->isStaticDataMember())
23649 return;
23650 // 2.10.6: threadprivate variable cannot appear in a declare target
23651 // directive.
23652 if (DSAStack->isThreadPrivate(VD)) {
23653 Diag(SL, diag::err_omp_threadprivate_in_target);
23654 reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false));
23655 return;
23656 }
23657 }
23658 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
23659 D = FTD->getTemplatedDecl();
23660 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
23661 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
23662 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
23663 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
23664 Diag(IdLoc, diag::err_omp_function_in_link_clause);
23665 Diag(FD->getLocation(), diag::note_defined_here) << FD;
23666 return;
23667 }
23668 }
23669 if (auto *VD = dyn_cast<ValueDecl>(D)) {
23670 // Problem if any with var declared with incomplete type will be reported
23671 // as normal, so no need to check it here.
23672 if ((E || !VD->getType()->isIncompleteType()) &&
23674 return;
23675 if (!E && isInOpenMPDeclareTargetContext()) {
23676 // Checking declaration inside declare target region.
23677 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
23678 isa<FunctionTemplateDecl>(D)) {
23679 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23680 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23681 unsigned Level = DeclareTargetNesting.size();
23682 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
23683 return;
23684 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23685 Expr *IndirectE = nullptr;
23686 bool IsIndirect = false;
23687 if (DTCI.Indirect) {
23688 IndirectE = *DTCI.Indirect;
23689 if (!IndirectE)
23690 IsIndirect = true;
23691 }
23692 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23693 getASTContext(),
23694 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
23695 : OMPDeclareTargetDeclAttr::MT_To,
23696 DTCI.DT, IndirectE, IsIndirect, Level,
23697 SourceRange(DTCI.Loc, DTCI.Loc));
23698 D->addAttr(A);
23699 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
23700 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
23701 }
23702 return;
23703 }
23704 }
23705 if (!E)
23706 return;
23708}
23709
23710/// This class visits every VarDecl that the initializer references and adds
23711/// OMPDeclareTargetDeclAttr to each of them.
23713 : public StmtVisitor<GlobalDeclRefChecker> {
23714 SmallVector<VarDecl *> DeclVector;
23715 Attr *A;
23716
23717public:
23718 /// A StmtVisitor class function that visits all DeclRefExpr and adds
23719 /// OMPDeclareTargetDeclAttr to them.
23721 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
23722 VD->addAttr(A);
23723 DeclVector.push_back(VD);
23724 }
23725 }
23726 /// A function that iterates across each of the Expr's children.
23727 void VisitExpr(Expr *Ex) {
23728 for (auto *Child : Ex->children()) {
23729 Visit(Child);
23730 }
23731 }
23732 /// A function that keeps a record of all the Decls that are variables, has
23733 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
23734 /// each Decl one at a time and use the inherited 'visit' functions to look
23735 /// for DeclRefExpr.
23737 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
23738 DeclVector.push_back(cast<VarDecl>(TD));
23739 while (!DeclVector.empty()) {
23740 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
23741 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
23742 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
23743 if (Expr *Ex = TargetVarDecl->getInit())
23744 Visit(Ex);
23745 }
23746 }
23747 }
23748};
23749
23750/// Adding OMPDeclareTargetDeclAttr to variables with static storage
23751/// duration that are referenced in the initializer expression list of
23752/// variables with static storage duration in declare target directive.
23754 GlobalDeclRefChecker Checker;
23755 if (isa<VarDecl>(TargetDecl))
23756 Checker.declareTargetInitializer(TargetDecl);
23757}
23758
23760 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23761 ArrayRef<SourceLocation> MotionModifiersLoc,
23762 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23763 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23764 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23768
23769 // Process motion-modifiers, flag errors for duplicate modifiers.
23770 unsigned Count = 0;
23771 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23772 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23773 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23774 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23775 continue;
23776 }
23777 assert(Count < NumberOfOMPMotionModifiers &&
23778 "Modifiers exceed the allowed number of motion modifiers");
23779 Modifiers[Count] = MotionModifiers[I];
23780 ModifiersLoc[Count] = MotionModifiersLoc[I];
23781 ++Count;
23782 }
23783
23784 MappableVarListInfo MVLI(VarList);
23786 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23787 if (MVLI.ProcessedVarList.empty())
23788 return nullptr;
23789
23790 return OMPToClause::Create(
23791 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23792 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23793 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
23794}
23795
23797 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23798 ArrayRef<SourceLocation> MotionModifiersLoc,
23799 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23800 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23801 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23805
23806 // Process motion-modifiers, flag errors for duplicate modifiers.
23807 unsigned Count = 0;
23808 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23809 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23810 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23811 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23812 continue;
23813 }
23814 assert(Count < NumberOfOMPMotionModifiers &&
23815 "Modifiers exceed the allowed number of motion modifiers");
23816 Modifiers[Count] = MotionModifiers[I];
23817 ModifiersLoc[Count] = MotionModifiersLoc[I];
23818 ++Count;
23819 }
23820
23821 MappableVarListInfo MVLI(VarList);
23822 checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
23823 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23824 if (MVLI.ProcessedVarList.empty())
23825 return nullptr;
23826
23827 return OMPFromClause::Create(
23828 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23829 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23830 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
23831}
23832
23833OMPClause *
23835 const OMPVarListLocTy &Locs) {
23836 MappableVarListInfo MVLI(VarList);
23837 SmallVector<Expr *, 8> PrivateCopies;
23839
23840 for (Expr *RefExpr : VarList) {
23841 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
23842 SourceLocation ELoc;
23843 SourceRange ERange;
23844 Expr *SimpleRefExpr = RefExpr;
23845 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23846 if (Res.second) {
23847 // It will be analyzed later.
23848 MVLI.ProcessedVarList.push_back(RefExpr);
23849 PrivateCopies.push_back(nullptr);
23850 Inits.push_back(nullptr);
23851 }
23852 ValueDecl *D = Res.first;
23853 if (!D)
23854 continue;
23855
23856 QualType Type = D->getType();
23857 Type = Type.getNonReferenceType().getUnqualifiedType();
23858
23859 auto *VD = dyn_cast<VarDecl>(D);
23860
23861 // Item should be a pointer or reference to pointer.
23862 if (!Type->isPointerType()) {
23863 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
23864 << 0 << RefExpr->getSourceRange();
23865 continue;
23866 }
23867
23868 // Build the private variable and the expression that refers to it.
23869 auto VDPrivate =
23870 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
23871 D->hasAttrs() ? &D->getAttrs() : nullptr,
23872 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
23873 if (VDPrivate->isInvalidDecl())
23874 continue;
23875
23876 SemaRef.CurContext->addDecl(VDPrivate);
23877 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
23878 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
23879
23880 // Add temporary variable to initialize the private copy of the pointer.
23881 VarDecl *VDInit =
23882 buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp");
23883 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
23884 SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
23886 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
23887 /*DirectInit=*/false);
23888
23889 // If required, build a capture to implement the privatization initialized
23890 // with the current list item value.
23891 DeclRefExpr *Ref = nullptr;
23892 if (!VD)
23893 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
23894 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23895 PrivateCopies.push_back(VDPrivateRefExpr);
23896 Inits.push_back(VDInitRefExpr);
23897
23898 // We need to add a data sharing attribute for this variable to make sure it
23899 // is correctly captured. A variable that shows up in a use_device_ptr has
23900 // similar properties of a first private variable.
23901 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23902
23903 // Create a mappable component for the list item. List items in this clause
23904 // only need a component.
23905 MVLI.VarBaseDeclarations.push_back(D);
23906 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23907 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
23908 /*IsNonContiguous=*/false);
23909 }
23910
23911 if (MVLI.ProcessedVarList.empty())
23912 return nullptr;
23913
23915 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
23916 MVLI.VarBaseDeclarations, MVLI.VarComponents);
23917}
23918
23919OMPClause *
23921 const OMPVarListLocTy &Locs) {
23922 MappableVarListInfo MVLI(VarList);
23923
23924 for (Expr *RefExpr : VarList) {
23925 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
23926 SourceLocation ELoc;
23927 SourceRange ERange;
23928 Expr *SimpleRefExpr = RefExpr;
23929 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23930 /*AllowArraySection=*/true);
23931 if (Res.second) {
23932 // It will be analyzed later.
23933 MVLI.ProcessedVarList.push_back(RefExpr);
23934 }
23935 ValueDecl *D = Res.first;
23936 if (!D)
23937 continue;
23938 auto *VD = dyn_cast<VarDecl>(D);
23939
23940 // If required, build a capture to implement the privatization initialized
23941 // with the current list item value.
23942 DeclRefExpr *Ref = nullptr;
23943 if (!VD)
23944 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
23945 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23946
23947 // We need to add a data sharing attribute for this variable to make sure it
23948 // is correctly captured. A variable that shows up in a use_device_addr has
23949 // similar properties of a first private variable.
23950 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23951
23952 // Create a mappable component for the list item. List items in this clause
23953 // only need a component.
23954 MVLI.VarBaseDeclarations.push_back(D);
23955 MVLI.VarComponents.emplace_back();
23956 Expr *Component = SimpleRefExpr;
23957 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23958 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23959 Component =
23961 MVLI.VarComponents.back().emplace_back(Component, D,
23962 /*IsNonContiguous=*/false);
23963 }
23964
23965 if (MVLI.ProcessedVarList.empty())
23966 return nullptr;
23967
23969 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23970 MVLI.VarComponents);
23971}
23972
23973OMPClause *
23975 const OMPVarListLocTy &Locs) {
23976 MappableVarListInfo MVLI(VarList);
23977 for (Expr *RefExpr : VarList) {
23978 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
23979 SourceLocation ELoc;
23980 SourceRange ERange;
23981 Expr *SimpleRefExpr = RefExpr;
23982 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23983 if (Res.second) {
23984 // It will be analyzed later.
23985 MVLI.ProcessedVarList.push_back(RefExpr);
23986 }
23987 ValueDecl *D = Res.first;
23988 if (!D)
23989 continue;
23990
23991 QualType Type = D->getType();
23992 // item should be a pointer or array or reference to pointer or array
23993 if (!Type.getNonReferenceType()->isPointerType() &&
23994 !Type.getNonReferenceType()->isArrayType()) {
23995 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
23996 << 0 << RefExpr->getSourceRange();
23997 continue;
23998 }
23999
24000 // Check if the declaration in the clause does not show up in any data
24001 // sharing attribute.
24002 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
24003 if (isOpenMPPrivate(DVar.CKind)) {
24004 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24005 << getOpenMPClauseName(DVar.CKind)
24006 << getOpenMPClauseName(OMPC_is_device_ptr)
24007 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
24009 continue;
24010 }
24011
24012 const Expr *ConflictExpr;
24013 if (DSAStack->checkMappableExprComponentListsForDecl(
24014 D, /*CurrentRegionOnly=*/true,
24015 [&ConflictExpr](
24017 OpenMPClauseKind) -> bool {
24018 ConflictExpr = R.front().getAssociatedExpression();
24019 return true;
24020 })) {
24021 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24022 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
24023 << ConflictExpr->getSourceRange();
24024 continue;
24025 }
24026
24027 // Store the components in the stack so that they can be used to check
24028 // against other clauses later on.
24030 SimpleRefExpr, D, /*IsNonContiguous=*/false);
24031 DSAStack->addMappableExpressionComponents(
24032 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
24033
24034 // Record the expression we've just processed.
24035 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
24036
24037 // Create a mappable component for the list item. List items in this clause
24038 // only need a component. We use a null declaration to signal fields in
24039 // 'this'.
24040 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
24041 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
24042 "Unexpected device pointer expression!");
24043 MVLI.VarBaseDeclarations.push_back(
24044 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
24045 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24046 MVLI.VarComponents.back().push_back(MC);
24047 }
24048
24049 if (MVLI.ProcessedVarList.empty())
24050 return nullptr;
24051
24053 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24054 MVLI.VarComponents);
24055}
24056
24057OMPClause *
24059 const OMPVarListLocTy &Locs) {
24060 MappableVarListInfo MVLI(VarList);
24061 for (Expr *RefExpr : VarList) {
24062 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
24063 SourceLocation ELoc;
24064 SourceRange ERange;
24065 Expr *SimpleRefExpr = RefExpr;
24066 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24067 /*AllowArraySection=*/true);
24068 if (Res.second) {
24069 // It will be analyzed later.
24070 MVLI.ProcessedVarList.push_back(RefExpr);
24071 }
24072 ValueDecl *D = Res.first;
24073 if (!D)
24074 continue;
24075
24076 // Check if the declaration in the clause does not show up in any data
24077 // sharing attribute.
24078 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
24079 if (isOpenMPPrivate(DVar.CKind)) {
24080 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24081 << getOpenMPClauseName(DVar.CKind)
24082 << getOpenMPClauseName(OMPC_has_device_addr)
24083 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
24085 continue;
24086 }
24087
24088 const Expr *ConflictExpr;
24089 if (DSAStack->checkMappableExprComponentListsForDecl(
24090 D, /*CurrentRegionOnly=*/true,
24091 [&ConflictExpr](
24093 OpenMPClauseKind) -> bool {
24094 ConflictExpr = R.front().getAssociatedExpression();
24095 return true;
24096 })) {
24097 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24098 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
24099 << ConflictExpr->getSourceRange();
24100 continue;
24101 }
24102
24103 // Store the components in the stack so that they can be used to check
24104 // against other clauses later on.
24105 Expr *Component = SimpleRefExpr;
24106 auto *VD = dyn_cast<VarDecl>(D);
24107 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
24108 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
24109 Component =
24112 Component, D, /*IsNonContiguous=*/false);
24113 DSAStack->addMappableExpressionComponents(
24114 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
24115
24116 // Record the expression we've just processed.
24117 if (!VD && !SemaRef.CurContext->isDependentContext()) {
24118 DeclRefExpr *Ref =
24119 buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
24120 assert(Ref && "has_device_addr capture failed");
24121 MVLI.ProcessedVarList.push_back(Ref);
24122 } else
24123 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
24124
24125 // Create a mappable component for the list item. List items in this clause
24126 // only need a component. We use a null declaration to signal fields in
24127 // 'this'.
24128 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
24129 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
24130 "Unexpected device pointer expression!");
24131 MVLI.VarBaseDeclarations.push_back(
24132 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
24133 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24134 MVLI.VarComponents.back().push_back(MC);
24135 }
24136
24137 if (MVLI.ProcessedVarList.empty())
24138 return nullptr;
24139
24141 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24142 MVLI.VarComponents);
24143}
24144
24146 Expr *Allocator, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
24147 SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
24148 if (Allocator) {
24149 // OpenMP [2.11.4 allocate Clause, Description]
24150 // allocator is an expression of omp_allocator_handle_t type.
24151 if (!findOMPAllocatorHandleT(SemaRef, Allocator->getExprLoc(), DSAStack))
24152 return nullptr;
24153
24154 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
24155 if (AllocatorRes.isInvalid())
24156 return nullptr;
24157 AllocatorRes = SemaRef.PerformImplicitConversion(
24158 AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
24160 /*AllowExplicit=*/true);
24161 if (AllocatorRes.isInvalid())
24162 return nullptr;
24163 Allocator = AllocatorRes.get();
24164 } else {
24165 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
24166 // allocate clauses that appear on a target construct or on constructs in a
24167 // target region must specify an allocator expression unless a requires
24168 // directive with the dynamic_allocators clause is present in the same
24169 // compilation unit.
24170 if (getLangOpts().OpenMPIsTargetDevice &&
24171 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
24172 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
24173 }
24174 // Analyze and build list of variables.
24176 for (Expr *RefExpr : VarList) {
24177 assert(RefExpr && "NULL expr in OpenMP private clause.");
24178 SourceLocation ELoc;
24179 SourceRange ERange;
24180 Expr *SimpleRefExpr = RefExpr;
24181 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24182 if (Res.second) {
24183 // It will be analyzed later.
24184 Vars.push_back(RefExpr);
24185 }
24186 ValueDecl *D = Res.first;
24187 if (!D)
24188 continue;
24189
24190 auto *VD = dyn_cast<VarDecl>(D);
24191 DeclRefExpr *Ref = nullptr;
24192 if (!VD && !SemaRef.CurContext->isDependentContext())
24193 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
24194 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
24195 ? RefExpr->IgnoreParens()
24196 : Ref);
24197 }
24198
24199 if (Vars.empty())
24200 return nullptr;
24201
24202 if (Allocator)
24203 DSAStack->addInnerAllocatorExpr(Allocator);
24204 return OMPAllocateClause::Create(getASTContext(), StartLoc, LParenLoc,
24205 Allocator, ColonLoc, EndLoc, Vars);
24206}
24207
24209 SourceLocation StartLoc,
24210 SourceLocation LParenLoc,
24211 SourceLocation EndLoc) {
24213 for (Expr *RefExpr : VarList) {
24214 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
24215 SourceLocation ELoc;
24216 SourceRange ERange;
24217 Expr *SimpleRefExpr = RefExpr;
24218 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24219 if (Res.second)
24220 // It will be analyzed later.
24221 Vars.push_back(RefExpr);
24222 ValueDecl *D = Res.first;
24223 if (!D)
24224 continue;
24225
24226 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
24227 // A list-item cannot appear in more than one nontemporal clause.
24228 if (const Expr *PrevRef =
24229 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
24230 Diag(ELoc, diag::err_omp_used_in_clause_twice)
24231 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
24232 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
24233 << getOpenMPClauseName(OMPC_nontemporal);
24234 continue;
24235 }
24236
24237 Vars.push_back(RefExpr);
24238 }
24239
24240 if (Vars.empty())
24241 return nullptr;
24242
24243 return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc,
24244 EndLoc, Vars);
24245}
24246
24248 Stmt *AStmt,
24249 SourceLocation StartLoc,
24250 SourceLocation EndLoc) {
24251 if (!AStmt)
24252 return StmtError();
24253
24255
24256 return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
24257 AStmt);
24258}
24259
24261 SourceLocation StartLoc,
24262 SourceLocation LParenLoc,
24263 SourceLocation EndLoc) {
24265 for (Expr *RefExpr : VarList) {
24266 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
24267 SourceLocation ELoc;
24268 SourceRange ERange;
24269 Expr *SimpleRefExpr = RefExpr;
24270 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24271 /*AllowArraySection=*/true);
24272 if (Res.second)
24273 // It will be analyzed later.
24274 Vars.push_back(RefExpr);
24275 ValueDecl *D = Res.first;
24276 if (!D)
24277 continue;
24278
24279 const DSAStackTy::DSAVarData DVar =
24280 DSAStack->getTopDSA(D, /*FromParent=*/true);
24281 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
24282 // A list item that appears in the inclusive or exclusive clause must appear
24283 // in a reduction clause with the inscan modifier on the enclosing
24284 // worksharing-loop, worksharing-loop SIMD, or simd construct.
24285 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
24286 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
24287 << RefExpr->getSourceRange();
24288
24289 if (DSAStack->getParentDirective() != OMPD_unknown)
24290 DSAStack->markDeclAsUsedInScanDirective(D);
24291 Vars.push_back(RefExpr);
24292 }
24293
24294 if (Vars.empty())
24295 return nullptr;
24296
24297 return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
24298 EndLoc, Vars);
24299}
24300
24302 SourceLocation StartLoc,
24303 SourceLocation LParenLoc,
24304 SourceLocation EndLoc) {
24306 for (Expr *RefExpr : VarList) {
24307 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
24308 SourceLocation ELoc;
24309 SourceRange ERange;
24310 Expr *SimpleRefExpr = RefExpr;
24311 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24312 /*AllowArraySection=*/true);
24313 if (Res.second)
24314 // It will be analyzed later.
24315 Vars.push_back(RefExpr);
24316 ValueDecl *D = Res.first;
24317 if (!D)
24318 continue;
24319
24320 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
24321 DSAStackTy::DSAVarData DVar;
24322 if (ParentDirective != OMPD_unknown)
24323 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
24324 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
24325 // A list item that appears in the inclusive or exclusive clause must appear
24326 // in a reduction clause with the inscan modifier on the enclosing
24327 // worksharing-loop, worksharing-loop SIMD, or simd construct.
24328 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
24329 DVar.Modifier != OMPC_REDUCTION_inscan) {
24330 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
24331 << RefExpr->getSourceRange();
24332 } else {
24333 DSAStack->markDeclAsUsedInScanDirective(D);
24334 }
24335 Vars.push_back(RefExpr);
24336 }
24337
24338 if (Vars.empty())
24339 return nullptr;
24340
24341 return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
24342 EndLoc, Vars);
24343}
24344
24345/// Tries to find omp_alloctrait_t type.
24346static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
24347 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
24348 if (!OMPAlloctraitT.isNull())
24349 return true;
24350 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
24351 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
24352 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
24353 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
24354 return false;
24355 }
24356 Stack->setOMPAlloctraitT(PT.get());
24357 return true;
24358}
24359
24361 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
24363 ASTContext &Context = getASTContext();
24364 // OpenMP [2.12.5, target Construct]
24365 // allocator is an identifier of omp_allocator_handle_t type.
24366 if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack))
24367 return nullptr;
24368 // OpenMP [2.12.5, target Construct]
24369 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
24370 if (llvm::any_of(
24371 Data,
24372 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
24373 !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack))
24374 return nullptr;
24375 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
24376 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
24377 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
24378 StringRef Allocator =
24379 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
24380 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
24381 PredefinedAllocators.insert(SemaRef.LookupSingleName(
24382 SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
24383 }
24384
24386 for (const UsesAllocatorsData &D : Data) {
24387 Expr *AllocatorExpr = nullptr;
24388 // Check allocator expression.
24389 if (D.Allocator->isTypeDependent()) {
24390 AllocatorExpr = D.Allocator;
24391 } else {
24392 // Traits were specified - need to assign new allocator to the specified
24393 // allocator, so it must be an lvalue.
24394 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
24395 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
24396 bool IsPredefinedAllocator = false;
24397 if (DRE) {
24398 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
24399 getAllocatorKind(SemaRef, DSAStack, AllocatorExpr);
24400 IsPredefinedAllocator =
24401 AllocatorTy !=
24402 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
24403 }
24404 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
24405 QualType AllocatorExprType = AllocatorExpr->getType();
24406 bool IsTypeCompatible = IsPredefinedAllocator;
24407 IsTypeCompatible = IsTypeCompatible ||
24408 Context.hasSameUnqualifiedType(AllocatorExprType,
24409 OMPAllocatorHandleT);
24410 IsTypeCompatible =
24411 IsTypeCompatible ||
24412 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
24413 bool IsNonConstantLValue =
24414 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
24415 if (!DRE || !IsTypeCompatible ||
24416 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
24417 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
24418 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
24419 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
24420 continue;
24421 }
24422 // OpenMP [2.12.5, target Construct]
24423 // Predefined allocators appearing in a uses_allocators clause cannot have
24424 // traits specified.
24425 if (IsPredefinedAllocator && D.AllocatorTraits) {
24427 diag::err_omp_predefined_allocator_with_traits)
24429 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
24430 << cast<NamedDecl>(DRE->getDecl())->getName()
24431 << D.Allocator->getSourceRange();
24432 continue;
24433 }
24434 // OpenMP [2.12.5, target Construct]
24435 // Non-predefined allocators appearing in a uses_allocators clause must
24436 // have traits specified.
24437 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
24439 diag::err_omp_nonpredefined_allocator_without_traits);
24440 continue;
24441 }
24442 // No allocator traits - just convert it to rvalue.
24443 if (!D.AllocatorTraits)
24444 AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
24445 DSAStack->addUsesAllocatorsDecl(
24446 DRE->getDecl(),
24447 IsPredefinedAllocator
24448 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
24449 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
24450 }
24451 Expr *AllocatorTraitsExpr = nullptr;
24452 if (D.AllocatorTraits) {
24454 AllocatorTraitsExpr = D.AllocatorTraits;
24455 } else {
24456 // OpenMP [2.12.5, target Construct]
24457 // Arrays that contain allocator traits that appear in a uses_allocators
24458 // clause must be constant arrays, have constant values and be defined
24459 // in the same scope as the construct in which the clause appears.
24460 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
24461 // Check that traits expr is a constant array.
24462 QualType TraitTy;
24463 if (const ArrayType *Ty =
24464 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
24465 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
24466 TraitTy = ConstArrayTy->getElementType();
24467 if (TraitTy.isNull() ||
24468 !(Context.hasSameUnqualifiedType(TraitTy,
24469 DSAStack->getOMPAlloctraitT()) ||
24470 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
24471 /*CompareUnqualified=*/true))) {
24473 diag::err_omp_expected_array_alloctraits)
24474 << AllocatorTraitsExpr->getType();
24475 continue;
24476 }
24477 // Do not map by default allocator traits if it is a standalone
24478 // variable.
24479 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
24480 DSAStack->addUsesAllocatorsDecl(
24481 DRE->getDecl(),
24482 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
24483 }
24484 }
24485 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
24486 NewD.Allocator = AllocatorExpr;
24487 NewD.AllocatorTraits = AllocatorTraitsExpr;
24488 NewD.LParenLoc = D.LParenLoc;
24489 NewD.RParenLoc = D.RParenLoc;
24490 }
24491 return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc,
24492 EndLoc, NewData);
24493}
24494
24496 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
24497 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
24499 for (Expr *RefExpr : Locators) {
24500 assert(RefExpr && "NULL expr in OpenMP shared clause.");
24501 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
24502 // It will be analyzed later.
24503 Vars.push_back(RefExpr);
24504 continue;
24505 }
24506
24507 SourceLocation ELoc = RefExpr->getExprLoc();
24508 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
24509
24510 if (!SimpleExpr->isLValue()) {
24511 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24512 << 1 << 0 << RefExpr->getSourceRange();
24513 continue;
24514 }
24515
24516 ExprResult Res;
24517 {
24519 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
24520 }
24521 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
24522 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
24523 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24524 << 1 << 0 << RefExpr->getSourceRange();
24525 continue;
24526 }
24527 Vars.push_back(SimpleExpr);
24528 }
24529
24530 return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc,
24531 ColonLoc, EndLoc, Modifier, Vars);
24532}
24533
24535 SourceLocation KindLoc,
24536 SourceLocation StartLoc,
24537 SourceLocation LParenLoc,
24538 SourceLocation EndLoc) {
24539 if (Kind == OMPC_BIND_unknown) {
24540 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24541 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
24542 /*Last=*/unsigned(OMPC_BIND_unknown))
24543 << getOpenMPClauseName(OMPC_bind);
24544 return nullptr;
24545 }
24546
24547 return OMPBindClause::Create(getASTContext(), Kind, KindLoc, StartLoc,
24548 LParenLoc, EndLoc);
24549}
24550
24552 SourceLocation StartLoc,
24553 SourceLocation LParenLoc,
24554 SourceLocation EndLoc) {
24555 Expr *ValExpr = Size;
24556 Stmt *HelperValStmt = nullptr;
24557
24558 // OpenMP [2.5, Restrictions]
24559 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
24560 // value.
24561 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem,
24562 /*StrictlyPositive=*/false))
24563 return nullptr;
24564
24565 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24567 DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP);
24568 if (CaptureRegion != OMPD_unknown &&
24570 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
24571 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24572 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
24573 HelperValStmt = buildPreInits(getASTContext(), Captures);
24574 }
24575
24577 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
24578}
24579
24582 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
24583 SourceLocation LParenLoc, SourceLocation EndLoc) {
24584
24585 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
24586 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
24587 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
24588 DepType != OMPC_DOACROSS_source_omp_cur_iteration &&
24589 DepType != OMPC_DOACROSS_source) {
24590 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
24591 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross);
24592 return nullptr;
24593 }
24594
24597 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
24598 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
24599 SemaRef,
24600 DepType == OMPC_DOACROSS_source ||
24601 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
24602 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
24603 VarList, DSAStack, EndLoc);
24604 Vars = VarOffset.Vars;
24605 OpsOffs = VarOffset.OpsOffs;
24606 TotalDepCount = VarOffset.TotalDepCount;
24607 auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc,
24608 EndLoc, DepType, DepLoc, ColonLoc, Vars,
24609 TotalDepCount.getZExtValue());
24610 if (DSAStack->isParentOrderedRegion())
24611 DSAStack->addDoacrossDependClause(C, OpsOffs);
24612 return C;
24613}
24614
24616 SourceLocation StartLoc,
24617 SourceLocation LParenLoc,
24618 SourceLocation EndLoc) {
24619 return new (getASTContext())
24620 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
24621}
24622
24624 SourceLocation EndLoc) {
24625 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
24626}
24627
24629 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
24630 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
24631 Expr *Stride, SourceLocation RBLoc) {
24632 ASTContext &Context = getASTContext();
24633 if (Base->hasPlaceholderType() &&
24634 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
24636 if (Result.isInvalid())
24637 return ExprError();
24638 Base = Result.get();
24639 }
24640 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
24642 if (Result.isInvalid())
24643 return ExprError();
24645 if (Result.isInvalid())
24646 return ExprError();
24647 LowerBound = Result.get();
24648 }
24649 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
24651 if (Result.isInvalid())
24652 return ExprError();
24654 if (Result.isInvalid())
24655 return ExprError();
24656 Length = Result.get();
24657 }
24658 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
24660 if (Result.isInvalid())
24661 return ExprError();
24663 if (Result.isInvalid())
24664 return ExprError();
24665 Stride = Result.get();
24666 }
24667
24668 // Build an unanalyzed expression if either operand is type-dependent.
24669 if (Base->isTypeDependent() ||
24670 (LowerBound &&
24671 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
24672 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
24673 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
24674 return new (Context) ArraySectionExpr(
24675 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
24676 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
24677 }
24678
24679 // Perform default conversions.
24681 QualType ResultTy;
24682 if (OriginalTy->isAnyPointerType()) {
24683 ResultTy = OriginalTy->getPointeeType();
24684 } else if (OriginalTy->isArrayType()) {
24685 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
24686 } else {
24687 return ExprError(
24688 Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
24689 << Base->getSourceRange());
24690 }
24691 // C99 6.5.2.1p1
24692 if (LowerBound) {
24693 auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
24694 LowerBound);
24695 if (Res.isInvalid())
24696 return ExprError(Diag(LowerBound->getExprLoc(),
24697 diag::err_omp_typecheck_section_not_integer)
24698 << 0 << LowerBound->getSourceRange());
24699 LowerBound = Res.get();
24700
24701 if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
24702 LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
24703 Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
24704 << 0 << LowerBound->getSourceRange();
24705 }
24706 if (Length) {
24707 auto Res =
24708 PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
24709 if (Res.isInvalid())
24710 return ExprError(Diag(Length->getExprLoc(),
24711 diag::err_omp_typecheck_section_not_integer)
24712 << 1 << Length->getSourceRange());
24713 Length = Res.get();
24714
24715 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
24716 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
24717 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
24718 << 1 << Length->getSourceRange();
24719 }
24720 if (Stride) {
24721 ExprResult Res =
24723 if (Res.isInvalid())
24724 return ExprError(Diag(Stride->getExprLoc(),
24725 diag::err_omp_typecheck_section_not_integer)
24726 << 1 << Stride->getSourceRange());
24727 Stride = Res.get();
24728
24729 if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
24730 Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
24731 Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
24732 << 1 << Stride->getSourceRange();
24733 }
24734
24735 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
24736 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
24737 // type. Note that functions are not objects, and that (in C99 parlance)
24738 // incomplete types are not object types.
24739 if (ResultTy->isFunctionType()) {
24740 Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
24741 << ResultTy << Base->getSourceRange();
24742 return ExprError();
24743 }
24744
24745 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
24746 diag::err_omp_section_incomplete_type, Base))
24747 return ExprError();
24748
24749 if (LowerBound && !OriginalTy->isAnyPointerType()) {
24751 if (LowerBound->EvaluateAsInt(Result, Context)) {
24752 // OpenMP 5.0, [2.1.5 Array Sections]
24753 // The array section must be a subset of the original array.
24754 llvm::APSInt LowerBoundValue = Result.Val.getInt();
24755 if (LowerBoundValue.isNegative()) {
24756 Diag(LowerBound->getExprLoc(),
24757 diag::err_omp_section_not_subset_of_array)
24758 << LowerBound->getSourceRange();
24759 return ExprError();
24760 }
24761 }
24762 }
24763
24764 if (Length) {
24766 if (Length->EvaluateAsInt(Result, Context)) {
24767 // OpenMP 5.0, [2.1.5 Array Sections]
24768 // The length must evaluate to non-negative integers.
24769 llvm::APSInt LengthValue = Result.Val.getInt();
24770 if (LengthValue.isNegative()) {
24771 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
24772 << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
24773 << Length->getSourceRange();
24774 return ExprError();
24775 }
24776 }
24777 } else if (ColonLocFirst.isValid() &&
24778 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
24779 !OriginalTy->isVariableArrayType()))) {
24780 // OpenMP 5.0, [2.1.5 Array Sections]
24781 // When the size of the array dimension is not known, the length must be
24782 // specified explicitly.
24783 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
24784 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
24785 return ExprError();
24786 }
24787
24788 if (Stride) {
24790 if (Stride->EvaluateAsInt(Result, Context)) {
24791 // OpenMP 5.0, [2.1.5 Array Sections]
24792 // The stride must evaluate to a positive integer.
24793 llvm::APSInt StrideValue = Result.Val.getInt();
24794 if (!StrideValue.isStrictlyPositive()) {
24795 Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
24796 << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
24797 << Stride->getSourceRange();
24798 return ExprError();
24799 }
24800 }
24801 }
24802
24803 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
24805 if (Result.isInvalid())
24806 return ExprError();
24807 Base = Result.get();
24808 }
24809 return new (Context) ArraySectionExpr(
24810 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
24811 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
24812}
24813
24815 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
24816 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
24817 ASTContext &Context = getASTContext();
24818 if (Base->hasPlaceholderType()) {
24820 if (Result.isInvalid())
24821 return ExprError();
24823 if (Result.isInvalid())
24824 return ExprError();
24825 Base = Result.get();
24826 }
24827 QualType BaseTy = Base->getType();
24828 // Delay analysis of the types/expressions if instantiation/specialization is
24829 // required.
24830 if (!BaseTy->isPointerType() && Base->isTypeDependent())
24831 return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
24832 LParenLoc, RParenLoc, Dims, Brackets);
24833 if (!BaseTy->isPointerType() ||
24834 (!Base->isTypeDependent() &&
24835 BaseTy->getPointeeType()->isIncompleteType()))
24836 return ExprError(Diag(Base->getExprLoc(),
24837 diag::err_omp_non_pointer_type_array_shaping_base)
24838 << Base->getSourceRange());
24839
24840 SmallVector<Expr *, 4> NewDims;
24841 bool ErrorFound = false;
24842 for (Expr *Dim : Dims) {
24843 if (Dim->hasPlaceholderType()) {
24845 if (Result.isInvalid()) {
24846 ErrorFound = true;
24847 continue;
24848 }
24850 if (Result.isInvalid()) {
24851 ErrorFound = true;
24852 continue;
24853 }
24854 Dim = Result.get();
24855 }
24856 if (!Dim->isTypeDependent()) {
24858 PerformOpenMPImplicitIntegerConversion(Dim->getExprLoc(), Dim);
24859 if (Result.isInvalid()) {
24860 ErrorFound = true;
24861 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
24862 << Dim->getSourceRange();
24863 continue;
24864 }
24865 Dim = Result.get();
24866 Expr::EvalResult EvResult;
24867 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
24868 // OpenMP 5.0, [2.1.4 Array Shaping]
24869 // Each si is an integral type expression that must evaluate to a
24870 // positive integer.
24871 llvm::APSInt Value = EvResult.Val.getInt();
24872 if (!Value.isStrictlyPositive()) {
24873 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
24874 << toString(Value, /*Radix=*/10, /*Signed=*/true)
24875 << Dim->getSourceRange();
24876 ErrorFound = true;
24877 continue;
24878 }
24879 }
24880 }
24881 NewDims.push_back(Dim);
24882 }
24883 if (ErrorFound)
24884 return ExprError();
24885 return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
24886 LParenLoc, RParenLoc, NewDims, Brackets);
24887}
24888
24890 SourceLocation IteratorKwLoc,
24891 SourceLocation LLoc,
24892 SourceLocation RLoc,
24894 ASTContext &Context = getASTContext();
24896 bool IsCorrect = true;
24897 for (const OMPIteratorData &D : Data) {
24898 TypeSourceInfo *TInfo = nullptr;
24899 SourceLocation StartLoc;
24900 QualType DeclTy;
24901 if (!D.Type.getAsOpaquePtr()) {
24902 // OpenMP 5.0, 2.1.6 Iterators
24903 // In an iterator-specifier, if the iterator-type is not specified then
24904 // the type of that iterator is of int type.
24905 DeclTy = Context.IntTy;
24906 StartLoc = D.DeclIdentLoc;
24907 } else {
24908 DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo);
24909 StartLoc = TInfo->getTypeLoc().getBeginLoc();
24910 }
24911
24912 bool IsDeclTyDependent = DeclTy->isDependentType() ||
24913 DeclTy->containsUnexpandedParameterPack() ||
24914 DeclTy->isInstantiationDependentType();
24915 if (!IsDeclTyDependent) {
24916 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
24917 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
24918 // The iterator-type must be an integral or pointer type.
24919 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
24920 << DeclTy;
24921 IsCorrect = false;
24922 continue;
24923 }
24924 if (DeclTy.isConstant(Context)) {
24925 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
24926 // The iterator-type must not be const qualified.
24927 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
24928 << DeclTy;
24929 IsCorrect = false;
24930 continue;
24931 }
24932 }
24933
24934 // Iterator declaration.
24935 assert(D.DeclIdent && "Identifier expected.");
24936 // Always try to create iterator declarator to avoid extra error messages
24937 // about unknown declarations use.
24938 auto *VD =
24939 VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc,
24940 D.DeclIdent, DeclTy, TInfo, SC_None);
24941 VD->setImplicit();
24942 if (S) {
24943 // Check for conflicting previous declaration.
24944 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
24946 RedeclarationKind::ForVisibleRedeclaration);
24947 Previous.suppressDiagnostics();
24949
24951 /*ConsiderLinkage=*/false,
24952 /*AllowInlineNamespace=*/false);
24953 if (!Previous.empty()) {
24954 NamedDecl *Old = Previous.getRepresentativeDecl();
24955 Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
24956 Diag(Old->getLocation(), diag::note_previous_definition);
24957 } else {
24959 }
24960 } else {
24962 }
24963
24964 /// Act on the iterator variable declaration.
24966
24967 Expr *Begin = D.Range.Begin;
24968 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
24969 ExprResult BeginRes =
24971 Begin = BeginRes.get();
24972 }
24973 Expr *End = D.Range.End;
24974 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
24975 ExprResult EndRes =
24977 End = EndRes.get();
24978 }
24979 Expr *Step = D.Range.Step;
24980 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
24981 if (!Step->getType()->isIntegralType(Context)) {
24982 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
24983 << Step << Step->getSourceRange();
24984 IsCorrect = false;
24985 continue;
24986 }
24987 std::optional<llvm::APSInt> Result =
24988 Step->getIntegerConstantExpr(Context);
24989 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
24990 // If the step expression of a range-specification equals zero, the
24991 // behavior is unspecified.
24992 if (Result && Result->isZero()) {
24993 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
24994 << Step << Step->getSourceRange();
24995 IsCorrect = false;
24996 continue;
24997 }
24998 }
24999 if (!Begin || !End || !IsCorrect) {
25000 IsCorrect = false;
25001 continue;
25002 }
25003 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
25004 IDElem.IteratorDecl = VD;
25005 IDElem.AssignmentLoc = D.AssignLoc;
25006 IDElem.Range.Begin = Begin;
25007 IDElem.Range.End = End;
25008 IDElem.Range.Step = Step;
25009 IDElem.ColonLoc = D.ColonLoc;
25010 IDElem.SecondColonLoc = D.SecColonLoc;
25011 }
25012 if (!IsCorrect) {
25013 // Invalidate all created iterator declarations if error is found.
25014 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
25015 if (Decl *ID = D.IteratorDecl)
25016 ID->setInvalidDecl();
25017 }
25018 return ExprError();
25019 }
25022 // Build number of ityeration for each iteration range.
25023 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
25024 // ((Begini-Stepi-1-Endi) / -Stepi);
25026 // (Endi - Begini)
25027 ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub,
25028 D.Range.End, D.Range.Begin);
25029 if (!Res.isUsable()) {
25030 IsCorrect = false;
25031 continue;
25032 }
25033 ExprResult St, St1;
25034 if (D.Range.Step) {
25035 St = D.Range.Step;
25036 // (Endi - Begini) + Stepi
25037 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(),
25038 St.get());
25039 if (!Res.isUsable()) {
25040 IsCorrect = false;
25041 continue;
25042 }
25043 // (Endi - Begini) + Stepi - 1
25045 D.AssignmentLoc, BO_Sub, Res.get(),
25046 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
25047 if (!Res.isUsable()) {
25048 IsCorrect = false;
25049 continue;
25050 }
25051 // ((Endi - Begini) + Stepi - 1) / Stepi
25052 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(),
25053 St.get());
25054 if (!Res.isUsable()) {
25055 IsCorrect = false;
25056 continue;
25057 }
25058 St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
25059 D.Range.Step);
25060 // (Begini - Endi)
25062 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
25063 if (!Res1.isUsable()) {
25064 IsCorrect = false;
25065 continue;
25066 }
25067 // (Begini - Endi) - Stepi
25068 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(),
25069 St1.get());
25070 if (!Res1.isUsable()) {
25071 IsCorrect = false;
25072 continue;
25073 }
25074 // (Begini - Endi) - Stepi - 1
25076 D.AssignmentLoc, BO_Sub, Res1.get(),
25077 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
25078 if (!Res1.isUsable()) {
25079 IsCorrect = false;
25080 continue;
25081 }
25082 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
25083 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(),
25084 St1.get());
25085 if (!Res1.isUsable()) {
25086 IsCorrect = false;
25087 continue;
25088 }
25089 // Stepi > 0.
25091 D.AssignmentLoc, BO_GT, D.Range.Step,
25092 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
25093 if (!CmpRes.isUsable()) {
25094 IsCorrect = false;
25095 continue;
25096 }
25097 Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
25098 CmpRes.get(), Res.get(), Res1.get());
25099 if (!Res.isUsable()) {
25100 IsCorrect = false;
25101 continue;
25102 }
25103 }
25104 Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false);
25105 if (!Res.isUsable()) {
25106 IsCorrect = false;
25107 continue;
25108 }
25109
25110 // Build counter update.
25111 // Build counter.
25112 auto *CounterVD = VarDecl::Create(Context, SemaRef.CurContext,
25113 D.IteratorDecl->getBeginLoc(),
25114 D.IteratorDecl->getBeginLoc(), nullptr,
25115 Res.get()->getType(), nullptr, SC_None);
25116 CounterVD->setImplicit();
25117 ExprResult RefRes =
25118 SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue,
25119 D.IteratorDecl->getBeginLoc());
25120 // Build counter update.
25121 // I = Begini + counter * Stepi;
25122 ExprResult UpdateRes;
25123 if (D.Range.Step) {
25124 UpdateRes = SemaRef.CreateBuiltinBinOp(
25125 D.AssignmentLoc, BO_Mul,
25126 SemaRef.DefaultLvalueConversion(RefRes.get()).get(), St.get());
25127 } else {
25128 UpdateRes = SemaRef.DefaultLvalueConversion(RefRes.get());
25129 }
25130 if (!UpdateRes.isUsable()) {
25131 IsCorrect = false;
25132 continue;
25133 }
25134 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
25135 D.Range.Begin, UpdateRes.get());
25136 if (!UpdateRes.isUsable()) {
25137 IsCorrect = false;
25138 continue;
25139 }
25140 ExprResult VDRes =
25141 SemaRef.BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl),
25142 cast<VarDecl>(D.IteratorDecl)->getType(),
25143 VK_LValue, D.IteratorDecl->getBeginLoc());
25144 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
25145 VDRes.get(), UpdateRes.get());
25146 if (!UpdateRes.isUsable()) {
25147 IsCorrect = false;
25148 continue;
25149 }
25150 UpdateRes =
25151 SemaRef.ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true);
25152 if (!UpdateRes.isUsable()) {
25153 IsCorrect = false;
25154 continue;
25155 }
25156 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
25157 D.AssignmentLoc, UO_PreInc, RefRes.get());
25158 if (!CounterUpdateRes.isUsable()) {
25159 IsCorrect = false;
25160 continue;
25161 }
25162 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(CounterUpdateRes.get(),
25163 /*DiscardedValue=*/true);
25164 if (!CounterUpdateRes.isUsable()) {
25165 IsCorrect = false;
25166 continue;
25167 }
25168 OMPIteratorHelperData &HD = Helpers.emplace_back();
25169 HD.CounterVD = CounterVD;
25170 HD.Upper = Res.get();
25171 HD.Update = UpdateRes.get();
25172 HD.CounterUpdate = CounterUpdateRes.get();
25173 }
25174 } else {
25175 Helpers.assign(ID.size(), {});
25176 }
25177 if (!IsCorrect) {
25178 // Invalidate all created iterator declarations if error is found.
25179 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
25180 if (Decl *ID = D.IteratorDecl)
25181 ID->setInvalidDecl();
25182 }
25183 return ExprError();
25184 }
25185 return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc,
25186 LLoc, RLoc, ID, Helpers);
25187}
25188
25190 : SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3284
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:2975
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:143
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 checkOMPArraySectionConstantForReduction(ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement, SmallVectorImpl< llvm::APSInt > &ArraySizes)
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 bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef)
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 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 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.
static bool checkOpenMPIterationSpace(OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA, unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, llvm::MutableArrayRef< LoopIterationSpace > ResultIterSpaces, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures)
Called on a for stmt to check and extract its iteration space for further processing (such as collaps...
#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, SemaOpenMP::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)
This file declares semantic analysis for OpenMP constructs and clauses.
static CharSourceRange getRange(const CharSourceRange &EditRange, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeMacroExpansion)
Definition: SourceCode.cpp:152
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
StateNode * Previous
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
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:648
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:1203
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2574
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:2590
bool DeclMustBeEmitted(const Decl *D)
Determines if the decl can be CodeGen'ed or deserialized from PCH lazily, only when used; this is onl...
CanQualType OMPArrayShapingTy
Definition: ASTContext.h:1131
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType VoidPtrTy
Definition: ASTContext.h:1118
void Deallocate(void *Ptr) const
Definition: ASTContext.h:724
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:1119
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:1590
CanQualType OMPIteratorTy
Definition: ASTContext.h:1131
IdentifierTable & Idents
Definition: ASTContext.h:644
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 ArraySectionTy
Definition: ASTContext.h:1130
CanQualType BoolTy
Definition: ASTContext.h:1092
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:1119
CanQualType IntTy
Definition: ASTContext.h:1100
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:2617
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:2340
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType VoidTy
Definition: ASTContext.h:1091
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:1568
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:757
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
This class represents BOTH the OpenMP Array Section and OpenACC 'subarray', with a boolean differenti...
Definition: Expr.h:6734
Expr * getBase()
Get base of the array section.
Definition: Expr.h:6800
Expr * getLength()
Get length of array section.
Definition: Expr.h:6810
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition: Expr.cpp:5063
Expr * getLowerBound()
Get lower bound of array section.
Definition: Expr.h:6804
SourceLocation getColonLocFirst() const
Definition: Expr.h:6831
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition: Expr.h:2664
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition: Type.h:3514
QualType getElementType() const
Definition: Type.h:3526
Attr - This represents one attribute.
Definition: Attr.h:42
Represents an attribute applied to a statement.
Definition: Stmt.h:2080
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:3840
Expr * getLHS() const
Definition: Expr.h:3889
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition: Expr.cpp:2181
static Opcode getOpForCompoundAssignment(Opcode Opc)
Definition: Expr.h:3986
bool isRelationalOp() const
Definition: Expr.h:3934
SourceLocation getOperatorLoc() const
Definition: Expr.h:3881
SourceLocation getExprLoc() const
Definition: Expr.h:3880
static Opcode reverseComparisonOp(Opcode Opc)
Definition: Expr.h:3958
Expr * getRHS() const
Definition: Expr.h:3891
Opcode getOpcode() const
Definition: Expr.h:3884
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition: Expr.cpp:2143
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:2535
Represents a C++ conversion function within a class.
Definition: DeclCXX.h:2862
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:1234
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:2820
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:1494
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.cpp:1638
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition: Expr.h:2990
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:4687
unsigned getNumParams() const
Definition: Decl.h:4729
void setNothrow(bool Nothrow=true)
Definition: Decl.cpp:5446
ImplicitParamDecl * getParam(unsigned i) const
Definition: Decl.h:4731
Describes the capture of either a variable, or 'this', or variable-length array type.
Definition: Stmt.h:3770
This captures a statement into a function.
Definition: Stmt.h:3757
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
Definition: Stmt.cpp:1407
SourceRange getSourceRange() const LLVM_READONLY
Definition: Stmt.h:3960
Stmt * getCapturedStmt()
Retrieve the statement being captured.
Definition: Stmt.h:3861
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:3952
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition: Expr.h:3483
Declaration of a class template.
Complex values, per C99 6.2.5p11.
Definition: Type.h:3082
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:1606
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:4179
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:1369
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1436
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:2066
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
Definition: DeclBase.h:2191
bool isFileContext() const
Definition: DeclBase.h:2137
bool isExternCXXContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
Definition: DeclBase.cpp:1330
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
Definition: DeclBase.cpp:1264
DeclContext * getLexicalParent()
getLexicalParent - Returns the containing lexical DeclContext.
Definition: DeclBase.h:2082
bool isNamespace() const
Definition: DeclBase.h:2151
bool isTranslationUnit() const
Definition: DeclBase.h:2142
void addDecl(Decl *D)
Add the declaration D into this context.
Definition: DeclBase.cpp:1698
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition: DeclBase.h:2322
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
Definition: DeclBase.cpp:1315
bool Encloses(const DeclContext *DC) const
Determine whether this declaration context encloses the declaration context DC.
Definition: DeclBase.cpp:1334
void addHiddenDecl(Decl *D)
Add the declaration D to this context without modifying any lookup tables.
Definition: DeclBase.cpp:1672
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:1497
const Decl * getSingleDecl() const
Definition: Stmt.h:1512
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
T * getAttr() const
Definition: DeclBase.h:579
bool hasAttrs() const
Definition: DeclBase.h:524
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:599
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:974
bool isInvalidDecl() const
Definition: DeclBase.h:594
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition: DeclBase.h:565
void setAccess(AccessSpecifier AS)
Definition: DeclBase.h:508
SourceLocation getLocation() const
Definition: DeclBase.h:445
void setImplicit(bool I=true)
Definition: DeclBase.h:600
void setReferenced(bool R=true)
Definition: DeclBase.h:629
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
Definition: DeclBase.h:1039
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:454
AccessSpecifier getAccess() const
Definition: DeclBase.h:513
AttrVec & getAttrs()
Definition: DeclBase.h:530
void setDeclContext(DeclContext *DC)
setDeclContext - Set both the semantic and lexical DeclContext to DC.
Definition: DeclBase.cpp:336
bool hasAttr() const
Definition: DeclBase.h:583
void setLexicalDeclContext(DeclContext *DC)
Definition: DeclBase.cpp:340
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclBase.h:968
Kind getKind() const
Definition: DeclBase.h:448
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition: DeclBase.h:433
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:1898
const DeclSpec & getDeclSpec() const
getDeclSpec - Return the declaration-specifier that this declarator was declared with.
Definition: DeclSpec.h:2045
SourceLocation getIdentifierLoc() const
Definition: DeclSpec.h:2334
void SetIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc)
Set the name of this declarator to be the given identifier.
Definition: DeclSpec.h:2337
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclSpec.h:2081
void setFunctionDefinitionKind(FunctionDefinitionKind Val)
Definition: DeclSpec.h:2731
const CXXScopeSpec & getCXXScopeSpec() const
getCXXScopeSpec - Return the C++ scope specifier (global scope or nested-name-specifier) that is part...
Definition: DeclSpec.h:2060
bool isInvalidType() const
Definition: DeclSpec.h:2712
const IdentifierInfo * getIdentifier() const
Definition: DeclSpec.h:2328
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:3064
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:3076
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3059
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3047
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:3055
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:3039
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:915
Represents a member of a struct/union/class.
Definition: Decl.h:3058
bool isBitField() const
Determines whether this field is a bitfield.
Definition: Decl.h:3149
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
Definition: Decl.h:3282
static FloatingLiteral * Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L)
Definition: Expr.cpp:1078
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition: Stmt.h:2781
Represents a function declaration or definition.
Definition: Decl.h:1971
const ParmVarDecl * getParamDecl(unsigned i) const
Definition: Decl.h:2707
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:2684
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition: Decl.h:2433
bool isConsteval() const
Definition: Decl.h:2445
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition: Decl.cpp:3692
Represents a prototype with parameter type info, e.g.
Definition: Type.h:4652
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:2138
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:2074
ImplicitConversionSequence - Represents an implicit conversion sequence, which may be a standard conv...
Definition: Overload.h:543
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:8591
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:977
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:461
A class for iterating through a result set and possibly filtering out results.
Definition: Lookup.h:673
Represents the results of name lookup.
Definition: Lookup.h:46
LLVM_ATTRIBUTE_REINITIALIZES void clear()
Clears out any current state.
Definition: Lookup.h:603
DeclClass * getAsSingle() const
Definition: Lookup.h:556
bool empty() const
Return true if no decls were found.
Definition: Lookup.h:362
Filter makeFilter()
Create a filter for this result set.
Definition: Lookup.h:747
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
Definition: Lookup.h:566
bool isAmbiguous() const
Definition: Lookup.h:324
bool isSingleResult() const
Determines if this names a single result which is not an unresolved value using decl.
Definition: Lookup.h:331
NamedDecl * getRepresentativeDecl() const
Fetches a representative decl. Useful for lazy diagnostics.
Definition: Lookup.h:573
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
Definition: Lookup.h:632
iterator end() const
Definition: Lookup.h:359
static bool isVisible(Sema &SemaRef, NamedDecl *D)
Determine whether the given declaration is visible to the program.
iterator begin() const
Definition: Lookup.h:358
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:3172
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition: Expr.h:3255
Expr * getBase() const
Definition: Expr.h:3249
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:3233
SourceLocation getExprLoc() const LLVM_READONLY
Definition: Expr.h:3367
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
An explicit cast in C or a C-style cast in C++, which uses the syntax ([s1][s2]......
Definition: ExprOpenMP.h:24
Expr * getBase()
Fetches base expression of array shaping expression.
Definition: ExprOpenMP.h:90
static OMPArrayShapingExpr * Create(const ASTContext &Context, QualType T, Expr *Op, SourceLocation L, SourceLocation R, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > BracketRanges)
Definition: Expr.cpp:5144
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:176
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:144
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:114
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
SourceLocation getBeginLoc() const
Returns starting location of directive kind.
Definition: StmtOpenMP.h:502
static const SpecificClause * getSingleClause(ArrayRef< OMPClause * > Clauses)
Gets a single clause of the specified kind associated with the current directive iff there is only on...
Definition: StmtOpenMP.h:477
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 OMPIteratorExpr * Create(const ASTContext &Context, QualType T, SourceLocation IteratorKwLoc, SourceLocation L, SourceLocation R, ArrayRef< IteratorDefinition > Data, ArrayRef< OMPIteratorHelperData > Helpers)
Definition: Expr.cpp:5273
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:417
clauselist_range clauselists()
Definition: DeclOpenMP.h:442
static OMPRequiresDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< OMPClause * > CL)
Create requires node.
Definition: DeclOpenMP.cpp:86
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, bool CanBeParallelFor)
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:1761
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const 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:4875
A (possibly-)qualified type.
Definition: Type.h:940
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
Definition: Type.cpp:2716
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition: Type.h:7444
QualType withRestrict() const
Definition: Type.h:1170
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
Definition: Type.cpp:3454
QualType withConst() const
Definition: Type.h:1154
void addConst()
Add the const type qualifier to this QualType.
Definition: Type.h:1151
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:1007
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: Type.h:7355
bool isConstant(const ASTContext &Ctx) const
Definition: Type.h:1100
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:7556
QualType getCanonicalType() const
Definition: Type.h:7407
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:7449
bool isMoreQualifiedThan(QualType Other) const
Determine whether this type is more qualified than the other given type, requiring exact equality for...
Definition: Type.h:7527
const Type * getTypePtrOrNull() const
Definition: Type.h:7359
Represents a struct/union/class.
Definition: Decl.h:4169
field_range fields() const
Definition: Decl.h:4375
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:5545
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:3376
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:378
Scope * getBreakParent()
getBreakParent - Return the closest scope that a break statement would be affected by.
Definition: Scope.h:302
bool isOpenMPOrderClauseScope() const
Determine whether this scope is some OpenMP directive with order clause which specifies concurrent sc...
Definition: Scope.h:527
const Scope * getParent() const
getParent - Return the scope that this is nested in.
Definition: Scope.h:267
bool isOpenMPLoopScope() const
Determine whether this scope is a loop having OpenMP loop directive attached.
Definition: Scope.h:520
@ OpenMPOrderClauseScope
This is a scope of some OpenMP directive with order clause which specifies concurrent.
Definition: Scope.h:150
A generic diagnostic builder for errors which may or may not be deferred.
Definition: SemaBase.h:110
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:56
ASTContext & getASTContext() const
Definition: SemaBase.cpp:9
Sema & SemaRef
Definition: SemaBase.h:40
const LangOptions & getLangOpts() const
Definition: SemaBase.cpp:11
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.
OMPClause * ActOnOpenMPNocontextClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nocontext' clause.
OMPClause * ActOnOpenMPXDynCGroupMemClause(Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_dyn_cgroup_mem' clause.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid)
Called at the end of '#pragma omp declare reduction'.
bool isInOpenMPTaskUntiedContext() const
Return true if currently in OpenMP task with untied clause context.
OMPClause * ActOnOpenMPUntiedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'untied' clause.
OMPClause * ActOnOpenMPSafelenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'safelen' 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...
OMPClause * ActOnOpenMPDefaultClause(llvm::omp::DefaultKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'default' clause.
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 ActOnOpenMPDispatchDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp dispatch' after parsing of the.
OMPClause * ActOnOpenMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'read' clause.
OMPClause * ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'filter' clause.
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)
Finish current declare reduction construct initializer.
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...
OMPClause * ActOnOpenMPFullClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-form 'full' clauses.
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.
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.
OMPClause * ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'detach' clause.
OMPClause * ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'use' clause.
OMPClause * ActOnOpenMPFailClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'fail' clause.
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 ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called once a target context is completed, that can be when a '#pragma omp end declare target' was en...
void tryCaptureOpenMPLambdas(ValueDecl *V)
Function tries to capture lambda's captured variables in the OpenMP region before the original lambda...
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.
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...
OMPClause * ActOnOpenMPPrivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'private' clause.
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, SourceLocation StartLoc, DeclarationName VN)
Build the mapper variable of '#pragma omp declare mapper'.
OMPClause * ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc, SourceLocation LParenLoc=SourceLocation(), Expr *NumForLoops=nullptr)
Called on well-formed 'ordered' clause.
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.
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.
OMPClause * ActOnOpenMPIsDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'is_device_ptr' clause.
OMPClause * ActOnOpenMPHasDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'has_device_addr' clause.
StmtResult ActOnOpenMPErrorDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, bool InExContext=true)
Called on well-formed '#pragma omp error'.
OMPClause * ActOnOpenMPPartialClause(Expr *FactorExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'partial' clauses.
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.
OMPClause * ActOnOpenMPLastprivateClause(ArrayRef< Expr * > VarList, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'lastprivate' clause.
void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT, DeclareTargetContextInfo &DTCI)
Called on correct id-expression from the '#pragma omp declare target'.
DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef< OMPClause * > ClauseList)
Called on well-formed '#pragma omp requires'.
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 * ActOnOpenMPFirstprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'firstprivate' clause.
StmtResult ActOnOpenMPDepobjDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp depobj'.
ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK, ExprObjectKind OK, SourceLocation Loc)
OMPClause * ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'priority' clause.
OMPClause * ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, ArrayRef< unsigned > Arguments, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, ArrayRef< SourceLocation > ArgumentsLoc, SourceLocation DelimLoc, SourceLocation EndLoc)
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.
OMPClause * ActOnOpenMPDistScheduleClause(OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'dist_schedule' clause.
OpenMPClauseKind isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, unsigned CapLevel) const
Check if the specified variable is used in 'private' clause.
OMPClause * ActOnOpenMPAllocateClause(Expr *Allocator, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocate' clause.
OMPClause * ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nowait' clause.
OMPClause * ActOnOpenMPNontemporalClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nontemporal' clause.
OMPClause * ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'bind' clause.
OMPClause * ActOnOpenMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'threads' clause.
OMPClause * ActOnOpenMPSharedClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'shared' clause.
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.
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 * ActOnOpenMPCopyinClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyin' clause.
OMPClause * ActOnOpenMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'mergeable' clause.
void startOpenMPCXXRangeFor()
If the current region is a range 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.
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...
OMPClause * ActOnOpenMPAffinityClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Called on well-formed 'affinity' clause.
OMPClause * ActOnOpenMPCompareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'compare' clause.
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.
OMPClause * ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'update' clause.
OMPClause * ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data, Expr *DepModifier, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depend' clause.
OMPClause * ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'doacross' clause.
VarDecl * ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
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...
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'.
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,...
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.
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id, OpenMPDirectiveKind Kind)
Called on correct id-expression from the '#pragma omp threadprivate'.
void ActOnOpenMPEndAssumesDirective()
Called on well-formed '#pragma omp end assumes'.
OMPClause * ActOnOpenMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nogroup' clause.
OMPClause * ActOnOpenMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier, Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'grainsize' clause.
ExprResult ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, Expr *LowerBound, SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length, Expr *Stride, SourceLocation RBLoc)
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.
bool isOpenMPRebuildMemberExpr(ValueDecl *D)
The member expression(this->fd) needs to be rebuilt in the template instantiation to generate private...
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
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.
bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, unsigned OpenMPCaptureLevel) const
Return true if the provided declaration VD should be captured by reference.
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.
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)
Called on well-formed '#pragma omp allocate'.
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind)
Return the number of captured regions created for an OpenMP directive.
bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified variable is captured by 'target' directive.
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...
OMPClause * ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'dynamic_allocators' clause.
StmtResult ActOnOpenMPScopeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scope' after parsing of the associated statement.
void ActOnOpenMPIteratorVarDecl(VarDecl *VD)
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.
bool isInOpenMPDeclareVariantScope() const
Can we exit an OpenMP declare variant scope at the moment.
Definition: SemaOpenMP.h:109
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...
StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp barrier'.
TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D)
Check variable declaration in 'omp declare mapper' construct.
ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc, SourceLocation LLoc, SourceLocation RLoc, ArrayRef< OMPIteratorData > Data)
OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)
Called on well-formed 'uses_allocators' clause.
StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)
End of OpenMP region.
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'.
OMPClause * ActOnOpenMPAcqRelClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acq_rel' clause.
OMPClause * ActOnOpenMPAllocatorClause(Expr *Allocator, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocator' clause.
ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind, bool StrictlyPositive=true, bool SuppressExprDiags=false)
bool isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const
OMPClause * ActOnOpenMPInclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'inclusive' 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...
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...
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 ActOnOpenMPEndDeclareVariant()
Handle a omp end declare variant.
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 ActOnOpenMPMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp masked' after parsing of the.
void ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D)
Act on D, a function definition inside of an omp [begin/end] assumes.
void EndOpenMPDSABlock(Stmt *CurDirective)
Called on end of data sharing attribute block.
OMPClause * ActOnOpenMPOrderClause(OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'order' clause.
OMPClause * ActOnOpenMPSizesClause(ArrayRef< Expr * > SizeExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'sizes' clause.
bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called on the start of target region i.e. '#pragma omp declare target'.
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...
OMPClause * ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'device' clause.
OMPClause * ActOnOpenMPNumThreadsClause(Expr *NumThreads, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_threads' clause.
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.
StmtResult ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp section' after parsing of the associated statement.
bool isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified global variable must be captured by outer capture regions.
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.
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind PrevMappedDirective=llvm::omp::OMPD_unknown)
OMPClause * ActOnOpenMPFlushClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'flush' pseudo clause.
OMPRequiresDecl * CheckOMPRequiresDecl(SourceLocation Loc, ArrayRef< OMPClause * > Clauses)
Check restrictions on Requires directive.
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...
void EndOpenMPClause()
End analysis of clauses.
bool isInOpenMPAssumeScope() const
Check if there is an active global omp begin assumes directive.
Definition: SemaOpenMP.h:241
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...
OMPClause * ActOnOpenMPNumTeamsClause(Expr *NumTeams, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_teams' clause.
QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare mapper' construct.
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.
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.
OMPClause * ActOnOpenMPMessageClause(Expr *MS, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'message' 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 * 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.
StmtResult ActOnOpenMPScanDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scan'.
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.
void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init)
Check if the current region is an OpenMP loop region and if it is, mark loop control variable,...
OMPClause * ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
void DiagnoseUnterminatedOpenMPDeclareTarget()
Report unterminated 'omp declare target' or 'omp begin declare target' at the end of a compilation un...
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...
OMPClause * ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'simdlen' clause.
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...
OMPClause * ActOnOpenMPUseDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_ptr' 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.
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
Definition: SemaOpenMP.h:53
OMPClause * ActOnOpenMPReleaseClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'release' clause.
OMPClause * ActOnOpenMPAcquireClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acquire' clause.
OMPClause * ActOnOpenMPProcBindClause(llvm::omp::ProcBindKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'proc_bind' clause.
OMPClause * ActOnOpenMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'simd' clause.
OMPClause * ActOnOpenMPXBareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_bare' clause.
StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt)
Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to an OpenMP loop directive.
OMPClause * ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'hint' clause.
OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
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...
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.
OMPClause * ActOnOpenMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'capture' clause.
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.
StmtResult ActOnOpenMPAtomicDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp atomic' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target update'.
StmtResult ActOnOpenMPOrderedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp ordered' after parsing of the associated statement.
ExprResult ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > Brackets)
OMPClause * ActOnOpenMPAtClause(OpenMPAtClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'at' clause.
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 * ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'init' clause.
OMPClause * ActOnOpenMPUseDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_addr' clause.
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
std::pair< StringRef, QualType > CapturedParamNameType
Definition: SemaOpenMP.h:54
OMPClause * ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'final' clause.
bool isInOpenMPTargetExecutionDirective() const
Return true inside OpenMP target region.
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.
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.
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...
StmtResult ActOnOpenMPFlushDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp flush'.
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.
OMPClause * ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'num_tasks' clause.
void ActOnOpenMPDeclareTargetInitializer(Decl *D)
Adds OMPDeclareTargetDeclAttr to referenced variables in declare target directive.
bool isInOpenMPDeclareTargetContext() const
Return true inside OpenMP declare target region.
Definition: SemaOpenMP.h:369
StmtResult ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancellation point'.
OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef< Expr * > Vars, const OMPVarListLocTy &Locs, OpenMPVarListDataTy &Data)
void startOpenMPLoop()
If the current region is a loop-based region, mark the start of the loop construct.
StmtResult ActOnOpenMPTargetDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target' 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.
OMPThreadPrivateDecl * CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef< Expr * > VarList)
Builds a new OpenMPThreadPrivateDecl and checks its correctness.
OMPClause * ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'severity' clause.
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.
void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, VarDecl *OmpPrivParm)
Finish current declare reduction construct initializer.
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 * ActOnOpenMPDefaultmapClause(OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'defaultmap' clause.
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.
StmtResult ActOnOpenMPTaskwaitDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskwait'.
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.
OMPClause * ActOnOpenMPRelaxedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'relaxed' clause.
OMPClause * ActOnOpenMPAlignedClause(ArrayRef< Expr * > VarList, Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'aligned' clause.
StmtResult ActOnOpenMPInteropDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp interop'.
OMPClause * ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depobj' pseudo clause.
OMPClause * ActOnOpenMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'seq_cst' clause.
void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, SourceLocation IdLoc=SourceLocation())
Check declaration inside target region.
OMPClause * ActOnOpenMPNovariantsClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'novariants' clause.
OMPClause * ActOnOpenMPCopyprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyprivate' clause.
OMPClause * ActOnOpenMPCollapseClause(Expr *NumForLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'collapse' clause.
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.
ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc, Expr *Op)
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.
OMPClause * ActOnOpenMPAlignClause(Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'align' clause.
OMPClause * ActOnOpenMPAtomicDefaultMemOrderClause(OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'atomic_default_mem_order' clause.
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 * ActOnOpenMPWeakClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'weak' clause.
OMPClause * ActOnOpenMPXAttributeClause(ArrayRef< const Attr * > Attrs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_attribute' clause.
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.
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.
StmtResult ActOnOpenMPParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel' after parsing of the associated statement.
StmtResult ActOnOpenMPSingleDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp single' after parsing of the associated statement.
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.
const ValueDecl * getOpenMPDeclareMapperVarName() const
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...
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed '#pragma omp threadprivate'.
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope)
Initialization of captured region for OpenMP region.
NamedDecl * lookupOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)
Searches for the provided declaration name for OpenMP declare target directive.
OMPClause * ActOnOpenMPExclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'exclusive' clause.
OMPClause * ActOnOpenMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'write' clause.
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.
void ActOnOpenMPAssumesDirective(SourceLocation Loc, OpenMPDirectiveKind DKind, ArrayRef< std::string > Assumptions, bool SkippedClauses)
Called on well-formed '#pragma omp [begin] assume[s]'.
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...
void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI)
Handle a omp begin declare variant.
StmtResult ActOnOpenMPLoopnest(Stmt *AStmt)
Process a canonical OpenMP loop nest that can either be a canonical literal loop (ForStmt or CXXForRa...
OMPClause * ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'reverse_offload' clause.
OMPClause * ActOnOpenMPThreadLimitClause(Expr *ThreadLimit, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'thread_limit' clause.
StmtResult ActOnOpenMPTaskDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp task' after parsing of the associated statement.
OMPClause * ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation NameModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'if' clause.
llvm::SmallDenseMap< const ValueDecl *, const Expr *, 4 > VarsWithInheritedDSAType
Definition: SemaOpenMP.h:408
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...
const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective()
Called at the end of target region i.e. '#pragma omp end declare target'.
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 * ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc)
StmtResult ActOnOpenMPCancelDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancel'.
StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskyield'.
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.
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'.
A RAII object to enter scope of a compound statement.
Definition: Sema.h:865
Expr * get() const
Definition: Sema.h:5827
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition: Sema.h:9547
Abstract base class used for diagnosing integer constant expression violations.
Definition: Sema.h:5776
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:457
ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo)
Package the given type and TSI into a ParsedType.
Definition: SemaType.cpp:6794
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition: Sema.h:698
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:1583
ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val)
Definition: SemaExpr.cpp:3848
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:15753
void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath)
ExprResult IgnoredValueConversions(Expr *E)
IgnoredValueConversions - Given that an expression's result is syntactically ignored,...
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition: Sema.h:7376
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
Definition: Sema.h:7417
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
Definition: Sema.h:7419
@ LookupAnyName
Look up any declaration with any name.
Definition: Sema.h:7421
ImplicitConversionSequence TryImplicitConversion(Expr *From, QualType ToType, bool SuppressUserConversions, AllowedExplicit AllowExplicit, bool InOverloadResolution, bool CStyle, bool AllowObjCWritebackConversion)
SemaOpenMP & OpenMP()
Definition: Sema.h:1013
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
Definition: Sema.h:3505
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl=nullptr, ExpressionEvaluationContextRecord::ExpressionKind Type=ExpressionEvaluationContextRecord::EK_Other)
Definition: SemaExpr.cpp:17673
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:20639
SmallVector< sema::FunctionScopeInfo *, 4 > FunctionScopes
Stack containing information about each of the nested function, block, and method scopes that are cur...
Definition: Sema.h:807
@ AR_inaccessible
Definition: Sema.h:1074
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:2245
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...
NamedDecl * HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists)
Definition: SemaDecl.cpp:6360
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:17458
FPOptionsOverride CurFPFeatureOverrides()
Definition: Sema.h:1420
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:20424
NamedDecl * LookupSingleName(Scope *S, DeclarationName Name, SourceLocation Loc, LookupNameKind NameKind, RedeclarationKind Redecl=RedeclarationKind::NotForRedeclaration)
Look up a name, looking for a single declaration.
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:1499
ExprResult PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter)
Perform a contextual implicit conversion.
ASTContext & Context
Definition: Sema.h:858
void ActOnCapturedRegionError()
Definition: SemaStmt.cpp:4929
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
Definition: SemaDecl.cpp:66
@ AllowFold
Definition: Sema.h:5792
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
Definition: SemaDecl.cpp:1521
void CleanupVarDeclMarking()
Definition: SemaExpr.cpp:19903
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
Definition: SemaExpr.cpp:762
ASTContext & getASTContext() const
Definition: Sema.h:527
ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:16032
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:19194
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:20154
void PopExpressionEvaluationContext()
Definition: SemaExpr.cpp:18099
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition: Sema.h:775
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
Definition: SemaExpr.cpp:2206
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...
void PushFunctionScope()
Enter a new function scope.
Definition: Sema.cpp:2126
const LangOptions & getLangOpts() const
Definition: Sema.h:520
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...
Preprocessor & PP
Definition: Sema.h:857
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:6651
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.
void CheckExtraCXXDefaultArguments(Declarator &D)
CheckExtraCXXDefaultArguments - Check for any extra default arguments in the declarator,...
const LangOptions & LangOpts
Definition: Sema.h:856
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
Definition: Sema.cpp:2360
DeclContext * getCurLexicalContext() const
Definition: Sema.h:702
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...
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
Definition: SemaCast.cpp:3340
void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, CapturedRegionKind Kind, unsigned NumParams)
Definition: SemaStmt.cpp:4840
sema::FunctionScopeInfo * getCurFunction() const
Definition: Sema.h:892
Expr * BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit)
Build a CXXThisExpr and mark it referenced in the current context.
ExprResult DefaultLvalueConversion(Expr *E)
Definition: SemaExpr.cpp:651
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
Definition: Sema.h:11732
FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, bool Final=false)
Definition: SemaDecl.cpp:20659
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
Definition: Sema.cpp:2316
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition: Sema.h:996
StmtResult ActOnCapturedRegionEnd(Stmt *S)
Definition: SemaStmt.cpp:4944
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E)
Definition: SemaExpr.cpp:4339
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
Definition: SemaExpr.cpp:21227
bool inTemplateInstantiation() const
Determine whether we are currently performing template instantiation.
Definition: Sema.h:10484
@ TryCapture_ExplicitByVal
Definition: Sema.h:5277
@ AA_Initializing
Definition: Sema.h:5201
@ AA_Converting
Definition: Sema.h:5200
@ AA_Casting
Definition: Sema.h:5203
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:11293
ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, Expr *CondExpr, Expr *LHSExpr, Expr *RHSExpr)
ActOnConditionalOp - Parse a ?: operation.
Definition: SemaExpr.cpp:9166
ExprResult PerformImplicitConversion(Expr *From, QualType ToType, const ImplicitConversionSequence &ICS, AssignmentAction Action, CheckedConversionKind CCK=CheckedConversionKind::Implicit)
PerformImplicitConversion - Perform an implicit conversion of the expression From to the type ToType ...
bool isCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind=CompleteTypeKind::Default)
Definition: Sema.h:11707
@ CTK_ErrorRecovery
Definition: Sema.h:7605
void setFunctionHasBranchProtectedScope()
Definition: Sema.cpp:2301
RedeclarationKind forRedeclarationInCurContext() const
std::pair< StringRef, QualType > CapturedParamNameType
Definition: Sema.h:8685
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:290
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
Definition: SemaExpr.cpp:5356
@ 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),...
TypeSourceInfo * GetTypeForDeclarator(Declarator &D)
GetTypeForDeclarator - Convert the type for the specified declarator to Type instances.
Definition: SemaType.cpp:6122
void diagnoseTypo(const TypoCorrection &Correction, const PartialDiagnostic &TypoDiag, bool ErrorRecovery=true)
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
Definition: SemaStmt.cpp:78
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Definition: SemaType.cpp:9276
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
Definition: Sema.h:830
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
Definition: SemaInternal.h:24
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
void DiscardCleanupsInEvaluationContext()
Definition: SemaExpr.cpp:18177
void PushDeclContext(Scope *S, DeclContext *DC)
Set the current declaration context until it gets popped.
Definition: SemaDecl.cpp:1328
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)
void PopDeclContext()
Definition: SemaDecl.cpp:1335
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:1605
void ActOnUninitializedDecl(Decl *dcl)
Definition: SemaDecl.cpp:14062
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
Definition: SemaDecl.cpp:13502
SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD=nullptr)
Definition: Sema.cpp:1899
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr)
Definition: SemaExpr.cpp:15596
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:15065
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:2331
sema::CapturedRegionScopeInfo * getCurCapturedRegion()
Retrieve the current captured region, if any.
Definition: Sema.cpp:2700
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:3222
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
Definition: SemaStmt.cpp:414
FullExprArg MakeFullExpr(Expr *Arg)
Definition: Sema.h:5841
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition: Sema.h:6733
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:1540
bool isVLASupported() const
Whether target supports variable-length arrays.
Definition: TargetInfo.h:1551
A semantic tree transformation that allows one to transform one abstract syntax tree into another.
Represents a declaration of a type.
Definition: Decl.h:3391
SourceLocation getBeginLoc() const
Get the begin source location.
Definition: TypeLoc.cpp:192
A container of type source information.
Definition: Type.h:7326
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition: TypeLoc.h:256
QualType getType() const
Return the type wrapped by this type source info.
Definition: Type.h:7337
The base class of the type hierarchy.
Definition: Type.h:1813
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1870
bool isConstantArrayType() const
Definition: Type.h:7678
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:2009
bool isArrayType() const
Definition: Type.h:7674
bool isArithmeticType() const
Definition: Type.cpp:2269
bool isPointerType() const
Definition: Type.h:7608
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: Type.h:7941
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:8186
bool isReferenceType() const
Definition: Type.h:7620
bool isEnumeralType() const
Definition: Type.h:7706
bool isScalarType() const
Definition: Type.h:8000
bool isVariableArrayType() const
Definition: Type.h:7686
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
Definition: Type.cpp:2046
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:694
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
Definition: Type.cpp:2224
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
Definition: Type.h:7895
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition: Type.h:2657
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition: Type.h:7870
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2649
bool isAnyComplexType() const
Definition: Type.h:7710
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
Definition: Type.h:2320
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition: Type.cpp:2174
bool isFunctionProtoType() const
Definition: Type.h:2490
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
Definition: Type.h:8042
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition: Type.h:2667
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition: Type.h:8172
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition: Type.cpp:2350
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
Definition: Type.h:8136
bool isFunctionType() const
Definition: Type.h:7604
bool isStructureOrClassType() const
Definition: Type.cpp:646
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:2254
bool isFloatingType() const
Definition: Type.cpp:2237
bool isAnyPointerType() const
Definition: Type.h:7612
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8119
bool isRecordType() const
Definition: Type.h:7702
bool isUnionType() const
Definition: Type.cpp:660
bool isFunctionNoProtoType() const
Definition: Type.h:2489
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition: Type.cpp:1874
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:2183
Expr * getSubExpr() const
Definition: Expr.h:2228
Opcode getOpcode() const
Definition: Expr.h:2223
static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent)
Definition: ExprCXX.cpp:372
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:1254
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition: Decl.h:1549
TLSKind getTLSKind() const
Definition: Decl.cpp:2165
bool hasInit() const
Definition: Decl.cpp:2395
void setInitStyle(InitializationStyle Style)
Definition: Decl.h:1432
InitializationStyle getInitStyle() const
The style of initialization for this declaration.
Definition: Decl.h:1446
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:1270
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition: Decl.h:1213
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition: Decl.h:1195
bool isFileVarDecl() const
Returns true for file scoped variable declaration.
Definition: Decl.h:1329
const Expr * getInit() const
Definition: Decl.h:1355
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition: Decl.h:1171
@ 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:1282
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
Definition: Decl.h:1240
bool isDirectInit() const
Whether the initializer is a direct-initializer (list or call).
Definition: Decl.h:1451
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
Definition: Decl.h:1216
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition: Decl.h:1155
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:1249
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Definition: Decl.h:1345
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:882
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.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
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:55
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
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
static constexpr StringRef getOpenMPVariantManglingSeparatorStr()
OpenMP variants are mangled early based on their OpenMP context selector.
Definition: Decl.h:5048
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:328
@ 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
for(const auto &A :T->param_types())
const FunctionProtoType * T
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
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
@ Implicit
An implicit conversion.
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 true
Definition: stdbool.h:21
#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:4731
llvm::SmallVector< Expr *, 4 > PreferTypes
Definition: OpenMPKinds.h:232
Iterator definition representation.
Definition: ExprOpenMP.h:160
Helper expressions and declaration for OMPIteratorExpr class for each iteration space.
Definition: ExprOpenMP.h:111
Expr * CounterUpdate
Updater for the internal counter: ++CounterVD;.
Definition: ExprOpenMP.h:121
Expr * Upper
Normalized upper bound.
Definition: ExprOpenMP.h:116
Expr * Update
Update expression for the originally specified iteration variable, calculated as VD = Begin + Counter...
Definition: ExprOpenMP.h:119
VarDecl * CounterVD
Internal normalized counter.
Definition: ExprOpenMP.h:113
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: SemaOpenMP.h:314
OpenMPDirectiveKind Kind
The directive kind, begin declare target or declare target.
Definition: SemaOpenMP.h:311
OMPDeclareTargetDeclAttr::DevTypeTy DT
The 'device_type' as parsed from the clause.
Definition: SemaOpenMP.h:308
SourceLocation Loc
The directive location.
Definition: SemaOpenMP.h:317
llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped
Explicitly listed variables and functions in a 'to' or 'link' clause.
Definition: SemaOpenMP.h:305
Data structure for iterator expression.
Definition: SemaOpenMP.h:1337
Data used for processing a list of variables in OpenMP clauses.
Definition: SemaOpenMP.h:1082
Data for list of allocators.
Definition: SemaOpenMP.h:1277
Expr * AllocatorTraits
Allocator traits.
Definition: SemaOpenMP.h:1281
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Definition: SemaOpenMP.h:1283
Clang specific specialization of the OMPContext to lookup target features.